rel="preload" 不该用于动态路由脚本预取,因其仅对当前页有效且抢占首屏带宽;应改用 rel="prefetch",它在空闲时低优先级下载,适配 SPA 懒加载,需用绝对路径、不加 as="script",并配合 preconnect 与降级逻辑。

rel="preload" 不该用在动态路由脚本预取上——它只对当前页有效,且会抢占首屏带宽;真正该用的是 rel="prefetch"。
为什么不能用 preload 加载动态路由 JS
浏览器把 rel="preload" 当作“当前页马上要用”的信号。动态路由脚本(比如 /js/product-detail.js)通常只在用户点击后才需要,不属于当前页渲染关键路径。强行 preload 会导致:
- 首屏资源被挤占:JS 下载优先级过高,拖慢
main.css、首屏图片甚至 HTML 解析 - 资源浪费:用户没点进对应路由,预加载的 JS 完全闲置,缓存也仅限当前页生命周期
- DevTools 显示 pending/canceled:尤其在 HTTP/2 推送已启用时,重复触发请求被浏览器主动取消
prefetch 才是动态路由脚本的正确预取方式
rel="prefetch" 明确告诉浏览器:“这资源用户**可能**下一步用到,请等空闲时低优先级下载”。它天然适配 SPA 的懒加载场景。
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
- 必须写绝对或根相对路径:
/js/product-detail.js✅,./js/product-detail.js❌(子路径下解析易出错) - 不要加
as="script":prefetch 不校验资源类型,加了反而可能因 MIME 不匹配导致静默失败 - 配合
preconnect提前建连:如果脚本托管在 CDN 域名(如https://cdn.example.com),先声明<link rel="preconnect" href="https://cdn.example.com"> - 放在
<head>底部或<body>开头:避免阻塞首屏关键资源解析,但确保 DOM 加载前已声明
如何验证 prefetch 是否生效
别只看 HTML 里写了没,得看浏览器行为:
立即学习“前端免费学习笔记(深入)”;
- 打开 DevTools → Network 面板 → 切换到 “All” 或 “JS” 标签 → 找到目标脚本请求 → 查看 Initiator 列是否为
prefetch - 观察请求时间线:prefetch 请求通常出现在主页面 load 事件之后,且 Priority 显示为
Low - 手动清空缓存后刷新页面,再点击对应路由,确认脚本加载耗时明显下降(从网络请求变为缓存读取)
容易被忽略的兼容与兜底细节
prefetch 在 Chrome、Firefox、Edge 中支持良好,但 Safari 直到 iOS 16.4 / macOS 13.3 才开始支持。生产环境必须加降级逻辑:
- 用
document.createElement('link')动态插入 prefetch,并捕获onerror事件做 fallback - 对关键路由(如支付页),仍建议保留传统异步 import() + loading state,prefetch 只作为性能优化层,不承担功能保障
- 避免在 SSR 页面中对未登录用户 prefetch 个人中心脚本——权限校验失败时,prefetch 仍会发出,造成无效请求


















