时代演进 · 跨时空印记
本文为现代工业级强缓存与协商缓存实践。亦可对比参阅作者 2018 年校招时期的早期手记:朝花夕拾 · 强缓存与协商缓存 (2018)。
浏览器强缓存与协商缓存机制
浏览器缓存做的好可以使得用户的体验得到大幅提升,减轻服务器并发压力,并节省 CDN 带宽。
缓存分层对比
| 维度 | 强缓存 (Strong Cache) | 协商缓存 (Conditional Cache) |
|---|---|---|
| 请求是否发送 | 否,直接从 Disk/Memory Cache 读取 | 是,携带缓存 Tag 向服务器询问 |
| 状态码 | 200 OK (from memory/disk cache) | 304 Not Modified / 200 OK |
| 生效关键 Header | Cache-Control: max-age, Expires | ETag / If-None-Match, Last-Modified / If-Modified-Since |
| 优先级 | Cache-Control > Expires | ETag (精确到哈希) > Last-Modified (秒级时间戳) |
强缓存原理
当浏览器发起请求时,首先检查本地缓存中的响应头:
- Expires (HTTP/1.0):记录过期的绝对时间戳(受客户端时间误差影响)。
- Cache-Control (HTTP/1.1):
max-age=<seconds>:相对有效时间。no-cache:跳过强缓存,立即发起协商缓存验证。no-store:完全不进行任何缓存。public / private:是否允许代理服务器/CDN 缓存。
协商缓存原理
强缓存失效后,浏览器向服务器发起条件请求:
- ETag & If-None-Match:服务器根据文件内容计算唯一的 Hash 摘要。浏览器请求时带上
If-None-Match: "hash",服务器若对比一致则返回304。 - Last-Modified & If-Modified-Since:记录资源最后修改时间。若在此时间之后未修改则返回
304。
Client Server
│ │
│── GET /style.css ───────>│ (First Request)
│<─ 200 OK + ETag: "abc" ──│
│ │
│── [Local Check] ─────────│ (Strong Cache within max-age -> Instant load)
│ │
│── GET /style.css ───────>│ (Expired -> Send If-None-Match: "abc")
│<─ 304 Not Modified ──────│ (Resource unchanged -> use local cache)