网络 & HTTP
HTTP 缓存
一、为什么需要缓存
每次请求都去服务器拿资源,慢且浪费带宽。缓存的本质是把拿过的资源存在本地,下次直接用或快速验证。
二、两种缓存机制
强缓存 — 不发请求
浏览器检查响应头,缓存未过期则直接用本地资源,不与服务器通信。
相关响应头:
# 旧方案(HTTP/1.0)
Expires: Thu, 20 May 2027 12:00:00 GMT # 绝对时间,有时区问题
# 新方案(HTTP/1.1,优先级更高)
Cache-Control: max-age=31536000 # 相对时间,单位秒(1 年)命中时 DevTools 显示 200 (from memory cache) 或 200 (from disk cache),无网络请求。
常见策略:
# 带 hash 的 JS/CSS → 强缓存一年
Cache-Control: max-age=31536000
# HTML 入口文件 → 不强缓存(保证能拿到最新资源引用)
Cache-Control: no-cache协商缓存 — 问一下服务器
强缓存过期后(或设了 no-cache),浏览器带着标识去问服务器资源有没有变。
两套方案:
# 方案一:基于修改时间(HTTP/1.0)
首次响应:Last-Modified: Wed, 20 May 2026 10:00:00 GMT
再次请求:If-Modified-Since: Wed, 20 May 2026 10:00:00 GMT
# 方案二:基于内容指纹(HTTP/1.1,优先级更高)
首次响应:ETag: "abc123"
再次请求:If-None-Match: "abc123"服务器判断结果:
- 没变 →
304 Not Modified,body 为空,浏览器用本地缓存 - 变了 →
200,返回新资源
三、304 是什么
浏览器:这个资源我有一份,指纹是 "abc123",变了吗?
服务器:没变。
↓
304 Not Modified(不传 body,省带宽)
↓
浏览器使用本地缓存的资源虽然比强缓存多一次网络往返,但不传资源 body,对大文件(图片、JS 包)节省明显。
四、完整流程
浏览器请求资源
│
├─ Cache-Control / Expires 未过期?
│ ├─ 是 → 200 (from cache) 强缓存命中,不发请求
│ └─ 否 ↓
│
├─ 携带 If-None-Match / If-Modified-Since 发请求
│ ├─ 资源未变 → 304 协商缓存命中,用本地缓存
│ └─ 资源已变 → 200 + 新资源五、ETag 比 Last-Modified 好在哪
| Last-Modified | ETag | |
|---|---|---|
| 精度 | 秒级,1 秒内多次修改检测不到 | 内容指纹,改一个字节都能检测 |
| 误判场景 | 内容没变但 mtime 变了(如重新部署)会误判过期 | 只看内容,不误判 |
| 服务器开销 | 小 | 需计算 hash,略大 |
六、口诀
强缓存不问,协商缓存问一下。强缓存看
Cache-Control,协商缓存看ETag+304。