prefetch必须静态写在HTML的<head>中,且位于<meta charset>和<title>之后、首个<link rel="stylesheet">或<script>之前;动态插入或置于<body>中完全无效。

prefetch 必须写在 里且位置靠前
浏览器只在初始 HTML 解析阶段识别 rel="prefetch",动态插入(比如 document.head.appendChild())或放在 中完全无效。它不是 JS 运行时指令,而是解析器早期就捕获的资源提示。
正确位置是:<meta charset> 和 <title></title> 之后、首个 <link rel="stylesheet"> 或 <script></script> 之前。Webpack/Vite 的 HTML 插件若把 prefetch 标签塞到 底部,大概率失效。
- ✅ 正确示例:
<head> <meta charset="utf-8"> <title>首页</title> <link rel="prefetch" href="/form/step2.7f8a.js" as="script"> <link rel="stylesheet" href="/main.css"> </head>
- ❌ 错误写法:
<body><link rel="prefetch" ...></body>或在DOMContentLoaded后用 JS 插入 - SSR 场景下,必须由服务端模板直接输出该标签,不能依赖客户端 hydration 补充
href 路径必须绝对或根相对,且资源得真实存在
href 值不能是 ./step2.html 或 step2.js —— 嵌套路由下解析易错;也不能是带 query 参数的动态地址(如 /posts?page=2),浏览器不会执行 JS 或发带参请求。
目标资源必须是构建产物中确定存在的静态文件,比如 Webpack/Vite 输出的 step2.xxx.js 或 step2.xxx.css。整页 HTML(as="document")风险极高:含 nonce/CSRF token 的响应会被缓存后复用,导致白屏或报错。
立即学习“前端免费学习笔记(深入)”;
- ✅ 推荐:
href="/assets/checkout.chunk.js"(JS)、href="/assets/checkout.e2d9.css"(CSS) - ❌ 避免:
href="./step2.html"、href="/posts?id=123"、href="https://cdn.example.com/font.woff2"(跨域字体不触发 CORS 预检,静默失败) - 验证方式:跳转后打开 Network 面板,该资源状态码应为
200 (from memory cache)或304,Initiator 显示prefetch
as 属性必须写对,否则降级为低效 fetch
as 不是可选装饰,它决定浏览器如何调度请求头、CORS 策略、缓存分区和优先级。漏写或类型错配,Priority 直接变成 Low,等同于普通 fetch,甚至进错缓存队列。
Chrome DevTools 的 Network 面板里,prefetch 请求的 Priority 列必须显示为 Low 才算生效;如果看到 High 或 Medium,说明被当成 preload 或普通请求处理了。
- JS 文件用
as="script",CSS 用as="style",图片用as="image" - 别对字体用
as="font"—— 即使同域也必须配crossorigin,Chrome 120+ 默认启用 CORS 检查 -
as="document"在 Safari(尤其 iOS 16.4 之前)基本无效,Chrome 若响应头缺Cache-Control: public, max-age=31536000,后续跳转仍不复用
浏览器空闲才触发,别指望它“立刻下载”
prefetch 不是写了就发请求的机制。它只在当前页 onload 完成、主线程空闲、网络带宽可用、且页面未卸载时,才可能启动。多步表单常因 JS 校验、动画阻塞 onload,用户点“下一步”太快,prefetch 根本没来得及发请求。
Chrome DevTools 默认隐藏 prefetch 请求,Network 面板需手动勾选 prefetch 类型过滤器;Safari 更难观测,建议用 chrome://net-internals/#events 筛选 URL_REQUEST_PREFETCH 类型。
- 常见“没反应”原因:页面还没完成
onload、目标 URL 跨域(协议/域名/端口任一不同)、as缺失或写错、资源已强缓存(Cache-Control: immutable) - 别预取超过 100KB 的资源,体积太大浏览器可能主动丢弃
- 最多放 1–2 个最高置信度的目标(如点击率 >70% 的第二步 JS),堆砌多个会稀释优先级
as 是否精准、以及浏览器有没有真正空闲下来——这三者耦合极强,任何一环断掉,prefetch 就只是 HTML 里一行安静的文本。



















