缓存的层次
一个网页从服务器到你眼前,可能经过多层缓存:
- 浏览器缓存(本地磁盘/内存);
- CDN 缓存;
- 反向代理缓存(如 Nginx);
- 应用内缓存。
任何一层返回了旧的副本,你看到的就是旧内容。
浏览器缓存的控制
服务器通过 HTTP 响应头告诉浏览器如何缓存:
一、强缓存
Cache-Control: max-age=3600效果:在 3600 秒内,浏览器直接使用本地副本,不向服务器发请求。
这在浏览器开发者工具中显示为"from disk cache"或"from memory cache"。
问题:如果内容更新了,浏览器不会知道——直到缓存过期。
二、协商缓存
ETag: "abc123"
Last-Modified: Wed, 21 Oct 2026 07:28:00 GMT浏览器下次请求时带上:
If-None-Match: "abc123"
If-Modified-Since: Wed, 21 Oct 2026 07:28:00 GMT服务器判断:
- 内容未变 → 返回 304 Not Modified(无响应体),浏览器用本地副本;
- 内容已变 → 返回 200 和新内容。
协商缓存每次都要发请求,但内容未变时不传输数据,节省带宽。
为什么需要"刷新"
普通刷新(F5):浏览器会发送条件请求(协商缓存),验证内容是否更新。
强制刷新(Ctrl+F5 / Cmd+Shift+R):浏览器跳过缓存,直接向服务器请求全新内容。
所以当你怀疑看到的是缓存时,强制刷新是最快的验证方法。
前端资源的缓存策略
问题:如果 JS/CSS 文件被强缓存,网站更新后用户可能一直看到旧版本。
业界标准做法:文件名哈希
app.a3f2c1d9.js
style.7b8e4f2a.css原理:
- 文件内容变化时,哈希值也变化 → 文件名不同 → 浏览器认为是不同的资源 → 重新下载;
- 文件内容不变时,文件名不变 → 命中缓存。
同时对 HTML 文档本身采用 Cache-Control: no-cache(每次都协商验证),这样 HTML 更新时能及时获取,而静态资源可以放心地强缓存。
这是最可靠的方案——既享受了缓存的性能,又保证了更新的及时性。
Service Worker
现代 Web 应用可以用 Service Worker 更精细地控制缓存。
它可以:
- 在后台预缓存资源,实现离线可用;
- 实现自定义的缓存策略(如"优先网络,失败时回退到缓存");
- 提供"有新版本可用"的提示。
代价:Service Worker 的缓存更新机制比较复杂。如果配置不当,用户可能长期停留在旧版本——这也是"刷新才能看到新内容"的一个常见原因。
一个排查思路
如果网站内容不更新,按顺序检查:
- 强制刷新试试(排除浏览器缓存);
- 查看响应头(确认
Cache-Control、ETag); - 检查 CDN 是否缓存了 HTML(很多 CDN 默认只缓存静态资源,但如果配置了页面缓存就会有问题);
- 检查代理层;
- 确认源站的内容确实更新了。
说明:本文为 Web 缓存机制的知识整理。