DevTools 缓存调试
按 Network 响应来源、HTTP validators、Service Worker/Cache Storage 和请求头逐层判断“为什么还是旧内容”,区分强缓存、协商缓存与可编程缓存。
[!info] related notes
- 所属 MOC: DevTools Network MOC, DevTools Application MOC
- 缓存模型: 浏览器缓存体系
- HTTP 缓存: 强缓存, 协商缓存, [[http-cache-storage|浏览器内部缓存存储]]
- Service Worker: Service Worker 请求调试
- 排障路线: 缓存不更新排查路线
DevTools 缓存调试
症状
常见表现:
- 服务端已经更新,但浏览器仍显示旧内容;
- Network 显示 304;
- Size/Transferred 显示 memory cache / disk cache;
- 刷新后问题消失,但普通导航仍复现;
- 开 DevTools 后问题“突然好了”;
- 清 HTTP cache 后仍然返回旧数据。
第一层:这次响应到底来自哪里
先看 Network:
- Status;
- Size / Transferred;
- Response Headers;
- Request Headers;
- 是否显示 from memory cache / disk cache;
- 是否显示 from ServiceWorker。
先回答:
这次请求真的到 origin server 了吗?
from memory/disk cache
说明浏览器直接复用了 HTTP cache representation,通常没有重新下载完整响应。
继续检查:
- Cache-Control;
- Expires;
- Age;
- Vary。
304 Not Modified
说明发生了 conditional request:
- If-None-Match / ETag;
- If-Modified-Since / Last-Modified。
304 本身不是错误,它表示缓存 representation 仍被服务器认可。
from ServiceWorker
此时问题已经不只是 HTTP cache。
继续看 Service Worker 请求调试。
第二层:检查 Cache-Control
优先问:
- max-age / s-maxage 多久?
- immutable 是否合理?
- no-cache 是“不能缓存”还是“使用前必须 revalidate”?
- no-store 是否真的需要?
- public/private 是否符合内容权限?
不要把 no-cache 理解成完全不缓存。
第三层:检查 Vary
相同 URL 不一定应该复用相同 response。
例如 response 依赖:
- Accept-Encoding;
- Origin;
- Accept-Language。
如果服务端按某个 request header 生成不同 representation,却漏掉对应 Vary,shared/browser cache 可能复用错误变体。
第四层:用 Disable cache 做实验
DevTools 的 Disable cache 适合回答:
如果暂时绕开普通 HTTP cache,问题是否消失?
如果消失:
→ HTTP cache policy/validator 更可疑。
如果仍存在:
→ 继续检查 Service Worker、应用 state、CDN/proxy 或服务端。
不要把“Disable cache 后正常”当成最终修复。
第五层:Application 面板
如果使用 Service Worker / Cache Storage:
检查:
- 当前页面是否被某个 Service Worker 控制;
- Cache Storage 中是否有旧 response;
- worker 是否已经更新但仍有旧 active worker;
- fetch handler 是否 cache-first;
- 更新流程是否等待旧 client 退出。
诊断矩阵
| 证据 | 优先怀疑 |
|---|---|
| from memory/disk cache | HTTP strong cache |
| 304 | validator / negotiated cache |
| from ServiceWorker | SW / Cache Storage |
| Disable cache 后正常 | HTTP cache policy |
| Disable cache 后仍旧 | SW / CDN / app state / server |
| 相同 URL 不同用户串内容 | Vary / private/public cache boundary |
修复原则
修复应落到真正 authority:
- fingerprinted static asset → 长期 immutable;
- HTML / dynamic API → 合理 revalidation;
- user-specific response → 正确 private/Vary;
- Service Worker → 明确 cache strategy 和 version/update;
- CDN → purge/versioning 与 origin header 一致。
不要把“让用户 Ctrl+F5”当产品修复。
迁移检查
给一个场景:部署新 JS 后部分用户仍加载旧版本。
不看正文完成:
- 用 Network 判断旧 JS 来自 HTTP cache 还是 Service Worker;
- 分别给出两条完全不同的证据链;
- 解释为什么 304 不等于“服务端没收到请求”;
- 说明 Disable cache 能证明什么、不能证明什么;
- 设计长期修复,而不是要求用户清缓存。