s-maxage:被漏掉最多的一行缓存配置

只写 max-age 会把边缘缓存和浏览器缓存绑在同一个时长上。而这两者合适的时长几乎从来不同——浏览器缓存发出去就召不回,边缘缓存随时可刷。

6 分钟缓存与命中
s-maxage:被漏掉最多的一行缓存配置

要点

用 s-maxage 放长边缘 TTL、用 max-age 收短浏览器 TTL,既提高命中率又保留随时刷新的能力。

本文目录
  1. 01两种缓存的根本不对称
  2. 02两条指令怎么配合
  3. 03什么时候该用 immutable

两种缓存的根本不对称

边缘缓存和浏览器缓存看起来是同一件事的两级,实际有一个决定性差别:边缘缓存你能主动刷,浏览器缓存你不能。

发现线上文件有问题时,边缘副本可以��控��台里一键刷新,几十秒内全网生效。但已经进了用户浏览器的副本,在 max-age 到期前无论如何都不会再来问你——哪怕你已经修好了。

这个不对称的后果

max-age=2592000(30 天)意味着一次错误发布,最坏情况要在部分用户那里挂 30 天。而 s-maxage=2592000 配 max-age=3600 能拿到几乎一样的命中率,事故窗口却只有 1 小时。

两条指令怎么配合

指令谁读它不写时的后果
max-age浏览器与边缘都读两者都退回厂商默认策略
s-maxage只有边缘(共享缓存)读边缘被迫沿用 max-age 的值

关键在最后一行:s-maxage 存在时,边缘优先用它,浏览器仍然用 max-age。两侧因此可以分开调。

# 边缘存 30 天,浏览器只存 1 小时
cache-control: public, s-maxage=2592000, max-age=3600

这一行的效果是:绝大多数请求由边缘的长副本命中(命中率高、回源少),而任何一次紧急修复最多 1 小时就能全量覆盖。

什么时候该用 immutable

如果文件名里带内容哈希(如 app.4f2a1c.js),文件内容永不改变——改的是文件名。这时上面的顾虑不存在,可以放心用最长 TTL:

cache-control: public, max-age=31536000, immutable
  • immutable 额外告诉浏览器:连「刷新页面时顺便验证一下」都不必做;
  • 没有它,用户按刷新键仍会为每个文件发一次条件请求(304),白付一次往返延迟;
  • 但这一切的前提是文件名真的带哈希——对 index.html 用 immutable 是灾难。

在你的网站验证

边缘核验解析你的 cache-control,并指出 s-maxage 是否缺失