module脚本缓存机制与普通script相同,但因依赖图和URL精确匹配要求更严;重复import同一路径仅发起一次请求,跨页面复用需URL完全一致且服务端配置合理。

module 脚本的缓存行为和普通 script 一样吗
一样,但触发条件更严。浏览器对 type="module" 脚本的缓存机制本身没变——仍是基于 HTTP Cache-Control、ETag、Last-Modified 等标准头;但模块依赖图会让缓存“命中率”实际更高,因为重复 import 同一模块路径(如 './utils.js')时,浏览器只发起一次网络请求,后续全部复用已缓存的模块实例,而不是重新 fetch + 执行。
为什么 import 路径写错会导致缓存完全失效
ESM 模块缓存键是**完整解析后的 URL**,不是文件名。哪怕只是少一个 .js 后缀,或路径中多一个斜杠,都会生成不同缓存键:
-
import { foo } from './utils.js'→ 缓存键:https://example.com/utils.js -
import { foo } from './utils'→ 解析失败,浏览器报Failed to resolve module specifier,根本不会进缓存流程 -
import { foo } from './utils.js?ts=123'→ 缓存键变成带查询参数的 URL,每次变更都算新资源,无法复用
所以路径必须精确匹配,且不能带无意义 query 参数。
多个页面 import 同一个 CDN 模块,能跨页面复用缓存吗
能,但前提是:
立即学习“前端免费学习笔记(深入)”;
- URL 完全一致(协议、域名、路径、大小写、后缀缺一不可)
- 服务端返回了可缓存响应头(如
Cache-Control: public, max-age=31536000) - 没有禁用缓存的 meta 标签或开发者工具勾选 “Disable cache”
例如:import { debounce } from 'https://cdn.skypack.dev/lodash-es@4.17.21/debounce' 在 pageA 和 pageB 中都出现,只要两次请求的 URL 字符串完全相同,Chrome/Firefox/Safari 都会复用同一份缓存,无需二次下载。
动态 import() 的缓存表现和静态 import 有区别吗
没有本质区别。无论 import('./a.js') 还是 import { x } from './a.js',浏览器都按 URL 缓存模块字节码和执行结果。但要注意:
-
import()返回的 Promise resolve 值是模块命名空间对象,不是原始代码——缓存的是模块实例,不是 Promise 对象本身 - 如果
import('./a.js?t=' + Date.now())这样拼时间戳,每次 URL 都不同,缓存彻底失效 - 模块首次被任意方式加载(静态或动态)后,后续所有
import()或静态import都直接返回已实例化的模块,不重新执行顶层代码
真正影响缓存利用率的,从来不是语法形式,而是 URL 稳定性与服务端配置是否合理。



















