缓存问题为什么值得单独查一遍
很多人把缓存当成“上线时顺手配一下”的东西,配完就不再回头看。但缓存是少数会同时影响三方的事情:用户、搜索引擎蜘蛛、以及你自己的服务器。用户在弱网下多等几秒,蜘蛛在同样的带宽里少抓几个页面,服务器在流量峰值时多扛一轮无意义的重复请求。
尤其是当站点规模变大、静态资源变多之后,一个配置不当的响应头会被放大成成百上千次重复下载。这不一定是“错误”,但确实是可以省下来的成本。
缓存的目标不是“让所有东西都缓存久一点”,而是让该久留的久留,该立刻更新的立刻更新。
先把资源分成三类
- 带指纹的静态资源:文件名里带内容哈希的 JS、CSS、字体、图片。内容一改,文件名就变,因此可以放心设置很长的缓存时间。
- 入口 HTML 与栏目页:文件名固定,内容会更新,缓存时间要短,或者依赖协商缓存来校验。
- 动态接口与用户相关数据:通常不该被公共缓存,要明确区分公开数据与登录后数据。
分不清这三类,后面的响应头基本是凭感觉写的。分类之后,每一类对应一套配置,问题往往就自己浮出来了。
常见的几类缓存问题
- 一律 no-store:出于“怕缓存出错”的顾虑,把所有响应都设成不缓存,结果是每次访问都完整回源。
- 静态资源缓存时间过短:比如只给了几十秒,等于把长缓存的好处全部放弃。
- HTML 缓存时间过长:内容改了,用户几天后才看到新页面,蜘蛛也一样。
- 文件名没变:CSS 改了内容但路径不变,浏览器继续用本地旧文件,页面样式看起来“改了个寂寞”。
- CDN 缓存没刷新:源站已经更新,边缘节点还在发旧版本,不同地区看到的页面不一致。
- 错误页被长期缓存:一次偶发的 404 或 500 被缓存住,之后一段时间用户和蜘蛛拿到的都是错误响应。
一份可照做的自查清单
- 打开浏览器开发者工具的 Network 面板,刷新页面,看静态资源的 Size 列是否出现“来自缓存”,第二次访问的加载时间是否明显下降。
- 用命令行请求几条代表性 URL 的响应头,确认 Cache-Control、ETag、Last-Modified 是否符合预期,而不是被中间层覆盖。
- 检查静态资源的文件名是否带内容指纹;如果没有,先补上构建流程里的哈希方案,再谈长缓存。
- 检查 HTML 的缓存策略是否足够短,或至少能通过 ETag 及时校验到新版本。
- 确认 404、500 这类错误状态没有被设置成长期缓存。
- 检查 CDN 的缓存规则与刷新流程:更新后由谁触发刷新、多久生效、是否覆盖全部分区节点。
- 观察服务器响应时间,缓存命中率高不高,回源请求是否集中在少数几个地址上。
- 确认压缩是否开启,文本类资源有没有走 gzip 或 brotli,别让体积白白翻倍。
更新时怎么让新旧版本衔接
最省心的做法,是让变更本身成为缓存失效的信号:静态资源用内容哈希命名,HTML 引用新文件名,老文件可以保留一段时间再清理。这样既不需要用户手动清缓存,也不会出现新旧样式混用。
入口页面则相反,尽量保持短缓存加校验,让更新能较快到达用户和蜘蛛。CDN 的刷新可以当作兜底手段,但不要把它当成唯一的更新机制。
几个容易被忽略的细节
- 带有 Vary 头的响应要确认设置是否准确,尤其是同一地址对不同客户端返回不同内容的情况。
- 请求里带上 Cookie 时,很多 CDN 会直接跳过缓存,检查一下是否真的需要每次都带。
- 图片和字体的缓存策略常被单独遗漏,它们往往占据页面体积的大头。
- 移动端与桌面端如果共用同一地址,要保证缓存维度能区分开,避免互相覆盖。
缓存自查不需要一次改完所有东西。挑一个流量较高的栏目页或详情页,把上面这份清单走一遍,记录改动前后的加载时间和回源请求数,再决定要不要推广到全站。