HTTP对前端的缓存
HTTP 请求本身就有非常完善的多级缓存机制。
静态资源默认都会缓存:JS、CSS、图片、字体、html、ico、json 等;
接口接口数据默认不缓存(看后端响应头)。
HTTP 请求的缓存机制是 Web 性能优化的基石。它是一套多层级、环环相扣的流程,核心目的是为了减少网络延迟、降低服务器负载并节省带宽。
我们可以把整个工作流程分为两大核心阶段(强缓存与协商缓存)以及三级存储位置。
# 一、 核心工作流程:两大阶段
当浏览器发起一个 HTTP 请求时,它会按照下面的逻辑进行检查
# 1. 第一阶段:强缓存(本地直接决定)
浏览器直接检查本地缓存,不需要向服务器发送任何请求。如果命中,直接返回状态码 200 OK (from disk cache/memory cache)。
控制强缓存的 Header 有两个:
Expires(HTTP/1.0 产物):使用的是绝对时间(如Expires: Wed, 21 Oct 2025 07:28:00 GMT)。缺点是如果客户端本地时间不准,缓存就会错乱。Cache-Control(HTTP/1.1 现代标准):使用的是相对时间,优先级高于Expires。max-age=3600:表示资源在接下来的 3600 秒(1小时)内有效。no-cache:误区预警!它并不意味着“不缓存”,而是指“使用资源前,必须先去服务器进行协商缓存验证”。no-store:这才是真正的“绝不缓存”,不保存任何副本。
# 2. 第二阶段:协商缓存(向服务器验证)
如果强缓存过期了,或者设置了 no-cache,浏览器就会带上缓存标记向服务器发请求,问一句:“我这边的版本还能用吗?”
服务器比对后,有两种结果:
- 没变(命中):服务器返回
304 Not Modified,不返回文件内容(身体)。浏览器直接读取本地旧缓存。极大地节省了带宽。 - 变了(未命中):服务器返回
200 OK,并带上最新的资源内容和新的缓存标记。
协商缓存依赖于两对 Header(都是成对出现的):
| 验证机制 | 浏览器请求 Header (Request) | 服务器响应 Header (Response) | 特点与优先级 |
|---|---|---|---|
| 基于时间戳 | If-Modified-Since | Last-Modified | 记录文件最后修改时间。缺点是只能精确到秒,且文件如果只是打开没修改,时间也会变。 |
| 基于唯一标识 | If-None-Match | ETag | 服务器根据文件内容生成的哈希值(类似指纹)。优先级高于时间戳,只要内容不变,ETag 就不变,精准度极高。 |
# 二、 缓存存储的三级物理位置
在强缓存命中时,你会发现控制台里有些显示 from memory cache,有些显示 from disk cache。这是浏览器的多级存储机制:
- Memory Cache(内存缓存):
- 特点:速度极快,读取只需 0ms,但容量小、进程关闭后即销毁。
- 存什么:通常存放当前页面正在使用的精简资源(如 Base64 图片、小体积的 JS/CSS)。
- Disk Cache(硬盘缓存):
- 特点:容量大,断电或关闭浏览器后依然存在,但读取速度比内存慢(需要 I/O 操作)。
- 存什么:大文件、长期不变的资源。浏览器会根据硬盘空闲情况和文件大小自动分配。
- Service Worker Cache(离线缓存):
- 特点:完全由开发者通过 JavaScript 控制的独立缓存,可以做到离线访问。它的优先级甚至高于浏览器的内置网络缓存。
# 三、 完整演练:一个请求的生命周期
- 首次请求:
- 浏览器请求
main.js。 - 服务器返回
200 OK,带上响应头:Cache-Control: max-age=86400,ETag: "xyz123"。 - 浏览器把文件存入 Disk Cache。
- 浏览器请求
- 第二天再次请求(10小时后,强缓存期内):
- 浏览器发现
max-age还没过期。 - 直接拦截请求,从 Disk Cache 读取,控制台显示
200 OK (from disk cache)。没有产生任何网络流量。
- 浏览器发现
- 第四天再次请求(3天后,强缓存过期):
- 浏览器发现过期了,于是发起网络请求。
- 请求头自动带上:
If-None-Match: "xyz123"。 - 服务器检查服务器上的
main.js,发现哈希值还是"xyz123"。 - 服务器返回
304 Not Modified(不带报文主体)。 - 浏览器收到 304,高高兴兴地去读本地旧缓存。
- 第五天(代码更新了):
- 浏览器同样发起带
If-None-Match: "xyz123"的请求。 - 服务器发现最新代码的哈希变成了
"abc999",不匹配。 - 服务器返回
200 OK,附带全新代码和新 ETag。浏览器更新本地缓存。
- 浏览器同样发起带

上次更新: 2026-06-29 17:10:35