rel="prefetch" 本质是静默预加载,不执行不渲染,仅存入HTTP缓存;其生效需满足静态写入head、同源绝对路径、正确as值等严格条件,动态插入或跨域均无效,真正可控方案是行为触发或动态import。

rel="prefetch" 本身设计就是静默的——它不执行、不渲染、不报错,也不提供 JS 回调。所谓“做到静默预加载”,其实是接受它的天然限制,而不是想办法让它“更安静”。
为什么你写了 rel="prefetch" 却看不到请求
这不是失效,是浏览器根本没启动它:
- Chrome DevTools 默认隐藏
prefetch请求,Network 面板必须手动勾选prefetch类型过滤器 - 页面还没触发
window.onload(比如有长任务、第三方 SDK 卡住主线程),prefetch就一直挂起 -
href是相对路径(如./step2.js)或协议相对路径(如//cdn.com/xxx.js),解析失败后静默忽略 -
as属性缺失或写错(比如as="fetch"或as="js"),浏览器直接丢弃该,Network 里毫无痕迹
rel="prefetch" 必须静态写在 里才可能生效
动态插入(比如 document.head.appendChild(link))90% 无效,尤其对 Safari 和旧版 Chrome:
- 必须随初始 HTML 一起解析,不能靠 JS 后续注入
- 目标 URL 必须同源,跨域(协议/域名/端口任一不同)时连 DNS 查询都不会发起
- 路径必须是绝对路径或根相对路径(如
/form/step2.7f8a.js),不能用./或../ -
as值必须严格匹配资源类型:as="script"(JS)、as="style"(CSS)、as="document"(HTML)
别预取 HTML 页面,改预取确定的 chunk 文件
as="document" 风险极高,且 Safari 支持极差(iOS 16.4 之前基本不发请求):
实现 Markdown↔ HTML 互转,支持导出 PDF,用于用户请求的文档格式转换。
- 服务端返回的 HTML 若含动态
nonce、CSRF token 或时间戳,缓存后复用会直接白屏 - 浏览器 prefetch HTML 时会顺带拉取其中所有
<script></script>和,但这些子资源若未单独声明prefetch,缓存键不一致,后续无法复用 - 真正可控的做法:明确知道构建产物中下一步用的 JS chunk 名(如
/assets/Step2.abc123.js),就只 prefetch 它;如果 CSS 分离,再加一行as="style" - 字体别用
prefetch——它不触发 CORS 预检,跨域字体大概率静默失败
静默 ≠ 可控,真正的“可控静默”得靠行为触发
静态写死 本质不可控:用户没打算点,它也可能发请求;用户真要点了,它却因 onload 没触发而没动。更可靠的方式是:
- 监听用户 hover 或滚动进入可视区,在 200ms 延迟后动态创建并插入
- 或者直接用
import('./Step2')—— 浏览器自动按需 prefetch,且兼容性更好、路径由打包工具保证 - 如果目标资源在 CDN 上,务必提前配
,否则 DNS + TLS 耗时远超 prefetch 本身
最易被忽略的一点:prefetch 只把文件扔进 HTTP 缓存,不执行 JS、不恢复表单状态、不复用 React 组件实例。你写了它,用户点下一步时依然要 mount、fetch、校验、滚动——这些它一个都不管。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










