关于 prefetch
prefetch 是面向 Web 开发者的浏览器加载优化技巧,在用户访问前低优先级获取可能需要的资源,以缩短后续导航等待时间。内容涵盖 HTML、HTTP 提示和 Webpack 用法,并提醒避免浪费带宽。
主要功能
- 01提前获取可能需要的资源
- 02支持 Webpack magic comments
- 03浏览器空闲时低优先级加载
- 04说明预取的带宽权衡
适用场景
- 01预先加载后续页面资源
- 02减少点击后组件的等待
- 03为可能访问的路由预取资源
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ patternsdev/ skills --skill prefetch安装后在 Claude Code 中输入/prefetch确认已加载。
详细介绍
预取
预取(<link rel="prefetch">)是一种浏览器优化,可让我们在后续路由或页面需要某些资源之前提前获取这些资源。预取可以通过多种方式实现:可以在 HTML 中声明(如下例所示),也可以通过 HTTP Header(Link: </js/chat-widget.js>; rel=prefetch)、Service Workers 或 Webpack 等更灵活的方式实现。
适用场景
- 确定用户很可能会在近期访问某些路由或需要某些资源时使用
- 有助于缩短后续导航时用户感知到的加载时间
不适用场景
- 对于不太可能用到的资源——不必要的预取会浪费带宽,并与关键请求争抢带宽
- 在带宽有限或按流量计费的连接中,预取会消耗用户的数据流量
- 当预取的资源频繁变化,使用时可能已经过期
使用说明
- 使用
<link rel="prefetch">或 Webpack 魔法注释(/* webpackPrefetch: true */)预取资源 - 只预取很可能需要的资源——不要过度预取,以免消耗带宽
- 浏览器空闲时会以低优先级加载预取资源
详情
<link rel="prefetch" href="/pages/next-page.html" />
<link rel="prefetch" href="/js/emoji-picker.js" />
预取
在展示如何根据可见性或交互导入模块的示例中,我们看到,点击按钮以切换组件后,实际组件显示在屏幕上之前往往会有一些延迟。这是因为用户点击按钮时,浏览器仍需请求并加载该模块!
在很多情况下,我们知道用户会在页面首次渲染后不久请求某些资源。虽然这些资源可能不会立即显示,因此不应包含在初始 bundle 中,但尽可能缩短加载时间、改善用户体验会很有帮助!
我们可以预取已知在应用中某个时刻很可能会用到的组件或资源。只需在导入语句中添加一条魔法注释,就能让 Webpack 知道需要预取某些 bundle:/* webpackPrefetch: true */。
const EmojiPicker = import(/* webpackPrefetch: true */ "./EmojiPicker");
构建应用后,我们可以看到 EmojiPicker 将会被预取。
Asset Size Chunks Chunk Names
emoji-picker.bundle.js 1.49 KiB emoji-picker [emitted] emoji-picker
vendors~emoji-picker.bundle.js 171 KiB vendors~emoji-picker [emitted] vendors~emoji-picker
main.bundle.js 1.34 MiB main [emitted] main
Entrypoint main = main.bundle.js
(prefetch: vendors~emoji-picker.bundle.js emoji-picker.bundle.js)
实际输出可以在文档 head 中看到,是一个带有 rel="prefetch" 的 link 标签。
<link rel="prefetch" href="emoji-picker.bundle.js" as="script" />
<link rel="prefetch" href="vendors~emoji-picker.bundle.js" as="script" />
即使用户尚未请求资源,浏览器也会请求并加载预取的模块。浏览器空闲且判断带宽足够时,就会发起请求以加载资源,并将其缓存。缓存资源可以显著缩短加载时间,因为用户点击按钮后,我们不必等待请求完成,而是可以直接从缓存中获取已加载的资源。
虽然预取是优化加载时间的好方法,但不要过度预取。如果用户最终从未请求 EmojiPicker 组件,我们就白白加载了该资源。这可能会让用户产生额外费用,或拖慢应用。只预取必要的资源。