Cache-Control: public 表示资源可被浏览器、CDN及所有中间代理缓存,适合公开静态资源;private 表示仅用户浏览器可缓存,禁止共享缓存,适用于含用户上下文但非敏感的内容。

浏览器对 Cache-Control: public 和 private 的理解本身没有“偏差”,但实际行为差异常被误读,根源在于缓存层级(浏览器 vs 代理/CDN)和用户操作方式(回退、刷新、新开页)的组合影响。Nginx 配置需明确意图、匹配资源特性,并辅以合理指令组合,才能让行为可预期。
区分 public 与 private 的真实作用范围
public 表示响应可被**任意中间节点缓存**:浏览器、公司代理、CDN、ISP 缓存等都可存储并复用。适合完全公开、无用户状态的资源,如 logo.png、vendor.js。
private 表示响应**仅允许最终用户的浏览器缓存**,禁止共享缓存(如 CDN 或反向代理)存储。适合含用户上下文但不敏感的内容,如个人头像 URL、带用户 ID 的 CSS 主题文件。
常见误解是认为 private = “不缓存”或 “后退时一定重发请求”——其实只要没过期,浏览器后退、前进、地址栏回车都直接读缓存;只有新开窗口或显式刷新才可能触发新请求(取决于是否带 max-age)。
避免典型行为错位的 Nginx 配置写法
以下配置基于实际生效逻辑,而非仅看指令字面:
- 静态资源(JS/CSS/图片)用
public, immutable, max-age=31536000:明确允许全链路缓存,且内容不变(immutable告诉浏览器无需验证 ETag/Last-Modified) - 用户专属接口(如
/api/user/settings)用private, max-age=600:浏览器可缓存 10 分钟,但 CDN 不得缓存;后退/前进直接读本地缓存 - 需强一致的动态数据(如
/api/order/status)用no-cache, max-age=0, must-revalidate:允许浏览器暂存,但每次使用前必须向服务器发起条件请求(If-None-Match / If-Modified-Since),确保内容最新 - 含支付、身份凭证的路径(如
/api/payment/confirm)用no-store, no-cache, must-revalidate:彻底禁用任何存储,连内存/临时目录都不留痕迹
验证缓存行为是否符合预期
不要只看响应头是否写出,要观察真实交互:
- 用 Chrome DevTools → Network 标签,勾选 “Disable cache” 对比有无缓存时的请求发起情况
- 测试三种操作:① 地址栏回车 ② 点击浏览器后退按钮 ③ Ctrl+T 新开标签页访问同一 URL —— 每种场景下查看是否发出新请求、状态码是 200 还是 304
- 若部署了 CDN(如 Cloudflare),需确认其未覆盖或忽略你设置的
Cache-Control;部分 CDN 默认强制 public 或忽略 private,需在 CDN 控制台单独配置缓存规则
补充说明:max-age 是行为关键变量
public 或 private 单独存在意义有限,真正决定“是否发请求”的是 max-age 值:
-
private, max-age=0:浏览器可缓存,但每次使用都需验证(类似 no-cache) -
private, max-age=300:5 分钟内后退/回车均不发请求;超时后首次使用会发验证请求 -
public, max-age=86400:CDN 和浏览器都可缓存一天;CDN 可能直接响应,用户看不到源站请求
不设 max-age 时,浏览器行为依赖 Last-Modified 或 Expires,容易不可控。建议始终显式设置 max-age。











