HTML文件本身不参与版本控制,真正起作用的是服务端缓存头、构建产物哈希命名及Service Worker缓存名;注释或<meta name="version">对缓存零影响,因浏览器不解析HTML文本作为缓存依据,且不会触发重新验证。

HTML 文件本身不参与版本控制,真正起作用的是服务端返回的缓存头、构建产物的哈希命名,以及 Service Worker 中的缓存名。靠改 index.html 里的注释或 <meta name="version"> 完全无效。
为什么 HTML 文件不能靠内容写版本号
浏览器不会解析 HTML 文档里的任意文本作为缓存依据。你写 <!-- v2.1.0 --> 或 <meta name="app-version" content="2.1.0">,对缓存行为零影响。它既不改变请求 URL,也不触发重新验证,更不会让浏览器拒绝使用磁盘缓存副本。
常见错误现象:index.html 已发布新版,但用户刷新后仍是旧 DOM;Network 面板里状态是 200 (from disk cache),说明浏览器压根没发请求——连看新版本的机会都没有。
- HTML 是 SPA 的“调度器”,它决定加载哪个带哈希的
main.a1b2c3.js;一旦被强缓存,后续所有资源更新都失效 -
<meta http-equiv="Cache-Control">在现代浏览器中被完全忽略,不是“可能不生效”,而是“明确不解析” - 本地用
file://协议打开时,根本没有 HTTP 头,任何缓存逻辑都不启动
Nginx / Apache / CDN 中对 HTML 的缓存头必须设为 no-cache
核心原则:HTML 必须禁用强缓存,启用协商缓存。否则用户永远卡在旧入口,新 JS/CSS 路径根本进不来。
立即学习“前端免费学习笔记(深入)”;
正确配置示例(Nginx):
location = /index.html {
add_header Cache-Control "no-cache, must-revalidate, max-age=0";
add_header ETag "";
expires epoch;
}-
no-cache不等于“不缓存”,而是每次使用前必须向服务器校验(发带If-None-Match的请求) - 空
ETag让 Nginx 自动基于文件内容生成哈希值,比Last-Modified更可靠 -
expires epoch确保强缓存彻底关闭;若漏写,某些 upstream 会覆盖掉add_header - CDN 必须同步设为“绕过缓存”或 TTL ≤ 60s,否则 CDN 会把源站的
no-cache当耳旁风,自己缓存 10 分钟
Service Worker 缓存名必须带构建版本,且与 HTML 更新联动
如果你用了 Service Worker,caches.open('pages') 这种固定名字是最大隐患。旧缓存不会自动清,新 SW 写入时可能冲突,导致离线白屏或 Request failed 错误。
推荐做法:
- 缓存名格式统一为
pages-${VERSION},其中VERSION来自构建环境变量(如 Vite 的import.meta.env.VITE_APP_VERSION) - 每次发布,
sw.js文件内容必须有变化(哪怕只加个注释),否则浏览器不会触发更新流程 -
install阶段显式调用cache.addAll(['/index.html', '/offline.html']),确保最新 HTML 进入新缓存 -
activate阶段只删不在CURRENT_CACHES列表里的缓存,避免误删当前页面正在用的缓存
构建产物哈希必须落到 JS/CSS 路径上,且服务端配 immutable
HTML 里写的 <script src="/main.a1b2c3.js"></script> 是唯一能触发“版本切换”的地方。但仅靠文件名哈希不够,服务端响应头必须配合:
- JS/CSS 响应头需含
Cache-Control: public, immutable, max-age=31536000 -
immutable告诉浏览器:URL 不变 → 内容绝不变,后续请求可跳过协商缓存直接复用 - 若 CDN 或服务器不支持
immutable,至少要确保ETag严格绑定文件内容(而非修改时间) - Webpack/Vite 构建时,务必用
contenthash(非hash或chunkhash),否则内容未变时哈希也可能变,导致缓存浪费
最易被忽略的一点:即使你把 HTML 缓存头设得再准,只要 Service Worker 预缓存了旧版 index.html,用户就永远看不到新结构——因为请求根本没走到网络层。SW 的更新逻辑、缓存名变更、activate 清理,三者缺一不可。



















