时代演进 · 跨时空印记

本文为现代工业级强缓存与协商缓存实践。亦可对比参阅作者 2018 年校招时期的早期手记:朝花夕拾 · 强缓存与协商缓存 (2018)

浏览器强缓存与协商缓存机制

浏览器缓存做的好可以使得用户的体验得到大幅提升,减轻服务器并发压力,并节省 CDN 带宽。

缓存分层对比

维度强缓存 (Strong Cache)协商缓存 (Conditional Cache)
请求是否发送否,直接从 Disk/Memory Cache 读取是,携带缓存 Tag 向服务器询问
状态码200 OK (from memory/disk cache)304 Not Modified / 200 OK
生效关键 HeaderCache-Control: max-age, ExpiresETag / If-None-Match, Last-Modified / If-Modified-Since
优先级Cache-Control > ExpiresETag (精确到哈希) > Last-Modified (秒级时间戳)

强缓存原理

当浏览器发起请求时,首先检查本地缓存中的响应头:

  1. Expires (HTTP/1.0):记录过期的绝对时间戳(受客户端时间误差影响)。
  2. Cache-Control (HTTP/1.1)
    • max-age=<seconds>:相对有效时间。
    • no-cache:跳过强缓存,立即发起协商缓存验证。
    • no-store:完全不进行任何缓存。
    • public / private:是否允许代理服务器/CDN 缓存。

协商缓存原理

强缓存失效后,浏览器向服务器发起条件请求:

  1. ETag & If-None-Match:服务器根据文件内容计算唯一的 Hash 摘要。浏览器请求时带上 If-None-Match: "hash",服务器若对比一致则返回 304
  2. 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)