前端优化 - 资源预加载技术(Prefetch, Preload, DNS-Prefetch,defer和async)

前言


当提到前端性能优化时,我们首先会联想到文件的合并、压缩,文件缓存和开启服务器端的 gzip 压缩等,这使得页面加载更快,用户可以尽快使用我们的 Web 应用来达到他们的目标。

资源预加载是另一个性能优化技术,我们可以使用该技术来预先告知浏览器某些资源可能在将来会被使用到。

引用 Patrick Hamann 的解释:

预加载是浏览器对将来可能被使用资源的一种暗示,一些资源可以在当前页面使用到,一些可能在将来的某些页面中被使用。作为开发人员,我们比浏览器更加了解我们的应用,所以我们可以对我们的核心资源使用该技术。

Prefetch


浏览器会在遇到如下link标签时,立刻开始下载main.js(不阻塞parser),并放在内存中,但不会执行其中的JS语句。
只有当遇到script标签加载的也是main.js的时候,浏览器才会直接将预先加载的JS执行掉。



Preload


浏览器会在空闲的时候,下载main.js, 并缓存到disk。当有页面使用的时候,直接从disk缓存中读取。其实就是把决定是否和什么时间加载这个资源的决定权交给浏览器。

如果prefetch还没下载完之前,浏览器发现script标签也引用了同样的资源,浏览器会再次发起请求,这样会严重影响性能的,加载了两次,,所以不要在当前页面马上就要用的资源上用prefetch,要用preload。


DNS 预解析 DNS-Prefetch

通过 DNS 预解析来告诉浏览器未来我们可能从某个特定的 URL 获取资源,当浏览器真正使用到该域中的某个资源时就可以尽快地完成 DNS 解析。例如,我们将来可能从 example.com 获取图片或音频资源,那么可以在文档顶部的 标签中加入以下内容:


当我们从该 URL 请求一个资源时,就不再需要等待 DNS 的解析过程。该技术对使用第三方资源特别有用。

在 Harry Roberts 的文章中提到:

通过简单的一行代码就可以告知那些兼容的浏览器进行 DNS 预解析,这意味着当浏览器真正请求该域中的某个资源时,DNS 的解析就已经完成了。

这似乎是一个非常微小的性能优化,显得也并非那么重要,但事实并非如此 – Chrome 一直都做了类似的优化。当在浏览器的地址栏中输入 URL 的一小段时,Chrome 就自动完成了 DNS 预解析(甚至页面预渲染),从而为每个请求节省了至关重要的时间。

defer和async


defer和async是script标签的两个属性,用于在不阻塞页面文档解析的前提下,控制脚本的下载和执行。
defer,async与下载时机也有关,具体看这张图。
前端优化 - 资源预加载技术(Prefetch, Preload, DNS-Prefetch,defer和async)_第1张图片
defer的执行时间是在所有元素解析完成之后,DOMContentLoaded 事件触发之前。

async的执行时间是在当前JS脚本下载完成后,所以多个async script是执行顺序是不固定的。async只能用于加载一些独立无依赖的代码,比如Google Analysis之类。

实例解析





  
  Faster
  
  
  
  

  








首先,Parser在遇到head中preload时开始下载JS,读到script标签的时候,如果已经下载完了,直接按顺序执行之。如果没下载完,则会等到下载完再执行。这样就可以在刚进入页面时开始非阻塞的下载JS代码了。

其次,页面会在空闲时,加载prefetch的JS,如果之后页面发生跳转,跳转的目标页面引入了prefetch.js,浏览器会直接从disk缓存中读取执行。

将script标签依然放在之前,并增加defer标签,确保老浏览器兼容,并在所有DOM元素解析完成之后执行其中的代码。

至此,完美的HTML结构出炉了。

CSS的下载和解析一样会阻塞渲染,造成白屏,CSS中的字体文件更是影响首屏渲染关键因素之一。

参考


带你玩转prefetch, preload, dns-prefetch,defer和async
前端性能优化 - 资源预加载
浏览器结构解析

你可能感兴趣的:(网站架构与性能优化)