link rel="modulepreload"是专为ES模块设计的预加载机制,提前请求并缓存模块及其依赖链但不执行,需路径、crossorigin、integrity等参数与实际import完全一致才能复用。

什么是 link rel="modulepreload"?
它不是用来预加载普通脚本或样式的,而是专为 ES 模块设计的预加载机制。浏览器遇到 <link rel="modulepreload" href="xxx.js"> 时,会提前发起请求并缓存模块及其依赖(包括 import 链),但不会执行,直到后续被 import() 或静态 import 引用。
为什么不能用 rel="preload" 加载模块?
rel="preload" 缺乏模块语义:它不解析模块图,也不处理 import 依赖链;浏览器把它当普通资源下载后,仍需重新解析、编译、链接才能使用——等于白忙一场。
-
rel="preload"的as值只能是"script",无法声明模块类型 - 遇到
import 'dep.js'时,依然要重新发起网络请求(即使 dep.js 已被 preload) - 模块的
crossorigin、integrity等属性在preload中不生效,导致校验失败或 CORS 错误
怎么写一个有效的 modulepreload?
必须匹配模块实际加载时的完整参数,否则浏览器不会复用缓存。关键点:
- 路径必须和
import()或import语句中写的完全一致(含查询参数、大小写) - 如果模块是跨域的,
<link>必须带crossorigin属性,且值要与后续 import 一致(crossorigin、crossorigin="anonymous"、crossorigin="use-credentials"三者互不兼容) - 若模块有 SRI(Subresource Integrity),
<link>必须包含相同integrity值 - 建议放在
<head>顶部,越早越好
示例:
立即学习“前端免费学习笔记(深入)”;
<link rel="modulepreload" href="./utils.js"> <link rel="modulepreload" href="./feature.js" crossorigin="anonymous" integrity="sha256-...">
常见失效场景和排查方法
页面没提速?大概率是预加载没被命中。检查以下几项:
- 控制台 Network 面板里找目标模块,看
Initiator是Other(说明未复用 modulepreload)还是Link(成功复用) - 对比
<link href="...">和import('./...')的字符串是否逐字符相等(比如./a.js≠a.js≠/a.js) - 动态
import()路径含变量时,modulepreload无法覆盖——它只对静态可分析路径有效 - Vite / Webpack 等构建工具生成的 chunk 名含 hash,手动写
modulepreload易过期;应交由构建插件自动注入
模块预加载真正起效的前提,是路径、CORS、integrity 全部严格对齐——差一个字符或一个属性,就退回原始加载流程。



















