缓存的核心矛盾只有一个:带指纹的静态资源可以缓存一年,HTML 必须快速失效。把 HTML 也设成长缓存,用户会长期停留在旧页面;把静态资源设成短缓存,每次访问都要回源。带回源规则分类设置才是正解。
-
规则条数
-
最长 TTL
-
平均 TTL(秒)
-
可 immutable 条数
| 路径模式 | TTL | 可读时长 | 建议策略 |
|---|
TTL 单位为秒:86400 = 1 天,604800 = 7 天,2592000 = 30 天,31536000 = 365 天。静态资源配合内容哈希文件名时可加 immutable;HTML 与接口响应一律短缓存或直通源站(TTL = 0)。
先分清两类资源,再谈 TTL
缓存配置的第一个决策不是「设多久」,而是「这个文件改名会不会变」。答案决定了两种完全不同的策略:
| 资源类型 | 文件名特点 | 推荐 TTL |
|---|---|---|
| JS / CSS / 字体 | 带内容哈希(app.3f9a2c.js) | 365 天 + immutable |
| 图片 / 视频 | 通常不变,改名才换 | 30 天 |
| HTML 页面 | URL 固定,内容常变 | 0–300 秒 |
| API 响应 | 实时数据 | 0(不缓存) |
带内容哈希的静态资源可以放心缓存一年——因为内容一改,文件名就变了,浏览器请求的是全新 URL,不存在「拿到旧文件」的问题。这就是前端构建工具给文件名加哈希的全部意义。
immutable 是什么
Cache-Control: max-age=31536000, immutable 中的 immutable 告诉浏览器:这个 URL 的内容永不变,连用户手动刷新(F5)都不必回源验证。少一次条件请求,就少一次往返延迟。
反过来说,immutable 绝不能用在文件名固定的资源上——一旦用了,用户按 Ctrl+F5 也拿不到新版本,只能清除浏览器缓存,这是最难排查的一类线上事故。
HTML 为什么必须短缓存
HTML 是所有资源的入口,它引用着带哈希的 JS 和 CSS。如果 HTML 被缓存了 1 天,用户会拿着旧 HTML 去请求已经不存在的旧哈希资源——白屏或功能异常。稳妥做法是 HTML 设 0–300 秒,配合 CDN 的主动刷新(purge)在发布时立刻失效。
两个常见配置错误
- 用路径前缀匹配却忘了顺序:规则按最长/最具体的模式优先,但不同 CDN 的实现细节不同。建议把最具体的规则写在前面,并用实际 URL 验证。
- 只设 max-age 不设 s-maxage:
max-age同时作用于浏览器和 CDN;如果希望 CDN 缓存更久、浏览器稍短,需要单独用s-maxage覆盖。
你可能还想问
各类资源的缓存时长怎么设?
带内容指纹的静态资源可设超长缓存(一年),HTML 入口不缓存或短缓存,接口数据按可容忍的延迟设定(几十秒到几分钟)。
如何让更新及时生效?
标准做法是文件名带哈希(内容变则文件名变),配合刷新入口 HTML;直接刷新全站缓存成本高,应尽量避免依赖强刷。
缓存与回源压力怎么平衡?
缓存命中率越高回源压力越小;对动态内容用短缓存加 stale-while-revalidate,可在保证新鲜度的同时削峰。
速查在线工具箱