核心区别
对比维度 | 强缓存 | 协商缓存 |
---|---|---|
是否发请求 | 不发送请求(直接使用本地缓存) | 发送请求(服务器验证缓存有效性) |
HTTP 状态码 | 200 (from disk/memory cache) | 304 Not Modified |
性能影响 | 无网络请求,速度最快 | 需网络往返,但比完整下载资源快 |
适用场景 | 长期不变的静态资源(如图片、JS/CSS 文件) | 频繁更新的资源(如用户个性化内容) |
实现机制
强缓存
通过以下 HTTP 头控制:
-
Expires
- 绝对时间(如
Expires: Wed, 21 Oct 2025 07:28:00 GMT
)。 - 缺点:客户端与服务端时间不一致会导致误差。
- 绝对时间(如
-
Cache-Control
- 优先级高于
Expires
。 - 常用指令:
max-age=3600
(资源有效期 3600 秒)。no-cache
(强制协商缓存)。no-store
(禁止缓存)。public
(允许代理服务器缓存)。private
(仅浏览器缓存)。
- 优先级高于
协商缓存
通过以下两组头验证:
-
Last-Modified(服务端) + If-Modified-Since(客户端)
- 基于文件修改时间(精度为秒级)。
- 缺点:文件内容不变但修改时间变化时会失效(如重新生成文件)。
-
ETag(服务端) + If-None-Match(客户端)
- 基于文件哈希值(如
ETag: "d3b07384d113edec49eaa6238ad5ff00"
)。 - 优先级高于
Last-Modified
。 - 缺点:计算哈希值消耗服务器资源。
- 基于文件哈希值(如
工作流程对比
强缓存流程
浏览器 → 检查缓存有效性 → 有效 → 直接使用缓存↓ 无效 → 进入协商缓存流程
协商缓存流程
浏览器 → 发送请求(携带 If-Modified-Since/If-None-Match) ↓
服务器 → 检查资源是否变化 → 未变化 → 返回 304(空响应体) ↓ 已变化 → 返回 200 + 新资源
实际应用策略
-
静态资源(JS/CSS/图片)
- 使用强缓存:
Cache-Control: max-age=31536000
(1 年)。 - 通过文件名哈希(如
app.d3b07384.js
)实现缓存更新。
- 使用强缓存:
-
HTML 文件
- 使用协商缓存:
Cache-Control: no-cache
。 - 避免因强缓存导致页面更新不及时。
- 使用协商缓存:
-
API 响应
- 动态数据:
Cache-Control: no-store
(禁用缓存)。 - 半静态数据:
Cache-Control: max-age=60, must-revalidate
。
- 动态数据:
常见问题与解决方案
问题 | 解决方案 |
---|---|
强缓存导致更新延迟 | 修改资源文件名(添加哈希值或版本号)。 |
协商缓存频繁验证浪费带宽 | 对不常变更的资源适当增加 max-age (如 max-age=600 + must-revalidate )。 |
ETag 计算影响服务器性能 | 对静态资源禁用 ETag(Nginx 配置 etag off; )。 |
最佳实践
-
分层缓存策略
- 浏览器强缓存 → CDN 缓存 → 服务器协商缓存。
-
调试工具
- Chrome DevTools 的 Network 面板:
- 强缓存资源显示
200 (from memory/disk cache)
。 - 协商缓存资源显示
304 Not Modified
。
- 强缓存资源显示
- Chrome DevTools 的 Network 面板:
-
缓存清除技巧
- 强制刷新:
Ctrl + F5
(跳过强缓存,触发完整请求)。 - 普通刷新:
F5
(允许协商缓存验证)。
- 强制刷新: