HTML modulepreload模块预加载怎么做:HTML模块预加载参考指南

作者:袖梨 2026-06-14
modulepreload 是专为 ES 模块设计的预加载机制,只下载不执行,需绝对路径、与 script src 完全一致、跨域加 crossorigin,不递归加载子模块,须手动声明所有关键依赖。

modulepreload 是专为 ES 模块设计的预加载机制,只下载、不执行,能提前拉取模块及其显式声明的依赖(但不会自动递归抓取 import 链)。它不是 deferasync 的替代品,而是前置下载调度——写对了能省 100–300ms 首屏 JS 延迟;写错了会静默失效,控制台连报错都没有。

怎么写一个有效的 modulepreload 标签

最简可用形式就是一行:<link rel="modulepreload" href="/assets/main.mjs">,但实际项目中必须注意几个硬性条件:

  • href 必须是绝对路径或根相对路径(如 /assets/main.mjs),不能是 ./main.mjs../lib/utils.mjs —— 浏览器直接忽略
  • href 值要和后续 <script type="module" src="...">src 完全一致,包括查询参数(?v=2.1.0 算不同资源)
  • 如果模块托管在 CDN 或跨域服务上(比如 https://cdn.example.com/app.mjs),<link> 必须加 crossorigin 属性,否则预加载被浏览器跳过
  • 不能用它加载非模块脚本(如 type="text/javascript"),会静默失败,不报错也不请求

modulepreload 不会自动加载 import 的子模块

你写了 <link rel="modulepreload" href="/assets/main.mjs">,而 main.mjs 里有 import { helper } from './helper.mjs',浏览器不会自动把 helper.mjs 也拉下来。

  • 必须手动列出所有关键依赖,比如再加一行 <link rel="modulepreload" href="/assets/helper.mjs">
  • 多个 modulepreload 标签建议按执行依赖顺序排列(如先 vendor,再 main),部分浏览器会按序发起请求,利于 TCP 连接复用
  • 手写容易漏、错、过期,真实项目应交由构建工具处理:Vite 默认启用 build.rollupOptions.output.manualChunks + 插件自动生成完整依赖链;Webpack 可配 webpack-preload-plugin;Rollup 需配合 rollup-plugin-module-preload

常见错误现象和验证方式

写了 modulepreload 却没生效,或者控制台报 Failed to load module script,大概率是以下问题之一:

立即学习“前端免费学习笔记(深入)”;

  • 路径不一致:检查 Network 面板里 main.mjs 实际请求的 URL 和 href 是否完全相同(含协议、端口、大小写、查询参数)
  • crossorigin:跨域模块未加该属性时,Network 面板里根本看不到请求,控制台也无提示
  • 模块本身执行时报错(如语法错误、import 路径错),这和 modulepreload 无关,但容易误判为预加载失败
  • 验证是否真正生效:打开 Chrome DevTools → Network → Filter 输入 main.mjs → 查看 Initiator 列是否为 preload,Priority 是否为 Highest

最易被忽略的一点:预加载只是“把字节拉进缓存”,不保证模块就绪。如果你在 DOMContentLoaded 里立刻调用模块导出的函数,仍可能因模块尚未执行而报 undefined —— 执行时机仍由 <script type="module"> 的解析位置决定,modulepreload 不改变这点。

相关文章

精彩推荐