如何控制Web资源加载的优先级?
使用 Proload/Prefetch 优化你的应用
Web 性能优化:Preload,Prefetch的使用及在 Chrome 中的优先级

prefeth/preload

  1. <link href="/heopappmgr-web/static/js/chunk-59db8fdf.3f177dca.js" rel="prefetch">
  2. <link href="/heopappmgr-web/static/js/app.117e76b3.js" rel="preload" as="script">

preload 提前加载
preload 顾名思义就是一种预加载的方式,它通过声明向浏览器声明一个需要提交加载的资源,当资源真正被使用的时候立即执行,就无需等待网络的消耗。

preload link必须设置as属性来声明资源的类型(font/image/style/script等),否则浏览器可能无法正确加载资源。

prefetch 预判加载
prefetch 跟 preload 不同,它的作用是告诉浏览器未来可能会使用到的某个资源,浏览器就会在闲时去加载对应的资源,即浏览器在空闲时间预先加载资源,真正使用时直接从浏览器缓存中快速获取。
image.png

vue-cli的默认配置

默认情况下,一个 Vue CLI 应用会为所有初始化渲染需要的文件自动生成 preload 提示。
这些提示会被 @vue/preload-webpack-plugin 注入,并且可以通过 chainWebpack 的config.plugin(‘preload’) 进行修改和删除

默认情况下,一个 Vue CLI 应用会为所有作为 async chunk 生成的 JavaScript 文件 (通过动态import()按需 code splitting 的产物) 自动生成 prefetch 提示。
这些提示会被 @vue/preload-webpack-plugin 注入,并且可以通过 chainWebpack 的 config.plugin(‘prefetch’) 进行修改和删除。

Prefetch 链接将会消耗带宽。如果你的应用很大且有很多 async chunk,而用户主要使用的是对带宽较敏感的移动端,那么你可能需要关掉 prefetch 链接并手动选择要提前获取的代码区块。

不同资源浏览器优先级

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

  • Highest 最高
  • High 高
  • Medium 中等
  • Low 低
  • Lowest 最低


从图中可以看出:(以 Blink 为例)

  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

资源加载的优先级 - 图3
使用 async/defer 属性在加载脚本的时候不阻塞 HTML 的解析,

  • defer 加载脚本执行会在所有元素解析完成,DOMContentLoaded 事件触发之前完成执行。它的用途其实跟 preload 十分相似。

你可以使用 defer 加载脚本在 head 末尾,这比将脚本放在 body 底部效果来的更好。

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