preload
是一种声明式的资源请求指令,它可以在不阻塞浏览器的情况下提前加载资源。这个指令为了就是提升性能,因为许多程序都需要对何时获取,处理和应用到文档的资源进行一个更粒度化的控制。
简单来说,preload
有以下几个好处:
- 可以将必要的资源提前加载,不阻塞浏览器的渲染,进而提升性能;
- 使用
as
来指定要加载的资源类型,可以更精确的优化加载的优先级; - 在适当的情况下,可以重复的利用同一资源;
当遇到需要 preload 的资源时,浏览器会立即进行资源获取,但是并不执行,将结果放在内存中,当再次遇到使用该资源的标签时,才会执行。
如何使用 Preload
我们可以使用 link 标签的方式来创建:
<link rel="preload" href="/styles.css" as="style">
<script>
var res = document.createElement("link");
res.rel = "preload";
res.as = "style";
res.href = "/styles.css";
document.head.appendChild(res);
</script>
而 as
属性会告诉浏览器资源要下载什么类型的资源,一些主要的 as
属性如下:
document
font
image
script
style
关于 as
的完成列表是由 Fetch 方案制定的,可以查看 request destinations 来进行详细了解。
另一种方式方式就是在 HTTP 响应头中加上 preload 字段:
Link: <https://example.com/styles.css>; rel=preload; as=style
这种方式比通过 Link 方式加载资源方式更快,请求在返回还没到解析页面的时候就已经开始预加载资源了。
preload 支持情况
通过 Can I use 我们可以知道目前主流浏览器对 preload 支持度还不错。
有时候我们并不知用户会使用什么浏览器,也可以通过一段代码来判断 <link rel="preload">
支持情况。
const preloadSupported = () => {
const link = document.createElement('link');
const relList = link.relList;
if (!relList || !relList.supports)
return false;
return relList.supports('preload');
};
优先级
先看看下面这张图:
资源加载的优先级分五个级别:
- Highest 最高
- High 高
- Medium 中等
- Low 低
- Lowest 最低
我们可以在 Network 面板看到当前站点加载的各个资源的优先级。
- 对于使用了 preload 的资源,可以通过 as 或者 type 属性来标识他们的优先级。比如 as = style,那浏览器就会将资源优先级提升为 Highest,即使这个资源不是样式文件。
- 忽略 as 属性,或者错误的 as 属性会使 preload 等同于 XHR 请求,浏览器不知道加载的是什么,因此会赋予此类资源非常低的加载优先级。
- 使用 prefetch,其优先级默认为 Lowest,浏览器在空闲时候才会对其进行加载。
避免滥用 preload
使用 <link rel="preload">
可能会浪费用户的带宽,所以在使用的时候要注意,特别是在没有缓存的情况下。
使用 preload 获取了资源但是在 onload 事件的 3s 后都没有使用时,在控制台会出现一个警告。
这个警告就是因为你正在尝试用 preload 为其他资源预加载以提高性能,但是这些加载的资源却并没有使用,白白的浪费了,尤其是在对带宽比较敏感的移动端,这相当于浪费用户的流量。
preload 和 prefetch 的区别
-
preload 主要用于当前页面必须要的资源。通常用于本页面要用到的关键资源,包括关键js、字体、css文件。而 prefetch 主要用于浏览器将来可能会用到的资源。
-
对于 preload 来说,一旦页面关闭了,它就会立即停止 preload 获取资源。而对于 prefetch, 用户离开了一个页面,而对其他页面的预请求还在进行中,这些请求将不会被中断。
-
preload将会把资源的下载顺序权重提高,使得关键数据提前下载好,优化页面打开速度。
-
无论资源是否可以缓存,prefetch 都会在网络堆栈缓存中至少保存 5 分钟。
-
当一个资源被 preload 或者 prefetch 获取后,它将被放在内存缓存中等待被使用,如果资源位存在有效的缓存之中(如 cache-control 或 max-age),它将被存储在缓存中可以被不同页面所使用
避免混用 preload 和 prefetch
不要将 preload 和 prefetch 进行混用,他们分别适用于不同的场景,对同一个资源同时使用 preload 和 prefetch 会造成二次加载。
<link rel="preload" href="https://at.alicdn.com/t/font_zck90zmlh7hf47vi.woff" as="font">
<link rel="prefetch" href="https://at.alicdn.com/t/font_zck90zmlh7hf47vi.woff" as="font">
preload 字体不带 crossorigin 也会造成二次获取。
preload 实际使用案例
任何你想要先加载后执行,或者想要提高页面渲染性能的地方都可以使用 preload。
提前加载字体文件
当在页面中使用了自定义的字体文件时,就得在 CSS 文件中引入该字体,而字体文件必须等到浏览器解析到该 CSS 文件时才会进行加载,就会导致页面字体样式闪动(FOUT, Flash of Unstyled Text),所以可以用 preoload 告诉浏览器提前加载。假如字体文件能在 CSS 生效前加载完成,那么完全可以消灭 FOUT。
响应式加载
当我们的站点在不同大小的设备上想加载不同的资源时,常见的做法是通过 JS 来判断设备的类型动态加载资源,但是这样的会话,浏览器就无法提前发现并加载这些资源,影响用户体验。使用 preload 搭配 link 标签的 media 属性加载资源会有更好的效果,并且这种资源只有在满足媒体条件的情况下才会被加载进来。
<link rel="preload" as="style" href="./main.css" media="(min-width:700px)">
总结
谢谢你能看到最后,希望本文能对你有帮助。
如果文中有什么不对的地方,还请各位指正。