确保模块 URL 变更并配合理缓存头才能更新 ESM:构建时用内容哈希命名(如 utils.a1b2c3.js),HTML 入口也加哈希;带哈希资源设 Cache-Control: public, max-age=31536000,HTML 设短缓存;用 modulepreload 预加载关键模块;动态 import 优先静态路径。

ES Modules(ESM)本身不控制缓存,浏览器是否加载新版本 JS 文件,完全取决于模块 URL 是否变化、服务端返回的缓存头是否合理,以及模块图解析时的请求行为。更新失效,本质是旧 URL 仍被复用,而服务端未提供新内容或浏览器跳过了请求。
确保模块 URL 变更才能触发新请求
浏览器按完整 URL 缓存模块,路径不变就永远读旧缓存。静态路径如 ./utils.js 极易卡在强缓存里,哪怕文件已更新。
- 构建时生成带内容哈希的文件名,例如
utils.a1b2c3.js,每次内容变更 URL 就不同,天然绕过旧缓存 - 避免用查询参数如
utils.js?v=1.2.0:CDN 或代理常忽略 query,导致缓存未刷新却仍返回 304 或旧响应 - HTML 中入口模块(如
<script type="module" src="main.js">)也建议加哈希,否则整个模块图都基于旧入口启动
服务端必须配对合理的 Cache-Control 策略
仅改文件名不够,还得让浏览器知道“这个带哈希的文件可以长期缓存”。否则即使 URL 新了,也可能因缓存头太短,下次又走协商缓存,拖慢加载。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 对带哈希的静态模块资源,设
Cache-Control: public, max-age=31536000(一年),让浏览器直接复用,不发任何请求 - 对 HTML 入口页,应设短缓存(如
max-age=0, must-revalidate)或禁用强缓存,确保每次都能拿到最新src地址 - 避免全局设
no-cache或no-store:前者增加 RTT 校验开销,后者彻底放弃缓存优势,加载变慢
利用 modulepreload 提前激活关键模块缓存
模块图首次解析时,浏览器仍需发起网络请求获取入口模块,再逐层 import。这期间无法跳过网络,但可提前把关键依赖拉进缓存。
立即学习“Java免费学习笔记(深入)”;
- 在 HTML head 中添加:
<link rel="modulepreload" href="core.js">,让浏览器在解析 HTML 阶段就并发请求并缓存 - 预加载的模块若带哈希且缓存头正确,后续 import 语句会立即命中 HTTP 缓存,不阻塞执行
- 注意不要 preload 过多非首屏模块,否则浪费带宽,反而影响首屏性能
动态 import 要保持 URL 一致性与可缓存性
用 import() 按需加载时,如果路径含变量(如 import(`./pages/${page}.js`)),构建工具可能无法静态分析,导致哈希失效或缓存策略错配。
- 优先使用静态字符串路径,便于打包工具提取、哈希、拆包
- 若必须动态,确保服务端对所有可能路径都配置了相同的长缓存策略,并验证实际响应头
- 避免在路径中拼时间戳或随机数,那会让每次请求都变成“新 URL”,完全失去缓存价值

















