在日常开发中,我们经常听到“缓存”这个词。合理利用缓存不仅能显著提升页面加载速度,还能减轻服务器压力。而浏览器缓存作为最基础也是最重要的性能优化手段之一,掌握其工作原理至关重要。
本文将带你系统梳理浏览器缓存的核心机制——强缓存 和 协商缓存,并通过图解方式帮助你彻底搞懂它们的工作流程。
一、为什么需要浏览器缓存?
当用户首次访问一个网页时,浏览器会下载 HTML、CSS、JS、图片等资源。如果每次刷新或跳转都重新请求这些资源,不仅耗时长、占用带宽,还会增加服务器负载。
浏览器缓存的作用就是:在一定时间内复用已下载的资源,避免重复请求,提升用户体验。
缓存策略主要分为两类:
- ✅ 强缓存(Strong Cache)
- 🔁 协商缓存(Revalidation Cache)
下面我们逐一详解。
二、强缓存:直接从本地拿资源
1. 什么是强缓存?
强缓存是指浏览器在接收到服务器响应时,根据响应头中的过期策略,判断资源是否“未过期”。如果未过期,则直接从本地缓存读取资源,不再向服务器发起请求。
此时,网络面板中该资源的状态码显示为:
200 OK (from disk cache)或(from memory cache)
2. 控制强缓存的头部字段
| 字段 | 协议版本 | 说明 |
|---|---|---|
Cache-Control | HTTP/1.1 ✅ | 推荐使用,优先级更高 |
Expires | HTTP/1.0 ⚠️ | 已过时,兼容用 |
✅ Cache-Control(推荐)
常见取值:
max-age=3600:资源最多缓存 3600 秒(1小时)no-cache:不使用强缓存,但可走协商缓存no-store:禁止任何缓存,每次都请求服务器public:资源可被所有中间节点缓存(如 CDN)private:仅客户端可以缓存,中间代理不可缓存
Cache-Control: max-age=3600, public
📌 注意:
Cache-Control优先级高于Expires。
⚠️ Expires
指定资源的绝对过期时间(GMT 格式):
Expires: Wed, 31 Aug 2025 07:00:00 GMT
但由于依赖客户端时间,容易因时间不同步导致问题,现已不推荐单独使用。
3. 强缓存工作流程图
图解:浏览器收到响应后检查
Cache-Control或Expires,若未过期,则直接使用本地缓存,不发请求。
三、协商缓存:让服务器决定是否更新
1. 什么是协商缓存?
当强缓存失效(即资源已过期),浏览器不会立刻下载新资源,而是发起一次请求询问服务器资源是否有更新。这个过程称为“协商缓存”。
如果资源未变,服务器返回 304 Not Modified,告诉浏览器继续使用缓存;否则返回 200 和新资源。
2. 协商缓存的两种机制
方式一:Last-Modified / If-Modified-Since
- 首次请求,服务器返回:
Last-Modified: Tue, 26 Aug 2025 10:00:00 GMT - 后续请求,浏览器自动带上:
If-Modified-Since: Tue, 26 Aug 2025 10:00:00 GMT - 服务器对比时间:
- 资源未修改 → 返回
304 - 资源已修改 → 返回
200+ 新资源
- 资源未修改 → 返回
⚠️ 缺点:时间精度为秒级,且文件内容未变但修改时间变了也会误判。
方式二:ETag / If-None-Match(推荐)
-
首次请求,服务器生成资源唯一标识:
ETag: "abc123xyz"(通常是内容哈希或版本号)
-
后续请求,浏览器带上:
If-None-Match: "abc123xyz" -
服务器对比 ETag:
- 一致 → 返回
304 - 不一致 → 返回
200+ 新资源
- 一致 → 返回
✅ 优点:精确到内容级别,即使时间没变但内容变了也能检测到。
🔥 优先级:
ETag>Last-Modified
3. 协商缓存工作流程图

图解:强缓存失效后,浏览器携带
If-Modified-Since或If-None-Match发起请求,由服务器判断是否返回304。
四、完整缓存(建议收藏)
整个缓存流程如下:
- 用户发起请求
- 浏览器检查是否存在强缓存(
Cache-Control/Expires)- ✅ 未过期 → 使用本地缓存(
200 from cache) - ❌ 已过期 → 进入协商缓存
- ✅ 未过期 → 使用本地缓存(
- 发起请求,携带
If-Modified-Since或If-None-Match - 服务器比对资源
- 未修改 → 返回
304,使用缓存 - 已修改 → 返回
200+ 新资源
- 未修改 → 返回
五、实际开发中的缓存策略建议
| 资源类型 | 建议缓存策略 |
|---|---|
| HTML 文件 | Cache-Control: no-cache 或短时间缓存 + ETag |
| CSS/JS 静态资源 | Cache-Control: max-age=31536000, immutable(配合文件指纹) |
| 图片/字体等媒体资源 | 长时间缓存 + 内容哈希命名 |
| API 接口数据 | 根据业务设置合理 max-age,必要时禁用缓存 |
💡 小技巧:使用 Webpack/Vite 构建时,通过
[contenthash]实现静态资源长期缓存。
六、如何调试缓存?
打开 Chrome DevTools → Network 面板:
- 查看状态码:
200(from cache):强缓存命中304:协商缓存生效200(常规):重新下载资源
- 检查 Response Headers 中的
Cache-Control、ETag等字段
七、总结
| 对比项 | 强缓存 | 协商缓存 |
|---|---|---|
| 是否发请求 | ❌ 不发 | ✅ 发 |
| 状态码 | 200 (from cache) | 304 或 200 |
| 判断依据 | Cache-Control / Expires | ETag / Last-Modified |
| 优先级 | 更高 | 强缓存失效后启用 |
| 性能表现 | 最优 | 次优(有网络通信) |
✅ 最佳实践:
合理设置 Cache-Control 实现长期缓存,搭配 ETag 提供精准更新检测,既能提升性能,又能保证内容实时性。