modulepreload不会打断递归加载,仅提前触发模块及其静态import依赖的fetch和parse,解决请求发起时机而非执行顺序;需手动预加载所有关键路径模块,严格匹配路径、CORS及URL完整性。

modulepreload 不会打断递归加载,但能提前触发依赖 fetch 和 parse
它解决的不是“执行顺序”,而是“请求发起时机”问题。浏览器默认在解析到 import 语句时才发起网络请求,形成瀑布链;modulepreload 把这个动作提前到 HTML 解析阶段——只要模块路径已知,就能并行拉取,包括其静态 import 的所有字面量路径依赖。
但注意:它不改变模块图拓扑,也不跳过执行时机。比如 main.js 里写了 import './utils.js',即使你 preload 了 main.js,utils.js 只有在 main.js 被真正 import 或执行到该行时才会进入链接(linking)和求值(evaluation)阶段。
- 必须手动预加载所有关键路径上的模块,包括深层嵌套的(如
chart.js → d3.js → wasm-loader.mjs) - 只对静态
import生效,import('./foo.js')或import(`./${name}.js`)完全无法被识别 - 如果某个预加载模块返回 404 或 MIME 类型不是
application/javascript,整个依赖链展开会中断
href 路径必须与实际 import 路径完全一致,包括查询参数和协议
浏览器按完整 URL 去重,/a.js 和 /a.js?v=1.2.3 被视为两个资源。Vite/Webpack 构建产物带 hash(如 main.abc123.js)时,手动写死 href 几乎必然失效。
- 相对路径(
./utils.js、../lib/index.js)不被支持,必须用根相对路径(/assets/utils.js)或绝对 URL - 跨域模块必须配
crossorigin属性,且值要和对应<script type="module">标签一致(anonymous/use-credentials/ 空字符串) - 不能用裸 specifier(如
lodash),必须是构建后解析出的真实路径(/node_modules/lodash-es/index.js) - 服务端需返回正确的
Access-Control-Allow-Origin,否则预加载静默失败,后续import直接报 CORS 错误
modulepreload 和 preload 的核心区别:是否理解模块图
rel="preload" 是通用下载指令,只管拉文件;rel="modulepreload" 是模块图感知的,会真实解析 JS 内容,扫描顶层 import 语句,并递归发起依赖请求——前提是这些路径也出现在其他 modulepreload 标签中。
-
rel="preload" as="script"加了as="script"才生效,漏写就降为低优先级 fetch -
rel="modulepreload"明确禁止as属性,加了直接被忽略(最常踩的坑) - 二者不能混用同一模块:既
preload又modulepreload,可能因缓存 key 不一致导致重复请求 - 对非模块脚本(
type="text/javascript")用modulepreload无效,浏览器直接跳过
Vite/webpack 自动化生成 modulepreload 的实操要点
手写易漏、难维护,尤其在动态 import 或多入口场景下。构建工具能提取 AST 中所有静态 import,但仍有边界限制。
- Vite 默认开启
build.modulePreload: { polyfill: false },但只处理直接依赖,不包含条件分支或export * from暴露的深层模块 - Webpack 需配合
experiments.outputModule: true和插件(如webpack-module-preload-plugin)导出模块图 - 如果用了
import map,预加载的href必须和 import map 解析后的最终 URL 一致(例如映射"lodash": "/node_modules/lodash-es/index.js",则 preload 的 href 就得写后者) - 内联模块(
<script type="module">...)无法被modulepreload处理,它只支持外部模块
真正起效的点不在“加了多少个”,而在“是否覆盖了首屏关键路径上所有静态可达模块”。漏掉一个深层依赖,瀑布链就从那里重新开始。构建产物路径变动、CORS 配置不一致、href 字符串微小差异——这些细节比语法本身更容易让优化失效。


















