做站点运营,缓存是个两面派。用得好,静态资源直接从访客浏览器或 CDN 返回,服务器压力小、首屏快;用得不好,运营和编辑就会陷入一种困惑:后台明明改了,前台还是老样子,只能靠“强制刷新”安慰自己——而真实访客不会替你按 Ctrl+F5。
先分清两类资源
排查缓存问题之前,先把站内资源分成两类,它们的策略完全不同。
- 带指纹的静态资源:CSS、JS、图片、字体,文件名里带一串哈希或版本号,比如 app.3f9a2c.css。这类文件内容变了文件名就变,可以放心长缓存。
- HTML 文档和接口响应:URL 固定,内容却经常变,缓存时间要短,或者干脆走协商缓存。
很多“改了不生效”的锅,其实是 HTML 被长缓存,而不是 CDN 出问题。先看首页 HTML 的响应头,再往下查。
看响应头,而不是猜
用浏览器开发者工具的 Network 面板或命令行工具查看响应头,重点看这几项:
- Cache-Control:max-age 是浏览器缓存秒数;s-maxage 针对 CDN 等共享缓存;public / private 决定能不能被中间节点缓存;no-store 表示完全不缓存。
- ETag / Last-Modified:给 HTML 用的协商缓存字段。访客再次访问时会带条件请求,内容没变就返回 304,省流量又不至于看到旧内容。
- Expires:老字段,和 Cache-Control 冲突时以后者为准,建议只留一个。
- Vary:涉及压缩、语言、设备适配时,写错会导致缓存串味,A 用户的页面被发给 B 用户。
常见的建议写法是:静态资源 max-age 设一年并配合 immutable;HTML 设几分钟到一小时的 max-age,同时保留 ETag。注意不要给 HTML 配 immutable,那等于告诉浏览器“永远别问服务器”。
CDN 这一层要单独看
即使源站响应头写对了,CDN 也可能按自己的规则缓存。需要确认几件事:
- 缓存键包含哪些内容:只看 URL,还是把查询参数也算进去?营销参数、跟踪参数是否被忽略?
- 哪些路径会被缓存:通常只缓存静态资源目录,不要整站通吃,尤其别缓存后台和登录态页面。
- 回源规则与刷新方式:发布后是等自然过期,还是主动刷新指定目录。
如果站内有登录态、地域差异或灰度分流,务必确认共享缓存不会把已登录页面发给未登录访客,这类问题排查起来最费时间。
更新流程里加一道检查
缓存问题的根源往往不在配置,而在发布流程。把下面几步固定下来,能省掉大部分重复沟通:
- 改 CSS / JS 时,同步更新文件名或版本参数,而不是靠刷新缓存解决。
- 发布后打开无痕窗口访问一次首页和一个栏目页,确认内容已更新;再用工具请求一次,确认响应头符合预期。
- 变更模板或全站公共组件时,提前安排一次缓存刷新,并通知相关同事,避免他们反复提交“页面没更新”的问题。
- 把缓存相关的改动记录在发布单上,出问题时能快速回滚。
一份简短的缓存自查清单
- 首页和栏目页 HTML 的 max-age 是否过长?
- 静态资源是否都带指纹,是否存在长期不变的文件名?
- 是否存在既设 no-store 又想靠 CDN 加速的矛盾配置?
- CDN 是否缓存了带登录态或个性化内容的响应?
- 发布流程里是否包含一次实际访问验证?
缓存配置不需要一次做到完美,先把“改了看不到”和“每次都回源”这两类高频问题理清,再根据访问日志逐步调整过期时间。站点运营的很多细节都是这样:不追求一步到位,但每次动完,都清楚自己改了什么。