HTML必须禁缓存而JS/CSS需强缓存:Nginx中对.html文件配置expires -1及no-store等响应头,确保每次获取最新HTML;构建时启用contenthash并由工具生成HTML,避免路径错误;上线前下线旧HTML,并可通过URL时间戳增强保障。

移动端 App 内嵌 H5 页面时,最让人头疼的不是 JS 报错或样式错乱,而是 index.html 被 WebView 死死缓存,导致新版本上线后白屏、404、功能失效。根本原因在于:HTML 文件一旦被缓存,后续所有相对路径引用的 JS/CSS(哪怕带了 hash)都会按旧 HTML 里的地址去请求——而旧地址在服务器上早已被删掉。
关键矛盾:HTML 必须不缓存,JS/CSS 必须强缓存
这是缓存策略的黄金配比:
- HTML 文件必须禁止缓存:每次访问都应向服务器发起真实请求,确保拿到最新版 index.html;
- JS/CSS/图片等静态资源必须强缓存:靠文件名哈希(如 app.a1b2c3.js)保证内容不变则复用,变则换名,浏览器自动更新;
- 如果 HTML 缓存了,哪怕 JS 名字变了,它还是按旧 HTML 里写的旧名字去请求——结果就是 404 白屏。
Nginx 配置:精准控制 HTML 不缓存
仅靠前端加 meta 标签或 URL 时间戳,在 App 的 WebView(尤其是 iOS WKWebView、Android 系统 WebView)中基本无效。真正可靠的方案是服务端强制响应头控制。在 Nginx 配置中针对 HTML 文件做如下设置:
location ~* \.html$ {
expires -1;
add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0";
add_header Pragma "no-cache";
add_header Expires "0";
}
注意:
• 不要用 location / 全局配置,否则会把 JS/CSS 也禁缓存,拖慢二次加载;
• 必须用正则匹配 \.html$,确保只作用于 HTML;
• no-store 比 no-cache 更彻底,连协商缓存都跳过,适合 App 场景。
配套动作:构建与发布不能“裸奔”
光靠 Nginx 不够,前后端需协同:
- Webpack/Vite 打包开启
filenameHashing: true(Vue CLI 默认开启),确保 JS/CSS 文件名含 contenthash; - HTML 必须由构建工具生成(如 html-webpack-plugin),避免手写 script 标签硬编码旧路径;
- 上线前确认服务器旧版本 HTML 已下线——否则即使不缓存,也可能命中旧 HTML;
- 若 App 启动时预加载首页,建议 App 端在加载 URL 末尾拼时间戳(如
?t=1746553320),作为双重保险,但不能替代 Nginx 配置。
验证是否生效:看响应头,别信感觉
打开 Chrome DevTools → Network → 刷一次首页 → 找到 index.html 请求 → 查看 Response Headers:
- 必须看到
Cache-Control: no-store, no-cache, ...; - 不能出现
ETag或Last-Modified触发协商缓存; - F5 刷新时,index.html 的 Status 应为
200(非304); - 对比 JS 文件的响应头,应有
Cache-Control: public, max-age=31536000类似长缓存设置。


















