prefetch 在 window.onload 完成、主线程空闲、无高优任务且页面未卸载时才发起请求;需满足同源、绝对或根相对路径、正确 as 属性,否则静默失效。

prefetch 什么时候会真正发起请求
它不会一写就发,必须等当前页面 window.onload 触发、主线程空闲、浏览器确认没有更高优先级任务(比如 preload 或同步脚本)时才尝试加载。常见卡点包括:页面里有长任务阻塞主线程;用户开了“节省流量”模式(Chrome/Edge 默认跳过);标签页还没完全加载完就被刷新或切走;目标资源返回了 Cache-Control: no-store —— 浏览器连缓存都不建,直接不发请求。
href 和 as 必须同时写对,缺一不可
href 必须是同源的绝对路径或根相对路径(如 /assets/detail.chunk.js),不能用协议相对路径(如 //cdn.example.com/xxx.js),否则会被当成非法协议静默忽略。as 不是可选装饰,它决定浏览器怎么处理这个请求:
- 预取 JS 文件 →
as="script"(不是as="js") - 预取 CSS →
as="style"(不是as="css") - 预取 HTML 页面 →
as="document"(Safari 对此支持弱,iOS 16.4 前基本无效) - 预取字体 →
as="font"(但注意:prefetch不触发 CORS 预检,跨域字体大概率静默失败)
写错或漏掉 as,请求大概率降级为普通 fetch,甚至被忽略——而且不报错、不警告。
为什么 Network 面板里看不到 prefetch 请求
Chrome DevTools 默认隐藏它,必须手动在 Network 面板右上角过滤器输入 prefetch 并勾选对应类型。更常见的“没看到”,其实是没满足触发条件:
- 页面还没触发
onload(比如第三方 SDK 拖慢了加载) -
<link rel="prefetch">被构建工具塞到了里,或晚于<title></title>插入 - 目标 URL 跨域(协议/域名/端口任一不同),浏览器连 DNS 查询都不发
- 资源已强缓存(
Cache-Control: immutable),浏览器直接从磁盘读,根本不发请求
真正能用的场景和替代方案
它只适合路径稳定、无动态参数、纯静态的资源,比如 Vite 构建后生成的 /assets/DetailPage.xxxx.js,而不是路由地址 /detail。整页 HTML 的 prefetch 在服务端渲染带 nonce/token 的场景下容易缓存后失效,不推荐。
- 更可控的做法:监听 hover 或滚动进入可视区,再动态插入
<link rel="prefetch">,加 200ms 延迟防误触 - 更简单可靠的方式:直接调用
import('./DetailPage'),浏览器自动 runtime prefetch,兼容性比rel="prefetch"好得多 - 别用它预加载图标、字体或 API 接口——这些要么浏览器自动处理,要么它根本不管
复杂点在于:它不提供任何 JS 接口,不执行、不解析、不传数据。你写了它,只是把文件扔进 HTTP 缓存;用户点下一步,依然要 mount 组件、调 fetch()、校验表单——这些它一个都管不了。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











