rel="prefetch" 是低优先级预下载资源至 http 缓存,需满足三条件:静态写在 html head 中、同源、浏览器空闲;不执行不解析,仅缓存,非 api 预取方案。

rel="prefetch" 不是“预加载当前页资源”的开关,它只在当前页 onload 完成、浏览器空闲、页面尚未卸载时,低优先级下载指定资源并存入 HTTP 缓存——写对了也不保证发起请求,写错了基本没反应。
为什么 DevTools 里根本看不到 prefetch 请求
这不是代码出错,而是触发条件没凑齐:
- Chrome 默认不显示
prefetch类型请求,必须在 Network 面板勾选prefetch过滤器,或清空所有过滤器再刷新 - 页面还没触发
onload(比如有长任务阻塞、大图未加载完、JS 执行卡顿),prefetch就不会启动 - 用户快速切走标签页、刷新或关闭页面,浏览器会主动取消已发出的请求(Network 里显示
cancelled) - Firefox 默认禁用:需手动访问
about:config,把network.prefetch-next设为true - Safari(尤其 iOS 16.4 之前)对
as="document"基本忽略,连请求都不发
怎么写才能让 rel="prefetch" 真正生效
三个硬性条件缺一不可,漏一个就白写:
- 必须静态写在 HTML 的
中,动态插入(如document.head.appendChild(link))多数无效 - 目标 URL 必须同源(协议、域名、端口完全一致),跨域请求浏览器静默丢弃,不报错也不发 OPTIONS
- 必须处于浏览器空闲状态:无高优先级请求、CPU/网络负载低、页面未卸载
正确示例:<link rel="prefetch" href="/js/detail.chunk.js" as="script">
关键细节:
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
-
href用绝对路径或根相对路径(如/pages/checkout.js),避免./next.js在嵌套路由下解析错 -
as值必须准确:JS 用as="script",CSS 用as="style",HTML 文档用as="document";写成as="fetch"是无效值 - 服务端响应头必须含
Cache-Control: public, max-age=31536000,否则下次跳转时缓存失效,prefetch白做
prefetch 和 preload 混用会重复请求
同一个 URL 同时被 rel="preload" 和 rel="prefetch" 声明,Chrome 会发两次独立请求:
-
preload是高优先级、立即 fetch、用于当前页 -
prefetch是低优先级、空闲时 fetch、用于下一页 - 浏览器不合并、不去重,Network 面板里能看到两个条目,
Priority分别标为high和low
特别注意:Webpack 的 SplitChunksPlugin 若配置了 prefetch: true,容易和你手动加的 preload 冲突。验证方式很简单:打开 DevTools Network,搜目标 URL,看是否出现两次。
想预取 API 数据?prefetch 根本不适用
rel="prefetch" 只下载、不执行、不解析、不提供 JS 接口——它不会触发 fetch()、不运行脚本、不吐出 JSON 给你用。
要提前获取可读取的 API 数据,该用:
-
fetch()+cache.put()存入 Cache API,后续用cache.match()读取 - SPA 路由切换前,用
fetch()预加载下一页所需数据,配合 Suspense 或 loading 状态管理 - 服务端启用 HTTP/3 QPACK 推送(需服务器支持),但客户端兼容性有限
最容易被忽略的一点:prefetch 不是“提前执行”,它只是提前下载。你不能靠它拿到数据,也不能靠它触发逻辑——它只负责把文件塞进缓存,剩下的,得靠你自己写的代码去匹配、读取、使用。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










