绝大多数情况下,动态路由 js chunk 不该用 preload。因为它是非首屏资源,preload 会抢占带宽、拖慢 lcp,且与运行时 import() 不匹配;应改用 prefetch 实现低优先级预加载。

动态路由 JS chunk 该不该用 preload
绝大多数情况下,不该。Webpack/Vite 打包出的路由级 chunk(如 about.123abc.js)不是首屏必需资源,preload 它只会抢占带宽、拖慢 LCP。
浏览器在解析 HTML 时根本不知道这个 chunk 何时被用到——它藏在 import() 里,静态分析无法识别。preload 标签是 parser-blocking 阶段触发的,而动态 import 是运行时行为,两者不匹配。
- ✅ 真正该 preload 的:首屏立即执行的入口脚本(如
app.js),且它没出现在 HTML 的<script src></script>中 - ❌ 不该 preload 的:所有
import('./pages/About.vue')对应的产物,哪怕你把它硬写进,浏览器也不会提前拉取 - ⚠️ 混用后果:DevTools Network 里看到
Priority是Low或请求状态为canceled,说明浏览器已忽略或降级处理
想预加载路由模块,该用 prefetch 而不是 preload
rel="prefetch" 才是为动态路由准备的正确工具。它不抢带宽,只在页面空闲时低优先级下载,且能被后续导航复用。
比如首页加载完成后,立刻 prefetch 用户可能点击的「用户中心」页的 JS 和 CSS:
<link rel="prefetch" href="/js/user-center.456def.js" as="script"><link rel="prefetch" href="/css/user-center.css" as="style">
- 必须用
as="script"或as="style",不能漏——否则缓存无法复用,下次跳转仍要重下 - 路径必须是绝对或根相对(
/js/...),避免子路由下解析失败 - 别在 prefetch 里写
as="font":字体 prefetch 在 Safari 和部分安卓 WebView 上会静默失败,因不触发 CORS 预检
如果非要对动态脚本做“类 preload”优化,得靠 JS 主动控制
真正可控的方式,是在路由切换前手动触发 fetch,而不是依赖 HTML 的 <link rel="preload">。
例如,在用户 hover 导航菜单项时,预拉取对应 chunk:
document.querySelector('.nav-about').addEventListener('mouseenter', () => {
import('./pages/About.vue').catch(() => {});
});
- 这种方式本质是提前触发
import(),让浏览器按需发起请求,优先级由运行时决定 - 比硬塞
<link rel="preload">更精准,不会污染首屏资源队列 - 注意 fallback:
import()失败时需有兜底逻辑,否则白屏风险上升
验证是否真生效,别信代码写了就完事
打开 Chrome DevTools → Network 面板,刷新页面后重点看三列:
-
Initiator列:prefetch 请求必须显示为prefetch,不是parser或script -
Priority列:应为Low;若出现Highest,说明误用了preload - 跳转到目标页后,对应资源应显示
200 (from memory cache)或304,而非重新请求
最容易被忽略的是:prefetch 资源的 Cache-Control 必须允许缓存(如 public, max-age=31536000),否则即使下了,跳转时也拿不到缓存命中。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











