经常听到这些名词,花了些时间搞搞明白。
介绍
先了解上面这张图(来源),了解浏览器对于要加载的资源是有优先级的。
- preload 优先于 prefetch
- …
Preload
Preload 是一种声明式的预加载资源的方式,用于告诉浏览器尽快请求一个重要的资源,浏览器会为此分配更高的优先级,但尽量不延迟 window.onload 事件的发生。
使用 preload 有三种方式,
// 1. Html 标签
<link rel="preload" href="/foo.css" as="style" />
// 2. 脚本的方式,动态加载一个 link 标签
<script>
var res = document.createElement("link");
res.rel = "preload";
res.as = "style";
res.href = "/foo.css";
document.head.appendChild(res);
</script>
// 3. HTTP Header
Link: <https://example.com/other/styles.css>; rel=preload; as=style
HTTP Header 还可用于 HTTP/2 的 Server Push 的方式。
什么时候用?当资源是当前渲染必须的,但不会第一时间发起请求时,用 preload。比如 CSS 里的字体文件,比如 code-splitting 之后当前路由需要异步加载文件,前者需要先下载 CSS 并解析后才能决定是否加载,后者需要下载 JS、解析、执行之后才能决定是否加载。把这些确定需要的资源文件提前请求,就是 preload 的作用。
preload 了不用在 chrome devtool 里会给出警告,
改 preload 却没有 preload 的资源在 Lighthouse 检测的时候也会给出改进建议,
Prefetch
Prefetch 是 Resouce Hints 的一种,也可用于预加载资源。但和 Preload 的区别是,他用于加载之后可能会用到的资源,浏览器在空了的时候加载,所以可能加载,也可能不加载。
Resource Hints 里除了 Prefetch,还有 Prerender、Preconnect 和 DNS Prefetch,顾名思义,应该能理解。其中 Prerender 用于预加载 html,并预加载其包含的子资源。
使用方式也有三种,同 Preload。
什么时候用?非重要的的资源,比如下一个页面才需要的,或者用户需要做一些操作之后才需要发起的操作。这些应该走 prefetch,而非 preload,因为 preload 的优先级较高,可能会推迟 window.onload 以及 TTI 的时间。
还有应用场景是基于路由的 Prefetch,比如 nuxt.js@2.4 加的 Smart prefetching,会自动 prefetch 可视区域里的 <Link>
指向的路由的资源,相似的实现还有 quicklink。
Prerender
Prerender 这个名词有些歧义,这里指的是基于 SSR 或其他方案预先提供好 HTML 内容,和前面 Resource Hints 的 Prerender 不是一回事。
实现上有几种思路:
- 基于 SSR,build 跑一遍,为每个路由生成 HTML
- 基于 react-snap 或 prerender.io 等方案,不挑框架,但有一定使用限制,比如对于动态路由的处理
TODO: 待细化。
工程化方案
webpack
webpack 自 4.6 起支持一些针对 preload 和 prefetch 的魔法注释。
import(_/* webpackPreload: true */_ "CriticalChunk")
import(_/* webpackPrefetch: true */_ "ImportantForNextPageChunk")
4.6 之前则可用 preload-webpack-plugin 实现。
参考
规范
文章
- Preload, prefetch and other <link> tags: what they do and when to use them · PerfPerfPerf
- Resource Fetch Prioritization and Scheduling in Chromium
- https://medium.com/reloading/preload-prefetch-and-priorities-in-chrome-776165961bbf
- https://web.dev/preload-critical-assets
- https://developers.google.com/web/fundamentals/performance/resource-prioritization
- https://developer.mozilla.org/en-US/docs/Web/HTML/Preloading_content
- https://www.cnblogs.com/xiaohuochai/p/9183874.html