prefetch不是静默缓存,仅下载文件存入HTTP缓存,不执行、不解析、不渲染;必须静态写在<head>中<meta charset>和<title>之后,用绝对或根相对路径,正确声明as属性(如as="script"),否则静默失效。

prefetch 不是“静默缓存”,它只存文件,不执行、不解析
写了 <link rel="prefetch"> 并不等于下一页资源“已就绪”——它只是把目标文件(比如 step2.8a2b.js)下载下来放进 HTTP 缓存,后续导航时浏览器才可能复用。它不会提前执行 JS、不会渲染 HTML、不会恢复表单状态、也不会触发任何 fetch() 或 useEffect。很多开发者以为加了就“秒开”,结果跳转后照样白屏几秒,原因就在这儿。
必须静态写在 <head> 里,动态插入基本无效
常见错误是用 JS 动态创建:document.createElement('link') + appendChild()。这种写法在绝大多数场景下不会触发 prefetch 请求,因为浏览器只认初始 HTML 解析阶段就存在的 <link rel="prefetch"> 标签。
- 正确位置:放在
<head>中<meta charset>和<title>之后,且不能在<body>里 - 路径必须是绝对路径或根相对路径(如
/form/step2.8a2b.js),不能用./step2.js或step2.html,嵌套路由下极易解析失败 - 别指望它处理 query 参数:
/form/step2.html?uid=123这类带动态参数的 URL,浏览器根本不会发请求
as 属性写错,等于没写
as 不是可选提示,它直接决定浏览器是否发起请求、用什么优先级、走哪套缓存策略。漏写或写错,prefetch 就会静默失效。
-
as="script"对应 JS 文件,as="style"对应 CSS,as="document"对应 HTML —— 但强烈建议避开as="document" - 写成
as="fetch"或as="json",浏览器直接忽略该标签,Network 面板里连痕迹都没有 - 字体别用 prefetch:
as="font"不触发 CORS 预检,跨域字体大概率失败且无报错 - 如果用了
crossorigin,必须确保服务端响应头含Access-Control-Allow-Origin
为什么 Network 面板看不到请求?不是 bug,是常态
Chrome DevTools 默认过滤掉 prefetch 请求,你得手动勾选 Network 面板左上角的 “Prefetch” 类型;即使看到请求,也可能因以下原因未真正进缓存:
立即学习“前端免费学习笔记(深入)”;
- 页面还没完成
onload(比如有长任务、第三方 SDK 卡住主线程),prefetch 就不会启动 - 用户快速跳转或关闭标签页,请求被取消,但浏览器可能仍在后台继续下载
- 响应头缺失
Cache-Control: public, max-age=31536000,缓存不可复用,下次导航仍走网络 - Safari(尤其 iOS 16.4 之前)对
as="document"基本不发起请求,Chrome 虽支持但更保守
真正能靠得住的,其实是 import() 动态导入 —— 它由运行时控制,优先级更高,所有现代浏览器都支持,且明确对应代码分割后的 chunk 路径。prefetch 的价值只在极少数确定路径、纯静态、同源、用户行为高度可预测的场景里,而且必须接受它“有时不响、有时失效、从不保证”的事实。



















