关键在于max-age与s-maxage各司其职:max-age控制浏览器缓存时长,s-maxage专用于CDN且覆盖max-age;二者需共存,不可替代,且须配合public/private等指令及稳定验证机制。

关键不是“怎么设数值”,而是让 max-age 和 s-maxage 各司其职:前者管浏览器,后者管 CDN,两者必须共存、不能互相替代。
max-age 是给浏览器看的“个人缓存时限”
它决定用户本地浏览器能直接读缓存多久,不发请求。适合控制个性化或轻量变动的内容:
- HTML 入口页建议设短一点,比如
max-age=60(1 分钟),避免用户卡在旧版页面; - 静态资源(JS/CSS/图片)若带内容哈希(如
app.a3f2.js),可设很长,比如max-age=31536000(1 年); - 设了
private的响应(如含用户信息的 HTML),max-age仍生效,但 CDN 通常会忽略它——所以别指望靠它控制 CDN。
s-maxage 是给 CDN 看的“共享缓存权威指令”
它覆盖 max-age,专为代理层(Cloudflare、Fastly、阿里云 CDN 等)设计,告诉它们:“你最多缓存这个时长,之后必须走验证流程”。
- 必须搭配
public(或至少不带private),否则 CDN 可能直接拒存; - 例如,API 返回的通用列表页,CDN 可缓存 5 分钟:
s-maxage=300; - 如果只写
max-age=300却没写s-maxage,CDN 可能因响应头含private或自身策略而跳过缓存。
典型组合写法与含义
正确写法要清晰、无歧义,且两个字段同时存在:
立即学习“Java免费学习笔记(深入)”;
-
Cache-Control: public, s-maxage=300, max-age=60
→ CDN 缓存 5 分钟,浏览器只缓存 1 分钟; -
Cache-Control: public, s-maxage=300, max-age=60, stale-while-revalidate=600
→ CDN 过期后还能继续返回旧内容 10 分钟,并后台悄悄刷新; -
Cache-Control: private, max-age=300
→ 浏览器缓 5 分钟,CDN 不缓(private明确禁止共享缓存)。
容易踩的坑
这些配置看似简单,但漏掉细节就会失效:
- 数值必须是整数秒,不能加引号或单位,如
s-maxage="300"是无效的; - 源站响应必须稳定提供
ETag或Last-Modified,否则 CDN 验证阶段无法返回 304,导致带宽浪费和缓存误更新; - 不要用查询参数(如
?v=1.2.0)代替哈希文件名——多数 CDN 默认忽略 query string,缓存会混乱。


















