rel="prefetch"必须静态写在HTML的中,且位于和之后、首个或之前;动态插入或置于中完全无效。

rel="prefetch" 必须放在 里且在 之后
浏览器只在初始 HTML 解析阶段读取 rel="prefetch",动态插入或写在 里完全无效。它不是 JS 运行时指令,而是解析器早期就捕获的资源提示。
常见错误是构建工具(比如 Webpack + HtmlWebpackPlugin)把 prefetch 标签塞到 底部,或者用 document.createElement 晚于 DOMContentLoaded 插入——这些统统不触发预取。
- 必须确保它出现在
<meta charset>和<title></title>之后、任何<link rel="stylesheet">或<script></script>之前 - 多个
prefetch标签之间无执行依赖,但按用户点击概率从高到低排列,部分浏览器会据此微调调度顺序 - 若 SSR 渲染,服务端模板需直接输出该标签,不能靠客户端 hydration 补充
prefetch 不下载 HTML,也不预解析它
很多人误以为 rel="prefetch" href="/post/123" 会让浏览器提前加载并缓存整个页面的 DOM 结构。实际上,它只缓存原始字节流(raw bytes),后续跳转仍需完整导航流程:DNS → TCP → TLS → HTTP GET → HTML 解析 → 构建 DOM/CSSOM → render。
这意味着:prefetch 对纯静态详情页(如 /post/2024-06-15-title)有效,但对带 query 参数(/post?id=123)、含 CSR 路由(/post/123#comments)或服务端动态渲染(/search?q=xxx)的 URL 几乎无效——缓存无法命中,甚至可能污染 disk cache。
立即学习“前端免费学习笔记(深入)”;
- 只适合路径稳定、无副作用、体积 ≤ 100KB 的资源,比如单个 JS chunk 或 WebP 图片
- 别对整页 HTML prefetch;更合理的做法是对下一跳的
main.js或关键 CSS chunk 做 prefetch - SSR 场景下,prefetch 对 fetch() 请求无意义,浏览器不支持
rel="prefetch"for API
Priority 显示为 Low 才算生效,否则配置错
在 Chrome DevTools 的 Network 面板里,prefetch 请求的 Priority 列必须显示为 Low。如果看到 High 或 Medium,说明它被当成 preload 或普通请求处理了——大概率是漏写了 as 属性,或写成了 rel="preload"。
验证是否真被缓存使用,不能只看 Network 是否有请求,要三看:
- Initiator 列显示为
Prefetch(不是Parser或Other) - 跳转后新页面中对应资源的请求 Size 显示为
from memory cache或from disk cache - Application → Cache Storage 中存在对应 URL 的缓存条目(注意 Firefox 和 Chrome 缓存命名略有差异)
移动端弱网下 prefetch 可能拖慢本页渲染
预取在空闲时触发,但“空闲”是相对的。在 3G 或高延迟 Wi-Fi 下,浏览器未必有真正空闲窗口;此时 prefetch 会抢占 HTTP/2 流和带宽,挤掉首屏图片、字体或 critical CSS 的请求,导致 FCP 延迟 200ms+。
这不是理论风险,而是真实可复现的问题。尤其当搜索结果页同时 prefetch 3–5 个详情页时,首屏加载耗时反而上升。
- 建议用
media属性做条件加载,例如:<link rel="prefetch" href="/post/abc" as="document" media="(min-width: 768px)"> - 避免跨域 prefetch,除非目标站明确设置
SameSite=Lax,否则可能意外携带 Cookie 触发埋点或登录态同步 - 服务端日志里会出现大量
200请求但无真实 PV,GA4 等统计系统需过滤User-Agent含prefetch的请求
prefetch 很少,多数失败不是因为语法错,而是路径不可预测、缓存未命中、或根本没等到空闲时机——它不像 preload 那样强制执行,而更像一个浏览器愿意听但不一定照做的建议。



















