Cache-Control: no-cache 配合 ETag 是唯一可靠组合,因 no-cache 强制每次使用前验证,ETag 作为内容强相关哈希(如 MD5/SHA256)确保资源一变缓存立即失效;max-age=0 语义模糊且可能被中间代理忽略,不如 no-cache 严格可靠。

Cache-Control + ETag 是唯一可靠组合
HTML 文件无法靠时间戳“准时过期”,max-age 依赖客户端时钟,Expires 更不可靠。真正能实现“资源一变、缓存立刻失效”的,只有 Cache-Control: no-cache 配合服务器返回的 ETag 响应头。浏览器每次发起请求时,会自动带上 If-None-Match(值为之前收到的 ETag),服务端比对后决定返回 200 还是 304。
关键点在于:no-cache 不是禁止缓存,而是强制走验证流程;ETag 必须是内容强相关哈希(如文件内容 MD5/SHA256),不能用最后修改时间或随机值。
- Webpack/Vite 构建 HTML 时,若用插件生成 contenthash(如
html-webpack-plugin的templateContentHash),可确保 HTML 内容变则ETag变 - Nginx 默认开启
etag on,但需确认未被add_header ETag ""覆盖 - Node.js(Express)中不要手动设
res.set("ETag", Date.now())——这会让 ETag 失去内容指纹意义
CDN 层必须透传并校验 ETag
很多缓存问题出在 CDN 没有真正执行协商缓存。即使源站返回了 ETag 和 Cache-Control: no-cache,CDN 若配置为“忽略 If-None-Match”或“强制回源不带校验头”,就等于废掉了整套机制。
验证方式:在 DevTools Network 中查看 HTML 请求的 Request Headers 是否含 If-None-Match,Response Headers 是否含 ETag,且状态码为 304 Not Modified。
- Cloudflare:需开启 “Origin Cache Control” 并确保 “Browser Cache TTL” 设为 “Respect Origin”
- AWS CloudFront:Behavior 设置里勾选 “Whitelist Headers” 并加入
If-None-Match,同时关闭 “Cache Based on Selected Request Headers” 的简化模式 - 自建 Nginx 作 CDN 边缘节点:必须配置
proxy_cache_revalidate on,否则默认跳过验证直接回源
HTML 文件名哈希化在部署侧更彻底
协商缓存依赖服务端实时计算和比对,仍有延迟和失败可能。对 HTML 本身而言,最精准的失效方式其实是让它“变成新资源”——即构建时重命名 index.html 为 index.8f3a2d.html,并同步更新入口链接(如 CDN 回源路径、Nginx try_files 规则)。
实现 Markdown↔ HTML 互转,支持导出 PDF,用于用户请求的文档格式转换。
这绕过了所有 HTTP 缓存逻辑,因为 URL 变了,浏览器天然视为全新请求,不会复用任何旧缓存。
- Vite 用户需配
build.rollupOptions.output.entryFileNames和build.rollupOptions.output.chunkFileNames,但注意:HTML 文件本身不参与 rollup 打包,需用插件如vite-plugin-html注入哈希 - Netlify/Vercel 等平台不支持直接哈希 HTML 文件名,此时必须退回到
Cache-Control: no-cache, must-revalidate+ETag组合 - 若使用
htmlcode.fun类托管服务,它不提供构建时重命名能力,也无服务端配置权,唯一可控手段就是每次部署后手动加版本查询参数(如index.html?v=20261010),但要注意部分 CDN 会忽略 query string 缓存键
为什么 max-age=0 不如 no-cache
max-age=0 表面看也是“立即过期”,但它属于强缓存失效路径,触发的是条件 GET(If-Modified-Since 或 If-None-Match),而语义上并不强制要求验证——某些老旧代理或中间网关可能直接返回过期副本。相比之下,no-cache 是 HTTP/1.1 明确定义的指令,明确要求“每次使用前必须验证”,浏览器和主流 CDN 都严格遵守。
- Chrome/Firefox/Safari 对
no-cache的处理一致:必发带校验头的请求,不走 memory/disk cache 直接复用 -
must-revalidate应始终与no-cache同用,防止用户手动跳过验证(比如禁用 JS 后的离线场景) - 别混用
no-cache和no-store:后者禁止一切缓存,连内存都不许存,对首屏加载性能伤害明显,HTML 完全不需要
精准失效不是靠一个头、一种配置就能搞定的事,它横跨构建、部署、CDN、源站四层。最容易被忽略的是 CDN 是否真正转发了 If-None-Match,以及 ETag 是否真的随内容变化——这两点一错,整个机制就形同虚设。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










