缓存問题為什么值得單獨查一遍
很多人把缓存当成“上线时顺手配一下”的東西,配完就不再回头看。但缓存是少數會同时影响三方的事情:用戶、搜尋引擎蜘蛛、以及你自己的服務器。用戶在弱網下多等几秒,蜘蛛在同样的带宽里少抓几個頁面,服務器在流量峰值时多扛一轮無意义的重复請求。
尤其是当站点規模變大、静態资源變多之後,一個配置不当的响應头會被放大成成百上千次重复下载。這不一定是“错誤”,但确實是可以省下来的成本。
缓存的目标不是“让所有東西都缓存久一点”,而是让该久留的久留,该立刻更新的立刻更新。
先把资源分成三類
- 带指纹的静態资源:文件名里带内容哈希的 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 會直接跳過缓存,检查一下是否真的需要每次都带。
- 图片和字体的缓存策略常被單獨遗漏,它們往往占據頁面体积的大头。
- 移動端與桌面端如果共用同一地址,要保證缓存维度能区分開,避免互相覆盖。
缓存自查不需要一次改完所有東西。挑一個流量較高的栏目頁或詳情頁,把上面這份清單走一遍,记錄改動前後的加载時間和回源請求數,再决定要不要推廣到全站。