html入口文件不能强缓存,因其是spa的“启动清单”,硬编码js/css哈希路径;若缓存旧版,将加载错误资源导致白屏或报错;应配置no-cache+etag协商缓存,每次验证后决定返回新html或304。

HTML 入口文件(通常是 index.html)在 SPA 中不能强缓存,必须确保每次访问都能拿到最新版本——否则它引用的 JS/CSS 文件名变了,但 HTML 还是旧的,就会加载错版本资源,引发白屏、报错或功能异常。
为什么 index.html 不能用强缓存?
它是整个应用的“启动清单”。里面硬编码着当前构建生成的 JS/CSS 资源路径(如 app.8a3f2d.js)。一旦浏览器缓存了旧版 HTML,即使服务端已发布新版资源,用户打开页面仍会去请求旧哈希名的 JS,而该文件可能已被删除或内容不匹配。
- 强缓存(如
max-age=31536000)会让浏览器跳过请求,直接复用本地 HTML - 用户刷新页面也不一定更新——尤其在移动端或 Hybrid 场景下,无法强制刷新
- 后果是资源引用错乱:HTML 新 + JS 旧,或 HTML 旧 + JS 新,逻辑断裂
推荐配置:协商缓存(no-cache + ETag)
让浏览器每次访问都向服务器发起条件请求,由服务端决定是否返回新 HTML 或 304 告知复用缓存。这是最稳妥、兼容性最好的方式。
- Nginx 配置示例:
location = /index.html {
add_header Cache-Control "no-cache";
# 不写 max-age=0 或 must-revalidate,语义不如 no-cache 明确
# ETag 默认开启,无需额外配置
} -
no-cache表示“使用前必须验证”,浏览器自动带上If-None-Match请求头 - 服务端比对 ETag 成功即返回 304,不传 HTML 内容,节省带宽;失败则返回 200 + 新 HTML
避免常见陷阱
有些配置看似合理,实际埋下隐患:
- 用
Cache-Control: no-store→ 完全禁用缓存,每次都要下载完整 HTML,增加首屏延迟 - 用
max-age=0, must-revalidate→ 触发冗余验证流程,不如no-cache简洁可靠 - CDN 或反向代理层未透传 ETag 或忽略
Vary头 → 导致不同用户拿到混杂版本 - 构建后未更新 HTML 中的资源路径 → 即使缓存策略正确,内容本身已失效
配合 Service Worker 的注意事项
如果用了 Service Worker,它可能拦截对 index.html 的请求并返回旧缓存,导致版本锁死:
- 在 SW 的
fetch事件中,对 HTML 路径慎用cache-first - 建议改用
network-first或stale-while-revalidate,确保 HTML 总能触达服务端 - 安装新 SW 时调用
self.skipWaiting()和clients.claim(),避免新旧 SW 并存 - activate 阶段清理旧缓存,防止残留过期 HTML 干扰
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











