Skip to content

强制缓存与协商缓存

约 1047 字大约 3 分钟

缓存HTTP

2025-07-12

强制缓存

强制缓存是浏览器在请求资源时首先检查的缓存机制

工作原理

  1. 浏览器发起请求时,首先检查本地缓存
  2. 如果缓存存在且未过期,直接使用缓存资源
  3. 如果缓存不存在或已过期,才向服务器发起请求

控制字段

强制缓存由两个主要的HTTP头部控制:

  1. Expires

    • HTTP/1.0的缓存控制字段
    • 值为一个绝对时间(如Expires: Wed, 21 Oct 2025 07:28:00 GMT
    • 缺点:依赖客户端本地时间,如果用户修改了系统时间,可能导致缓存失效
  2. Cache-Control

    • HTTP/1.1引入的更强大的缓存控制字段

    • 常用指令:

      • max-age=:设置缓存的最大生命周期(秒)
      • no-cache:不使用强制缓存,直接进入协商缓存
      • no-store:完全不使用任何缓存
      • public:响应可以被任何中间节点缓存
      • private:响应只能被浏览器缓存
    • 示例:Cache-Control: max-age=31536000

优先级:当Cache-ControlExpires同时存在时,Cache-Control的优先级更高。

强制缓存的三种情况

  1. 缓存不存在:直接向服务器发起请求(如同第一次请求)
  2. 缓存存在但已过期:强制缓存失效,进入协商缓存阶段
  3. 缓存存在且未过期:直接使用缓存,状态码200,但显示from cache

协商缓存

当强制缓存失效时,浏览器会进入协商缓存阶段

工作原理

  1. 浏览器携带缓存标识向服务器发起请求
  2. 服务器根据标识判断资源是否变化
  3. 如果未变化,返回304 Not Modified,浏览器使用本地缓存
  4. 如果已变化,返回200和新资源

控制字段

协商缓存有两组控制字段:

  1. Last-Modified / If-Modified-Since

    • 服务器在首次响应时返回Last-Modified头部,表示资源最后修改时间
    • 浏览器再次请求时,在If-Modified-Since头部带上这个时间
    • 服务器比较当前资源修改时间和If-Modified-Since
    • 缺点:精度只到秒级,可能因文件内容未变但修改时间变化导致不必要的请求
  2. ETag / If-None-Match

    • 服务器在首次响应时返回ETag头部,是资源的唯一标识符(通常是内容的哈希值)
    • 浏览器再次请求时,在If-None-Match头部带上这个ETag值
    • 服务器比较当前资源ETag和If-None-Match
    • 更精确,能感知内容变化

优先级:当ETagLast-Modified同时存在时,ETag的优先级更高。

协商缓存的两种情况

  1. 缓存有效:返回304 Not Modified,浏览器使用本地缓存
  2. 缓存无效:返回200和新资源

缓存流程总结

  1. 浏览器发起请求时,先检查强制缓存

    • 如果缓存有效且未过期,直接使用缓存
    • 如果缓存不存在或已过期,进入协商缓存阶段
  2. 协商缓存阶段:

    • 浏览器发送请求,携带If-None-Match(ETag)和/或If-Modified-Since(Last-Modified)
    • 服务器验证资源是否变化
      • 未变化:返回304,浏览器使用缓存
      • 已变化:返回200和新资源
  3. 新资源会被浏览器缓存,并更新缓存标识

实际应用建议

  • 对于静态资源(如JS、CSS、图片):设置较长的max-age(如1年),并使用内容哈希作为文件名或查询参数,这样可以在内容变化时自动失效缓存
  • 对于频繁变化的资源:使用no-cache或较短的max-age,依赖协商缓存
  • 对于敏感数据:使用no-store确保不缓存

通过合理配置缓存策略,可以显著提高网站性能,减少服务器负载,提升用户体验。