modulepreload能提前解析es模块ast并缓存依赖图,而preload仅下载不预解析;modulepreload需满足路径完全一致、跨域加crossorigin、仅支持绝对或根相对路径三个硬性条件。

普通 preload 对 ES 模块的解析优先级没有提升作用——它只下载,不预解析;真正能提前解析模块 AST 并缓存依赖图的,是 modulepreload。
为什么 preload + as="script" 不能加速模块解析
浏览器把 preload 当作通用资源提示,即使 href 指向 .mjs 文件,它也仅发起 fetch 请求、写入通用缓存,不会触发 V8 的模块预解析流程。等到 <script type="module" src="main.mjs"></script> 真正出现时,仍要重新读取字节流、构建 AST、分析 import 语句、递归请求依赖——这些耗时环节一个没少。
-
preload下载后,JS 文件进的是fetch缓存池,不是模块缓存池 - 没有
modulepreload,浏览器无法在 HTML 解析阶段就对模块语法做预处理 - 如果同时写了
<link rel="preload" as="script">和<script type="module"></script>,Chrome 可能重复请求(尤其路径带查询参数不一致时)
modulepreload 必须满足的三个硬性条件
漏掉任意一条,modulepreload 就静默失效,控制台可能完全不报错,但 Network 面板里看不到高优请求。
-
href值必须与后续<script type="module" src="..."></script>的src完全一致(协议、域名、路径、查询参数如?v=2.1.0) - 跨域模块(含 CDN、字体服务、静态托管平台)必须显式加
crossorigin属性,否则浏览器直接忽略该link - 只支持绝对路径或根相对路径(如
/assets/main.mjs),不支持./main.mjs或../vendor.mjs
如何让 modulepreload 真正覆盖整个模块链
modulepreload 不递归,也不自动分析 import 依赖。你写了 main.mjs 的预加载,但若它 import 了 utils.mjs,而你没单独声明后者,那 utils.mjs 仍要等 main.mjs 下载并解析后才开始拉取。
- 按执行顺序排列多个
modulepreload:vendor.mjs在前,main.mjs在后,利于 TCP 连接复用 - 每个被
import的模块都得单独写一行<link rel="modulepreload"> - 手动维护极易出错,真实项目应由构建工具生成:Vite 用户可用
vite-plugin-module-preload,Webpack 可配html-webpack-plugin插件自动注入完整依赖列表
常见失效现象与快速验证方式
最典型的“写了等于没写”,往往发生在路径微小差异或 CORS 配置错位时。不要只看控制台有没有报错,要看 Network 面板里的实际行为。
- 打开 Chrome DevTools → Network → 刷新页面 → 查找对应
.mjs请求 → 点开看Priority列:正常modulepreload应为Highest,若显示Low或根本没出现,说明未生效 - 检查响应头:跨域模块必须返回
Access-Control-Allow-Origin: *(或精确域名),且<link>标签中必须有crossorigin - 对比
href和src字符串是否逐字相等:大小写、斜杠结尾、查询参数顺序、编码格式(如空格是否被转义为%20)都算差异
真正难的不是写对那一行 <link rel="modulepreload">,而是确保整个模块依赖图被完整、精确、可复现地声明出来——这一步手工几乎不可靠,必须交给构建时的静态分析。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











