spa主bundle必须用rel="preload"而非script标签,因其可在html解析阶段并行下载、抢占网络空闲窗口,提前400–800ms起始下载;而script标签会阻塞解析且无法控制优先级,且必须配as="script"、路径一致、避免重复请求。

为什么 SPA 主 Bundle 一定要用 rel="preload" 而不是 <script src></script>
因为浏览器解析 HTML 时,<script src="main.js"></script> 会阻塞解析,且必须等 DOM 构建到该标签才发起请求;而 <link rel="preload" href="main.js" as="script"> 在 解析阶段就触发下载,与 HTML 解析并行——实测在 3G 网络下可提前 400–800ms 开始下载。
常见错误现象:Lighthouse 显示 “Eliminate render-blocking resources” 报警,Network 面板里 main.js 的 Start Time 比 index.html 完成解析晚 600ms+,首屏 JS 执行严重滞后。
-
rel="preload"必须写在最前面,紧贴<meta charset>后,动态插入或放在<title></title>之后都无效 - 漏写
as="script"会导致 Priority 显示为 Low,等同于没写;写成as="module"或as="fetch"会被忽略 - 如果后续用
<script type="module" src="main.js"></script>加载,preload的href必须完全一致(包括查询参数、大小写、斜杠),否则缓存不复用 - Webpack/Vite 构建产物若含 hash(如
app.abc123.js),需确保preload的 href 与实际输出路径同步,否则缓存失效
as="script" 和 as="modulepreload" 到底该选哪个
取决于你的主入口是否使用静态 import 依赖链。如果 main.js 是 ES 模块,且内部有 import { render } from './core.js' 这类同步导入,rel="preload" 只下载 main.js,子模块仍要等解析后才请求——多轮 RTT 延迟不可避免。
此时应换用 rel="modulepreload":
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
-
modulepreload会预解析main.js并递归预取所有静态import的依赖(如core.js、router.js) - 不能加
as属性,加了反而被忽略 -
href必须和最终type="module"标签里的路径完全一致(含查询参数) - 多个
modulepreload标签无执行顺序依赖,但必须全部出现在首个<script type="module"></script>之前
预加载 CSS 和字体时最容易踩的坑
预加载 main.css 或 inter-bold.woff2 表面简单,但错一个属性就静默失效——Network 面板里 Initiator 显示为 (Other)、Priority 是 Low,就是典型信号。
- CSS 预加载必须配
as="style"(不是"stylesheet"),且要手动切换:<link rel="preload" href="main.css" as="style" onload="this.onload=null;this.rel='stylesheet'"> - 字体必须同时写
as="font"和crossorigin(即使同源也得加),否则 Chrome/Safari 加载完直接丢弃 - 字体
href必须和@font-face中src的 URL 完全一致(含 CDN 域名、版本号、查询参数) - 不要对已用
<link rel="stylesheet">声明过的 CSS 再 preload,浏览器可能因路径细微差异(比如多一个/)触发二次请求
别让 preload 变成性能拖累
preload 不是越多越好。它抢占有限的并发连接数(通常 6 个)和带宽,瞎加反而拖慢首屏。只对「当前页首屏立刻需要、且 HTML/CSS/JS 里还没自然声明」的资源生效。
- 适合:
@font-face引用的 WOFF2 字体、内联<style></style>里的 hero 图背景 URL、紧跟<script type="module"></script>的主 chunk - 不适合:
analytics.js、非首屏轮播图、第三方 widget、所有路由 chunk(这些该用rel="prefetch") - SSR 场景下,服务端注入的
preload若与客户端 hydration 时动态插入的重复,可能双下载 - 已缓存的资源,
preload仍会触发一次 HTTP HEAD 请求(Chrome 表现),纯属浪费
真正关键的不是“有没有加 preload”,而是“加的那条是否真被首屏用到、是否路径和类型完全匹配、是否挤占了更急需的资源通道”。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










