强制缓存vs协商缓存
强制缓存与协商缓存的区别
⭐ 核心区别对比
特征 | 强制缓存 | 协商缓存 |
---|---|---|
工作方式 | 不与服务器通信,直接使用缓存 | 先与服务器协商,再决定是否使用缓存 |
HTTP头部 | Cache-Control /Expires | ETag /If-None-Match 或Last-Modified /If-Modified-Since |
状态码 | 200 (from cache) | 304 (Not Modified) |
是否发请求 | 否(缓存有效时) | 是(但只传输很小的元数据) |
缓存控制精度 | 时间维度 | 内容维度 |
网络消耗 | 无 | 小量请求/响应 |
🌟 缓存判断流程
强制缓存详解
强制缓存的HTTP头部
// 服务器响应头部示例
Cache-Control: max-age=3600 // 缓存有效期1小时
Expires: Wed, 21 Oct 2022 07:28:00 GMT // 具体过期时间(旧版)
当浏览器再次请求该资源时,如果缓存仍在有效期内:
- 无需发送请求
- 直接从缓存获取资源
- 状态码为200(但实际上是从缓存获取)
协商缓存详解
协商缓存的HTTP头部
// 第一次请求,服务器响应头部
ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"
Last-Modified: Wed, 21 Oct 2022 07:28:00 GMT// 再次请求,浏览器请求头部
If-None-Match: "33a64df551425fcc55e4d42a148795d9f25f89d4"
If-Modified-Since: Wed, 21 Oct 2022 07:28:00 GMT
当浏览器再次请求该资源时:
- 发送请求到服务器(但只包含缓存校验信息)
- 服务器判断缓存是否有效
- 若有效:返回304状态码(无响应体)
- 若无效:返回200状态码和新资源
- 浏览器根据响应决定:
- 使用缓存(304)
- 更新缓存(200)
💡 两种缓存机制的完整示例
强制缓存示例
// 首次请求
GET /style.css HTTP/1.1
Host: example.com// 服务器响应
HTTP/1.1 200 OK
Content-Type: text/css
Cache-Control: max-age=3600
Date: Mon, 01 Nov 2023 10:00:00 GMT
...// 一小时内再次请求 - 浏览器不发送请求到服务器
// 直接从缓存读取,网络面板可能显示(from disk cache)
协商缓存示例
// 首次请求
GET /script.js HTTP/1.1
Host: example.com// 服务器响应
HTTP/1.1 200 OK
Content-Type: application/javascript
ETag: "abc123"
Cache-Control: no-cache
Date: Mon, 01 Nov 2023 10:00:00 GMT
...// 再次请求 - 浏览器发送条件请求
GET /script.js HTTP/1.1
Host: example.com
If-None-Match: "abc123"// 若资源未修改,服务器响应
HTTP/1.1 304 Not Modified
Date: Mon, 01 Nov 2023 11:00:00 GMT
ETag: "abc123"
// 注意:无响应体,节省带宽
📊 应用场景对比
场景 | 建议缓存策略 | 原因 |
---|---|---|
静态资源(JS/CSS) | 强制缓存+文件名Hash | 内容变化时文件名变化,确保总是最新 |
HTML页面 | 协商缓存 | 需要及时更新但又要减少带宽 |
API响应 | 根据需求使用Cache-Control | 可能需要每次都获取最新数据 |
用户头像等 | 强制缓存(长时间) | 更新不频繁,节省带宽 |
经常变化的资源 | 协商缓存 | 可能频繁变化但又需要缓存 |
🎯 最佳实践
📚 总结
-
⚠️ 强制缓存:
- 不与服务器通信,直接使用缓存
- 通过
Cache-Control
和Expires
控制 - 返回200状态码(from cache)
- 完全避免网络请求,性能最优
-
⚠️ 协商缓存:
- 与服务器协商是否使用缓存
- 通过
ETag
/Last-Modified
进行验证 - 返回304状态码表示使用缓存
- 需要发送请求,但可避免传输资源内容
两种缓存策略互为补充,合理结合使用可以显著提高网站性能,减少服务器负载和带宽消耗。