![](/assets/img/weixin-blog.311ae013.png)
# 预加载资源 preload
TIP
- preload:以高优先级为当前页面加载资源;(预加载)
preload 的资源应该在当前页面立即使用,如果不加上 script 标签执行预加载的资源,控制台中会显示警告,提示预加载的资源在当前页面没有被引用;
**使用 preload 时,应配合 as 属性,表示该资源的优先级,使用 as="style" 属性将获得最高的优先级,as ="script"将获得低优先级或中优先级,其他可以取的值有font/image/audio/video; **
- prefetch:以低优先级为后面的页面加载未来需要的资源,只会在空闲时才去加载;(预拉取)
prefetch 的目的是取未来会使用的资源,所以当用户从 A 页面跳转到 B 页面时,进行中的 preload 的资源会被中断,而 prefetch 不会; preload 字体时要加上crossorigin属性,即使没有跨域,否则会重复加载:
此文章,旨在个人记录使用。文章摘录自:用 preload 预加载页面资源 (opens new window) 和link 预加载详解 (opens new window)
优化下一个页面显示的其中一个步骤,是可以在当前页面提前加载资源。包括css
/'js'/'image'等。这时我们就可以使用到preload
了。
preload 提供了一种声明式的命令,让浏览器提前加载指定资源(加载后并不执行),在需要执行的时候再执行。提供的好处主要是
- 将加载和执行分离开,可不阻塞渲染和 document 的 onload 事件
- 提前加载指定资源,不再出现依赖的 font 字体隔了一段时间才刷出
# 一、如何使用 preload?
<!-- 使用 link 标签静态标记需要预加载的资源 -->
<link rel="preload" href="/path/to/style.css" as="style" />
<!-- 或使用脚本动态创建一个 link 标签后插入到 head 头部 -->
<script>
const link = document.createElement("link");
link.rel = "preload";
link.as = "style";
link.href = "/path/to/style.css";
document.head.appendChild(link);
</script>
说明:preload 不仅仅支持 css 的预加载,上述只是使用 css,作为样例。那么具体支持哪些呢?
# 二、注意事项
避免滥用 preload: 若不确定资源是必定会加载的,则不要错误使用 preload,以免本末倒置,给页面带来更沉重的负担。
避免混用 preload 和 prefetch preload 和 prefetch 混用的话,并不会复用资源,而是会重复加载。
避免错用 preload 加载跨域资源。 crossorigin 属性在加载字体的时候是必须的,即便字体没有跨域是在自己公司的服务器上,因为用户代理必须采用匿名模式来获取字体资源。为什么?请见这里 (opens new window)和阿里:preload 预加载资源 (opens new window)
# 三、不同资源加载的优先级规则
我们先来看一张图:
一共分成五个级别:
- Highest 最高
- Hight 高
- Medium 中等
- Low 低
- Lowest 最低
# html 主要资源,其优先级是最高的
# css 样式资源,其优先级也是最高的
# script 脚本资源,优先级不一
前三个 js 文件是写死在 html 中的静态资源依赖,后三个 js 文件是根据首屏按需异步加载的组件资源依赖,这正验证了这个规则。
# font 字体资源,优先级不一
css 样式文件中有一个 @font-face 依赖一个 font 文件,样式文件中依赖的字体文件加载的优先级是 Highest;
在使用 preload 预加载这个 font 文件时,若不指定 crossorigin 属性(即使同源),则会采用匿名模式的 CORS 去加载,优先级是 High
看下图对比:
第一条 High 优先级,也就是 preload 的请求:
第二条 Highest 也就是样式引入的请求:
可以看到,在 preload
的请求中,缺少了一个 origin
的请求头字段,表示这个请求是匿名的请求
。
让这两个请求能共用缓存的话,目前的解法是给 preload 加上 crossorigin 属性,这样请求头会带上 origin, 且与样式引入的请求同源,从而做到命中缓存:
<link rel="preload" as="font" crossorigin href="https://at.alicdn.com/t/font_zck90zmlh7hf47vi.woff" />
# 四、预加载使用场景
# 字体提前加载
eb 字体是较晚才能被发现的关键资源中常见的一种。但是在用户体验对前端来说至关重要的现阶段前端开发来说,web 字体对页面的渲染也是至关重要。字体的引用被深埋在 css 中,即便预加载器有提前解析 css,也无法确定包含字体信息的选择器是否会真正作用在 dom 节点上。所以为了减少 FOUT(无样式字体闪烁,flash of unstyled text )需要预加载字体文件,有了 preload,一行代码搞定。
<link rel="preload" href="font.woff2" as="font" type="font/woff2" crossorigin />
注意:
crossorigin
属性在加载字体的时候是必须的,即便字体没有跨域是在自己公司的服务器上,因为用户代理必须采用匿名模式来获取字体资源(为什么会这样呢?)。
# 动态加载,但不执行
通常我们可能想在当前页去加载下一页的资源,但是在媒婆 preload 的情况下,我们常常使用动态创建 script 标签的形式,但是动态创建 script 标签的话,js 代码会立即执行。在有了preload
之后,就可以做到动态加载,延迟执行。
let link = document.createElement("link");
link.href = "myscript.js";
link.rel = "preload";
link.as = "script";
document.head.appendChild(link);
上面这段代码可以让你预先加载脚本,下面这段代码可以让脚本执行
let script = document.createElement("script");
script.src = "myscript.js";
document.body.appendChild(script);
# 基于标记语言的异步加载
<link rel="preload" as="style" href="asyncstyle.css" onload="this.rel='stylesheet'" />
preload 的 onload 事件可以在资源加载完成后修改 rel 属性,从而实现非常酷的异步资源加载。
脚本也可以采用这种方法实现异步加载
难道我们不是已经有了<script async>
,<scirpt async>
虽好,但却会阻塞 window 的 onload 事件。某些情况下,你可能希望这样,但总有一些情况你不希望阻塞 window 的 onload 。
举个例子,你想尽可能快的加载一段统计页面访问量的代码,但又不愿意这段代码的加载给页面渲染造成延迟从而影响用户体验,关键是,你不想延迟 window 的 onload 事件。
有了 preload, 分分钟搞定。
<link
rel="preload"
as="script"
href="async_script.js"
onload="let script = document.createElement('script'); script.src = this.href; document.body.appendChild(script);"
/>
# 五、浏览器兼容性检测
其浏览器支持如下:
const isPreloadSupported = () => {
const link = document.createElement("link");
const relList = link.relList;
if (!relList || !relList.supports) {
return false;
}
return relList.supports("preload");
};
参考:用 preload 预加载页面资源 (opens new window) 参考:link 预加载详解 (opens new window)
- 本文链接: https://mrgaogang.github.io/javascript/deep/%E9%A1%B5%E9%9D%A2%E9%A2%84%E5%8A%A0%E8%BD%BD.html
- 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 许可协议。转载请注明出处!