本文已参与「新人创作礼」活动,一起开启掘金创作之路。
为什么需要预加载?
浏览器同时发出并发请求数是有限制的,受最大tcp连接数限制,单个tcp连接,在同一时间只能处理一个http请求(只的是http/1.1,http2支持多路复用),请求一般像Chrome为6个,因此资源获取的时机以及优先级便尤为重要。
Link 标签 rel="preload"
该属性可以指明哪些资源是在页面加载完成后即刻需要的。对于这种即刻需要的资源,你可能希望在页面加载的生命周期的早期阶段就开始获取,在浏览器的主渲染机制介入前就进行预加载。这一机制使得资源可以更早的得到加载并可用,且更不易阻塞页面的初步渲染,进而提升性能。
<link href="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.js" rel='preload' as='script'/>
通过 HTTP header 方式:
Link: <https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.js>; rel=preload; as=script
除了rel之外还需要通过href和as属性指定需要被预加载资源的资源路径及其类型。
as属性的作用
as属性是必须要设置的,使用as来指定将要预加载的内容的类型,将使得浏览器能够:
- 更精确地优化资源加载优先级。
- 匹配未来的加载需求,在适当的情况下,重复利用同一资源。
- 为资源应用正确的内容安全策略。
- 为资源设置正确的
Accept请求头。
如果未设置或者设置错误as属性,则将不能提高其加载优先级
哪些资源可以被预加载?
- audio: 音频文件。
- document: 一个将要被嵌入到
<frame>或<iframe>内部的HTML文档。 - embed: 一个将要被嵌入到
<embed>元素内部的资源。 - fetch: 那些将要通过
fetch和XHR请求来获取的资源,比如一个ArrayBuffer或JSON文件。 - font: 字体文件。
- image: 图片文件。
- object: 一个将会被嵌入到元素内的文件。
- script: JavaScript文件。
- style: 样式表。
- track: WebVTT文件。
- worker: 一个JavaScript的
web worker或shared worker。 - video: 视频文件。
Link 标签 rel="prefetch"
**页面资源预加载(Link prefetch)**是浏览器提供的一个技巧,目的是:让浏览器在空闲时间下载或预读取一些文档资源,用户在将来将会访问这些资源。一个 Web 页面可以对浏览器设置一系列的预加载指示,当浏览器加载完当前页面后,它会在后台静悄悄的加载指定的文档,并把它们存储在缓存里。当用户访问到这些预加载的文档后,浏览器能快速的从缓存里提取给用户。优先级会低于preload
<link rel="prefetch" href="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.js">
资源正在被加载时点击了某个链接
当用户点击一个连接,或开始任何形式的页面加载时,预取操作将被停止且任何预取提示将被丢弃。如果一个预取文档只下载了一部分,那么这部分文档将被保存在缓存中,供服务端发送一个 "Accept-Ranges: bytes" 的返回头。这个返回头通常是由网络服务器在返回静态内容时生成的。当用户真正访问这个已经(部分)预载过的文档时,该文档的剩余部分将被通过一个 HTTP byte-range 的请求获取。
Link 标签 rel="prerender"
这是一个重量级的选项,它可以让浏览器提前加载指定页面的所有资源。
<link rel="prerender" href="/nextpage.html"/>
要小心的使用
prerender,因为它将会加载很多资源并且可能造成带宽的浪费,尤其是在移动设备上。还要注意的是
Link 标签 rel="subresource"
被Chrome支持了有一段时间,已经移除不必关注,并且已经有些搔到预加载当前导航/页面(所含有的资源)的痒处了。但它有一个问题——没有办法处理所获取内容的优先级(as也并不存在),所以最终,这些资源会以一个相当低的优先级被加载,这使得它能提供的帮助相当有限。
webpack中的使用
利用
import()动态加载脚本并设置魔法注释实现
const NotFound = asyncLoad(() => import(/*webpackPrefetch: true */'pages/not-found'));
const NotFound = asyncLoad(() => import(/*webpackPreload: true */'pages/not-found'));
利用
preload-webpack-plugin
参考链接