资源提示 Resource Hints
比较 preload、modulepreload、prefetch、preconnect 与 dns-prefetch 在当前导航关键资源、未来导航资源和连接预热上的不同作用、成本与浏览器支持边界。
[!info] related notes
- 所属 MOC: 前端基础 MOC, 前端性能优化 MOC
- 关键路径: 关键路径优化
- 首屏: 首屏加载优化
- 缓存: 浏览器缓存体系
- 验证工具: DevTools Network 面板
资源提示 Resource Hints
浏览器实现和支持度会变化;生产使用前应结合当前 compatibility data 和真实 Network trace 验证。
核心关系
资源提示不是一个“加速开关”,而是在浏览器原本调度之前提前提供意图:
- 只先解析域名 → dns-prefetch
- 提前建立跨源连接 → preconnect
- 当前导航的高优先级资源 → preload / modulepreload
- 未来可能需要的资源 → prefetch
它们的成本不同,也不能互相替代。
dns-prefetch
目标:只提前完成 DNS resolution。
<link rel="dns-prefetch" href="https://cdn.example.com">
适合可能稍后访问的 cross-origin。
对 same-origin 通常没有实际收益,因为当前站点地址在页面解析前已经完成解析/连接流程。
preconnect
目标:提前准备到某个 origin 的连接。
HTTPS 场景可能包括 DNS、TCP 与 TLS handshake。
<link rel="preconnect" href="https://fonts.example.com" crossorigin>
适合当前页面很快一定会请求的关键第三方 origin。
不要对大量第三方 origin 全部 preconnect;连接本身会占资源。
preload
目标:让浏览器尽早发现并获取当前导航即将使用的资源;具体请求优先级还取决于资源类型、as、fetch priority 与浏览器调度。
<link
rel="preload"
href="/fonts/app.woff2"
as="font"
type="font/woff2"
crossorigin
>
关键点:
- 针对当前页面;
- 提前 fetch/cache,但不会因为 preload 自动执行或应用;
as会影响请求模式、优先级与 CSP;- 字体等资源的
crossorigin要与真实消费请求的 mode 匹配,否则可能重复下载。
不要 preload 所有资源。
modulepreload
ES Modules 有专门的:
<link rel="modulepreload" href="/app.js">
它理解 module fetching semantics;关键 ES module 应优先考虑 modulepreload,而不是把所有模块当普通 script preload。
prefetch
目标:低优先级提前获取未来导航可能需要的资源。
<link rel="prefetch" href="/next-page-data.json">
它不是当前页面关键资源优化工具。
rel=prefetch 的浏览器支持与执行策略需要按目标环境检查,不能假设所有浏览器都会执行提示。
还要考虑:
- 用户是否真的会导航过去;
- bandwidth / data saver;
- cache policy;
- browser scheduling heuristics。
现代 navigation speculation 还可能使用 Speculation Rules API。
103 Early Hints
资源提示也不只来自 HTML。
服务器可以在最终响应准备完成前发送 HTTP 103 Early Hints,配合 Link header 让浏览器更早 preconnect/preload。
价值是把关键资源发现提前到最终 HTML 之前。
决策表
| 需求 | 优先考虑 |
|---|---|
| 只想提前解析第三方域名 | dns-prefetch |
| 当前页面很快会用某个第三方 origin | preconnect |
| 当前页面晚发现但关键的资源 | preload |
| 当前页面关键 ES module | modulepreload |
| 后续导航可能使用的资源 | prefetch / navigation speculation |
验证方法
使用 DevTools Network 验证:
- 请求是否真的提前发生;
- priority;
- initiator;
- 是否重复下载;
- connection timing;
- LCP / 关键资源是否真正提前。
性能收益必须测量,而不是根据语义直接推断。
常见失败模式
- preload everything;
- preconnect every origin;
- preload request mode 不匹配;
- 把 prefetch 当当前页面关键资源;
- 只看规则建议,不看 Waterfall。
学习检查
- dns-prefetch 与 preconnect 各自提前做到哪一步?
- preload 与 prefetch 的当前导航 / 未来导航语义有什么差异?
- 为什么 preload 必须认真设置 as 和 request mode?
- 为什么大量 preconnect/preload 可能反而变慢?
- modulepreload 与普通 script preload 有什么差异?
- 为什么 rel=prefetch 不能假定所有浏览器行为一致?
- 103 Early Hints 把资源发现提前到了哪个阶段?
- 给 Web Font、第三方 API、下一页数据三个对象,选择 hint 并说明如何在 Network 面板验证。