会,prefetch 会后台持续下载资源并消耗流量,即使页面关闭;其行为受 as 属性影响显著,as="document" 易引发连带加载,as="script" 更安全;移动端须结合网络条件动态控制。

会,prefetch 在用户没跳转到目标页面时,确实会下载资源并消耗流量——这不是 bug,是设计使然。
prefetch 请求不会因页面关闭而中断
和 preload 不同,prefetch 是“后台闲时加载”,浏览器一旦发起请求,即使用户刷新、关闭当前页,甚至切到其他标签页,下载仍会继续。这意味着:
- 用户在弱网或按流量计费的移动网络下,可能在不知情时被预取了几十 KB 到几 MB 的 JS/CSS/HTML
- 如果预取的是整页 HTML(比如
<link rel="prefetch" href="/article/123" as="document">),还可能触发其子资源(图片、字体、API)的连带加载 - Chrome DevTools 的 Network 面板里看不到
prefetch请求的完整生命周期,容易误判“没发出去”而重复加
as="document" 和 as="script" 的行为差异极大
不指定 as 属性时,浏览器默认按 as="fetch" 处理,优先级极低且缓存策略松散;但显式声明类型会直接影响资源是否被复用、是否进 HTTP 缓存、是否受 CSP 限制:
-
as="document":预取整个 HTML 页面,适合 SPA 中已知下一步必跳的路由(如登录后固定跳 dashboard),但需确保该 HTML 不含服务端动态 nonce 或一次性 token,否则缓存后渲染失败 -
as="script":只预取 JS 文件,配合 code-splitting 后的 chunk 名称(如src_async_login.js)更安全,且能被 script 标签或import()直接复用 -
as="style"或as="font"几乎不推荐用于prefetch:字体和样式通常属于当前页关键路径,该用preload而非预测性加载
移动端必须加网络条件判断
Chrome 和 Safari 都支持 navigator.connection.effectiveType,但 prefetch 本身不感知网络状态。真实项目中应主动拦截:
- 检测到
navigator.connection?.effectiveType === '2g' || 'slow-2g'时,直接移除所有<link rel="prefetch">节点 - 监听
navigator.connection?.onchange,在网络变差时 abort 当前 prefetch 请求(需配合AbortController+ 动态fetch替代静态 link) - 服务端可通过 User-Agent 或 Client-Hints 判断设备类型,在响应 HTML 时选择性注入 prefetch 标签(比如 PC 端注入,iOS WebView 不注入)
真正难处理的不是“要不要加 prefetch”,而是“加了之后怎么确保它只在合适的时候动”。很多团队上线后才发现 iOS 用户反馈流量突增——因为 Safari 虽不支持 prerender,但对 prefetch 的执行比 Chrome 更激进,且不暴露相关调试入口。










