前端性能优化-preload、prefetch和defer、async

avatar

前端性能优化-preload、prefetch和defer、async

preload

表示用户十分有可能需要在当前浏览中加载目标资源,所以浏览器必须预先获取和缓存对应资源且更不易阻塞页面的初步渲染进而提升性能
它可以通过 Link 标签进行创建:

1
2
3
4
5
<!-- as属性在下面讲解 -->
<link rel="preload" href="/path/to/style.css" as="style">

<!-- HTTP 响应头模式 -->
Link: <https://example.com/other/styles.css>; rel=preload; as=style

这种方式比通过 Link 方式加载资源方式更快,请求在返回还没到解析页面的时候就已经开始预加载资源了

preload兼容性

preload兼容性

prefetch

它的作用是告诉浏览器未来可能会使用到的某个资源,浏览器就会在闲时去加载对应的资源,若能预测到用户的行为,比如懒加载,点击到其它页面等则相当于提前预加载了需要的资源。
它同样可以通过 Link 标签进行创建:

1
2
3
4
5
<!-- as属性在下面讲解 -->
<link rel="prefetch" href="/images/big.jpeg">

<!-- HTTP 响应头模式 -->
Link: <https://example.com/other/styles.css>; rel=prefetch; as=style

prefetch兼容性

prefetch兼容性

link标签上的as属性与加载的优先级

一个资源的加载的优先级被分为五个级别,分别是:

  • Highest 最高
  • High 高
  • Medium 中等
  • Low 低
  • Lowest 最低
  1. HTML/CSS 资源,其优先级是最高的
  2. font 字体资源,优先级分别为 Highest/High
  3. 图片资源,如果出现在视口中,则优先级为 High,否则为 Low
    而 script 脚本资源就比较特殊,优先级不一,脚本根据它们在文件中的位置是否异步、延迟或阻塞获得不同的优先级:
  • 网络在第一个图片资源之前阻塞的脚本在网络优先级中是 High
  • 网络在第一个图片资源之后阻塞的脚本在网络优先级中是 Medium
  • 异步/延迟/插入的脚本(无论在什么位置)在网络优先级中是 Low

自己网站资源优先级也可以通过 Chrome 控制台 Network 一栏进行查看.

  1. 对于使用 prefetch 获取资源,其优先级默认为最低,Lowest,可以认为当浏览器空闲的时候才会去获取的资源。
  2. 而对于 preload 获取资源,可以通过 “as” 或者 “type” 属性来标识他们请求资源的优先级(比如说 preload 使用 as=”style” 属性将获得最高的优先级,即使资源不是样式文件)
  3. 没有 “as” 属性的将被看作异步请求。

async/defer

async&defer

async与defer是针对 script 标签而言的,他是 script 标签上的html属性

async: 对于普通脚本,如果存在 async 属性,那么普通脚本会被并行请求,并尽快解析和执行。

defer: 这个布尔属性被设定用来通知浏览器该脚本将在文档完成解析后,触发 DOMContentLoaded 事件前执行。有 defer 属性的脚本会阻止 DOMContentLoaded 事件,直到脚本被加载并且解析完成

使用 async/defer 属性在加载脚本的时候不阻塞 HTML 的解析,defer 加载脚本执行会在所有元素解析完成,DOMContentLoaded 事件触发之前完成执行。它的用途其实跟 preload 十分相似。你可以使用 defer 加载脚本在 head 末尾,这比将脚本放在 body 底部效果来的更好.

  1. 它相比于 preload 加载的优势在于浏览器兼容性好,从 caniuse 上看基本上所有浏览器都支持,覆盖率达到 93%,
  2. 不足之处在于:defer 只作用于脚本文件,对于样式、图片等资源就无能为力了,并且 defer 加载的资源是要执行的,而 preload 只下载资源并不执行,待真正使用到才会执行文件。
  3. 对于页面上主/首屏脚本,可以直接使用 defer 加载,而对于非首屏脚本/其它资源,可以采用 preload/prefeth 来进行加载

实际使用案例

  1. 提前加载字体文件。由于字体文件必须等到 CSSOM 构建完成并且作用到页面元素了才会开始加载,会导致页面字体样式闪动。所以要用 preload 显式告诉浏览器提前加载。假如字体文件在 CSS 生效之前下载完成,则可以完全消灭页面闪动效果。
  2. 使用 preload 预加载第二屏的内容,在网页开发中,对于非首屏部分采用懒加载是我们页面常用的优化手段,所以我们在页面 onload 之后可以通过 preload 来加载次屏所需要的资源,在用户浏览完首屏内容滚动时能够更快地看到次屏的内容。
  3. 在页面加载完成之后,可以分析页面上所有的链接,判断用户可能会点击的页面,分析提取下一跳页面上所有的资源使用 prefetch 进行加载(这里不使用 preload,因为不一定会点击),浏览器会在空闲地时候进行加载,当用户点击链接命中了缓存,这可以有效地提升下一页面的首屏渲染时间。
  4. 对于商品列表页面,在用户鼠标停留在某个商品的时候,可以去分析商品详情页所需要的资源并提前开启 preload 加载,跟第 3 点类似,都是用来预测用户的行为并且做出一些预加载的手段,区别在于当用户停留在商品上时,点击命中率更高,preload 可以立即加载资源,有效提升缓存命中率。

参考链接: