Cache-Control设置不当会导致HTML长期不更新;正确策略是:静态页设max-age=300,动态页用no-cache+ETag验证,敏感页用no-store,且必须通过响应头而非meta标签配置。

Cache-Control 设置不当会导致 HTML 永远不更新
直接给 index.html 配 Cache-Control: public, max-age=3600 是最常见也最危险的操作。它会让浏览器在 1 小时内完全跳过服务器请求,哪怕你刚在 CMS 里改完标题,用户刷新看到的仍是旧内容。根本原因在于:HTML 几乎从不带 ETag 或 Last-Modified 做协商验证,强缓存一开,就彻底失去“更新感知”能力。
真正起效的策略不是“缓存 HTML”,而是“让 HTML 的变更能被浏览器立刻察觉”。这需要组合动作:
- 对纯静态 HTML(如文档站首页),设
max-age=300(5 分钟)足够平衡 CDN 回源压力和更新及时性 - 对含少量动态片段的页面(比如用
htmx加载评论),用no-cache—— 它强制每次发请求,但允许服务器返回304 Not Modified,节省带宽又不失控制权 - 对仪表盘、订单页这类含敏感或实时数据的页面,必须用
no-store,禁止任何环节缓存 - 切忌在 HTML 里写
<meta http-equiv="Cache-Control" content="...">—— 现代 Chrome/Firefox/Edge 全部忽略,只当没写
ETag 是 HTML 缓存更新的安全兜底
光靠 max-age 不行,必须配 ETag 才算完整。服务器生成 HTML 时,应基于内容计算哈希(如 SHA-256),作为 ETag 值返回。这样即使设置了 max-age=3600,用户在缓存期内再次访问,浏览器仍会发带 If-None-Match 的请求;内容一变,ETag 就不同,服务器返回 200 OK 和新 HTML,否则返回 304。
注意:Last-Modified 精度只有秒级,且依赖文件系统时间戳,在 SSR 或模板渲染场景下容易失效;ETag 是内容级标识,更可靠。
使用 PptxGenJS 和 Python 解析,将结构化的 HTML/CSS 幻灯片内容转换为原生、可编辑的 PowerPoint(.pptx)演示文稿。
立即学习“前端免费学习笔记(深入)”;
Nginx / Express 中设置缓存头的实际写法
配置必须落在 HTTP 响应头,不能靠前端代码或 meta 标签。不同环境写法差异明显,容易漏掉关键点:
- Nginx 中,
location = /index.html块里加:add_header Cache-Control "public, max-age=300";—— 注意要用=精确匹配,避免误配到其他路径 - Express 中,不能只在路由里写
res.set('Cache-Control', '...'),得确保它在所有可能出口路径上都执行,尤其要覆盖res.sendFile()和中间件异常分支 - CDN(如 Cloudflare、阿里云)通常会覆盖源站
Cache-Control,必须在 CDN 控制台单独配置 HTML 类型的缓存规则,不能只信后端 header - GitHub Pages、Vercel 等静态托管平台默认对 HTML 返回
no-cache,需显式配置_headers或vercel.json文件才能生效
URL 版本化只适用于构建产物,不适用于普通 HTML
给 main.js 加哈希命名(如 main.a1b2c3d4.js)是安全的长期缓存手段,但把它套用到 index.html 上行不通——除非你每次构建都生成带哈希的新 HTML 文件(如 index.abc123.html),并用服务端重定向或入口 HTML 动态加载它。普通 CMS 或手写 HTML 没这机制,硬加 ?v=1.2.3 参数反而可能被代理或 CDN 忽略,或导致 SEO 重复内容问题。
更现实的做法是:把 HTML 当作“索引”,把 CSS/JS/img 当作“资产”。HTML 本身缓存周期短甚至不缓存,而资产用 immutable + 长期 max-age,这才是当前主流框架(Vite、Next.js、Remix)的真实做法。


















