HTML设max-age=3600会导致生产事故,因其强缓存跳过验证,使含动态字段(如评论数、token、价格)的页面无法及时更新,CDN还可能错误共享用户数据;应禁用HTML的max-age,改用no-cache, must-revalidate并配合后端ETag校验。

为什么给 HTML 设 max-age=3600 会出生产事故
内容页面(如文章页、商品详情页)看似静态,实则常含动态字段:评论数、CSRF token、登录态昵称、实时价格、时间戳。一旦缓存过期,用户刷新看到的仍是旧 HTML,但服务端数据已变——轻则按钮失效,重则表单提交携带过期 token 导致 403 或越权。
根本原因是 max-age=3600 触发强缓存,浏览器跳过所有验证请求,ETag 和 Last-Modified 完全不生效;CDN 若也缓存了该响应,还可能把带用户信息的 HTML 错误返回给其他访客(private 指令在多数 CDN 上被忽略)。
- 现象示例:
Status列显示200 from disk cache,但页面“已售罄”字样没更新成“补货中” - 常见误配:Nginx 中对
location ~* \.html$直接写expires 1h或add_header Cache-Control "public, max-age=3600" - 修复优先级:先停掉所有 HTML 的
max-age > 0配置,再补协商机制
no-cache 和 max-age=0, must-revalidate 怎么选
两者都强制走协商流程,但行为细节不同:no-cache 允许缓存副本,但每次必须带 If-None-Match 或 If-Modified-Since 向服务端验证;max-age=0, must-revalidate 语义更严格,明确要求“哪怕用户点了强制刷新,也必须校验”,兼容性略好于纯 no-cache(尤其对部分老旧代理)。
- 推荐统一用
Cache-Control: no-cache, must-revalidate—— 简洁、明确、现代浏览器支持完善 - 绝对不要加
private:CDN 节点通常忽略它,等于白写,还可能误导运维以为“已隔离用户数据” - 敏感操作页(如支付确认、账号注销)必须用
no-store,彻底禁用任何中间环节缓存(包括内存缓存)
Nginx 中如何正确配 HTML 协商缓存
关键不是只加 Cache-Control,而是让它和 ETag 协同工作。Nginx 默认的 ETag 基于文件修改时间和大小生成,对动态 HTML 不适用(比如 PHP/Node 输出的内容,mtime 不变但内容常变)。
立即学习“前端免费学习笔记(深入)”;
正确配置需两步:关掉默认 ETag,再由后端输出真实内容哈希(或让 Nginx 基于响应体计算):
location ~* \.html$ {
add_header Cache-Control "no-cache, must-revalidate";
etag off;
add_header ETag "";
}-
etag off禁用 Nginx 默认 ETag,避免和后端冲突 -
add_header ETag ""让 Nginx 对响应体做 MD5 哈希生成 ETag(需开启http块中的etag on,但此处显式关闭后又空值触发体哈希) - 若后端能稳定输出
Content-MD5头,可直接用它设为 ETag,更可控 - 验证方式:DevTools Network → 找 HTML 请求 → 看
Status是否为304 Not Modified
静态资源缓存才是提速主战场
HTML 文件本身通常不到 50KB,而它引用的 main.a1b2c3.js、style.b4c5d6.css、首屏图片才占体积大头。这些资源变动少、可预测,才适合激进缓存。
- 构建时必须启用内容哈希:Webpack/Vite 都支持
contenthash,确保文件内容一变 URL 就变 - Nginx 配置要配合
immutable:add_header Cache-Control "public, immutable",让浏览器后续访问跳过验证请求 - 危险操作:给无哈希的
main.css配immutable—— 改了样式但 URL 不变,用户永远拿不到新版本 - CDN 缓存策略必须和源站响应头一致:源站返回
no-cache,CDN 后台却开了自动缓存,就会导致 HTML 版本错配
真正容易被忽略的是协同断点:开发者改了 Nginx 的 Cache-Control,但忘了同步调整 CDN 控制台的缓存规则;或者构建工具没开 contenthash,却在 Nginx 里写了 immutable。缓存问题从来不是单点配置,而是全链路对齐。



















