prefetch 必须写死在初始 html 中且位置严格,路径需绝对或根相对,as 属性必须正确指定资源类型,否则请求被忽略或降级;它仅缓存静态资源,不执行、不渲染、不影响首屏,且受网络策略和浏览器限制。

prefetch 必须写死在 HTML 里才可能生效
动态插入(比如 document.head.appendChild())基本无效,浏览器只在初始 HTML 解析阶段识别 rel="prefetch"。它不走 JS 生命周期,也不响应事件或状态变化。
常见错误是用 JS 检测用户 hover 或 scroll 后再创建 link —— 这种写法在 Chrome、Edge、Firefox 中大概率被忽略,Network 面板里连请求都不会出现。
- 正确位置:
<meta charset>和<title></title>之后、任何<link rel="stylesheet">或<script></script>之前 - 路径必须是绝对路径(
/assets/step2.8a2b.js)或根相对路径(/pages/checkout.html),不能用./next.js或//cdn.example.com/xxx - 跨域资源需加
crossorigin属性,但 Safari 对跨域as="document"支持极差,建议优先同源
as 属性不是可选,写错等于没写
浏览器靠 as 决定怎么发请求、走哪条缓存策略、是否校验 MIME 类型。漏掉或写错,请求会被降级为普通 fetch(),甚至静默丢弃。
- 预取 JS 文件:必须用
as="script",例如<link rel="prefetch" href="/assets/detail.4f9c.js" as="script"> - 预取 HTML 页面:必须用
as="document",例如<link rel="prefetch" href="/pages/checkout.html" as="document"> - 预取 CSS:用
as="style";预取字体(不推荐)需as="font"+crossorigin -
as="fetch"和as="json"是无效值,浏览器不识别,也不报错,只是当普通链接处理
为什么 Network 面板看不到 prefetch 请求
不是代码错了,是浏览器根本没触发它。真实原因往往和直觉相反:
- 当前页还没执行完
onload:比如有长任务阻塞主线程、大图未加载完、同步脚本卡住 - 用户开了“节省流量”模式(Chrome/Edge 默认跳过,Safari 直接忽略)
- 标签页快速关闭或跳转,浏览器主动中止请求,Network 显示
cancelled - 目标资源返回
Cache-Control: no-store或max-age=0,浏览器连缓存都不建,直接不发请求 - DevTools 默认隐藏 prefetch 请求:必须手动在 Network 面板勾选
prefetch过滤器,或清空所有过滤器再刷新
它只存文件,不执行、不渲染、不发 API
rel="prefetch" 的作用边界非常窄:把静态资源二进制 blob 存进 HTTP 缓存,仅此而已。后续跳转时复用,但组件 mount、fetch() 调用、表单校验、滚动复位这些全得你自己写。
- 别用它预取
/api/user/profile—— 它不发 fetch 请求,也不解析 JSON - 别预取含服务端动态 token 的 HTML(如带随机
nonce或登录态 cookie 的/profile),缓存后复用会因校验失败白加载还报错 - 别指望它优化首屏:它等
onload完才启动,对 LCP/FCP 零帮助 - 移动端尤其危险:用户切页或关闭标签后,prefetch 请求仍后台持续下载,无法中止
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











