HTTP缓存策略之协商缓存与强缓存详解
字数 1711 2025-12-05 16:53:51

HTTP缓存策略之协商缓存与强缓存详解

一、题目描述

HTTP缓存是Web性能优化的核心技术之一,能显著减少网络传输、降低服务器负载。HTTP缓存分为强缓存协商缓存两种机制:

  • 强缓存:浏览器不向服务器发送请求,直接使用本地缓存
  • 协商缓存:浏览器向服务器验证缓存是否过期,决定是否使用缓存

理解这两种缓存的工作流程、相关HTTP头部以及适用场景,是构建高效Web应用的基础。

二、知识背景

HTTP缓存基于HTTP协议中的缓存控制头部实现,主要涉及:

  • 强缓存:Cache-ControlExpires
  • 协商缓存:Last-Modified/If-Modified-SinceETag/If-None-Match

浏览器处理缓存的基本流程:

用户请求资源 → 检查强缓存是否有效 → 有效则使用缓存
              ↓ 无效
           向服务器发送请求(带协商缓存头)
              ↓
       服务器验证缓存是否过期 → 未过期返回304
              ↓
        过期则返回新资源(200)

三、强缓存详解

3.1 工作原理

强缓存阶段,浏览器不会与服务器通信,直接从本地缓存中读取资源。

关键HTTP头部:

  1. Cache-Control(HTTP/1.1标准)
Cache-Control: max-age=3600
  • max-age=3600:资源在3600秒内有效
  • no-cache:禁用强缓存,需向服务器验证
  • no-store:完全不缓存
  • public:允许任何缓存方缓存
  • private:只允许客户端缓存
  • s-maxage:针对共享缓存的时间
  1. Expires(HTTP/1.0标准)
Expires: Wed, 21 Oct 2025 07:28:00 GMT
  • 指定资源的绝对过期时间
  • 受客户端和服务器时间差异影响,优先级低于Cache-Control

3.2 实际流程示例

请求:GET /app.js
响应头:
  Cache-Control: public, max-age=3600
  Expires: Wed, 21 Oct 2025 08:00:00 GMT

用户在3600秒内再次请求该资源时,浏览器检查:

  1. 计算当前时间与缓存时间的差值是否小于max-age
  2. 如果小于,直接使用本地缓存(状态码200,from disk cache/memory cache)
  3. 如果大于,进入协商缓存阶段

注意:Chrome浏览器中,强缓存会显示:

  • from disk cache:磁盘缓存
  • from memory cache:内存缓存

四、协商缓存详解

4.1 工作原理

当强缓存失效时,浏览器携带缓存标识向服务器请求验证。如果资源未改变,服务器返回304,浏览器使用本地缓存。

两种验证机制:

  1. Last-Modified / If-Modified-Since
# 第一次请求响应
Last-Modified: Wed, 21 Oct 2025 07:28:00 GMT

# 后续请求请求头
If-Modified-Since: Wed, 21 Oct 2025 07:28:00 GMT
  • 基于文件最后修改时间
  • 问题:1秒内多次修改无法识别,时间不精确
  1. ETag / If-None-Match
# 第一次请求响应
ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"

# 后续请求请求头
If-None-Match: "33a64df551425fcc55e4d42a148795d9f25f89d4"
  • 基于文件内容生成的哈希值
  • 优先级高于Last-Modified
  • 强ETag:字节级变化就会改变
  • 弱ETag(W/前缀):允许语义不变的内容变化

4.2 服务器验证流程

服务器收到带有If-None-Match/If-Modified-Since的请求:
1. 检查If-None-Match是否存在
   - 存在:比较ETag是否匹配
     - 匹配 → 返回304 Not Modified
     - 不匹配 → 返回200和新资源
   
2. 无ETag,检查If-Modified-Since
   - 存在:比较修改时间
     - 资源未修改 → 返回304
     - 已修改 → 返回200和新资源
   
3. 两者都无,返回200和新资源

五、完整缓存流程图解

用户请求资源
    ↓
检查本地是否有缓存
    ↓
    ├── 无缓存 ──→ 正常请求服务器 → 返回资源(200)
    ↓
    └── 有缓存 ──→ 检查Cache-Control/Expires
            ↓
        强缓存有效? ──是─→ 使用本地缓存(200 from cache)
            ↓
            否
            ↓
    ┌───────────────────────────┐
    ↓                           ↓
If-None-Match/ETag    If-Modified-Since/Last-Modified
    ↓                           ↓
服务器验证ETag       服务器验证修改时间
    ↓                           ↓
    └───────── 匹配/未修改 ──────┘
            ↓
        返回304 Not Modified → 使用本地缓存
            ↓
        不匹配/已修改
            ↓
        返回200和新资源 → 更新缓存

六、缓存策略最佳实践

6.1 不同资源类型的缓存策略

// 1. 静态资源(JS/CSS/图片) - 强缓存+文件名hash
Cache-Control: public, max-age=31536000
// 文件名带hash:app.a1b2c3.js

// 2. HTML文件 - 协商缓存
Cache-Control: no-cache
// 或短时间缓存
Cache-Control: max-age=0, must-revalidate

// 3. API接口 - 按需缓存
Cache-Control: no-cache, private
// 或短时间缓存
Cache-Control: max-age=60

6.2 缓存更新策略

// 方案1:文件名hash(推荐)
// app.旧hash.js → app.新hash.js
// 强缓存一年

// 方案2:查询参数
// app.js?v=1 → app.js?v=2
// 部分CDN可能不识别查询参数

// 方案3:清除缓存
// Cache-Control: no-cache, no-store, must-revalidate

七、浏览器缓存位置

  1. Memory Cache(内存缓存)

    • 快速读取,标签页关闭即失效
    • 较小资源,如样式、脚本
  2. Disk Cache(磁盘缓存)

    • 持久化存储,大文件
    • 根据Cache-Control头部确定存储位置
  3. Service Worker Cache

    • 可编程缓存API
    • 离线应用支持

八、实际开发注意事项

8.1 常见问题

  1. 缓存污染:错误配置导致缓存旧版本

    # 错误:所有JS文件缓存一年
    location ~* \.(js|css)$ {
        expires 1y;
    }
    # 正确:带hash的文件长期缓存
    location ~* \.[a-f0-9]{8}\.(js|css)$ {
        expires 1y;
    }
    
  2. CDN边缘缓存:注意CDN可能缓存304响应

  3. 用户强制刷新:Ctrl+F5会跳过强缓存

8.2 调试技巧

// Chrome DevTools查看缓存状态
1. Network面板  Disable cache禁用缓存
2. 查看Size列
   - (memory cache)/(disk cache)强缓存命中
   - 304协商缓存命中
3. 查看Response Headers中的缓存相关头部

九、总结对比

特性 强缓存 协商缓存
状态码 200 (from cache) 304 Not Modified
是否请求
相关头部 Cache-Control, Expires ETag/If-None-Match, Last-Modified/If-Modified-Since
性能 最优(无网络请求) 次优(有请求但无响应体)
时效性 可能过期 实时验证
适用场景 长期不变静态资源 经常变化资源

实际应用中通常组合使用:

Cache-Control: public, max-age=3600
ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"

这样的配置让浏览器在3600秒内使用强缓存,过期后通过ETag验证,实现性能和实时性的平衡。

HTTP缓存策略之协商缓存与强缓存详解 一、题目描述 HTTP缓存是Web性能优化的核心技术之一,能显著减少网络传输、降低服务器负载。HTTP缓存分为 强缓存 和 协商缓存 两种机制: 强缓存 :浏览器不向服务器发送请求,直接使用本地缓存 协商缓存 :浏览器向服务器验证缓存是否过期,决定是否使用缓存 理解这两种缓存的工作流程、相关HTTP头部以及适用场景,是构建高效Web应用的基础。 二、知识背景 HTTP缓存基于HTTP协议中的缓存控制头部实现,主要涉及: 强缓存: Cache-Control 、 Expires 协商缓存: Last-Modified / If-Modified-Since 、 ETag / If-None-Match 浏览器处理缓存的基本流程: 三、强缓存详解 3.1 工作原理 强缓存阶段,浏览器不会与服务器通信,直接从本地缓存中读取资源。 关键HTTP头部: Cache-Control (HTTP/1.1标准) max-age=3600 :资源在3600秒内有效 no-cache :禁用强缓存,需向服务器验证 no-store :完全不缓存 public :允许任何缓存方缓存 private :只允许客户端缓存 s-maxage :针对共享缓存的时间 Expires (HTTP/1.0标准) 指定资源的绝对过期时间 受客户端和服务器时间差异影响,优先级低于Cache-Control 3.2 实际流程示例 用户在3600秒内再次请求该资源时,浏览器检查: 计算当前时间与缓存时间的差值是否小于max-age 如果小于,直接使用本地缓存(状态码200,from disk cache/memory cache) 如果大于,进入协商缓存阶段 注意 :Chrome浏览器中,强缓存会显示: from disk cache :磁盘缓存 from memory cache :内存缓存 四、协商缓存详解 4.1 工作原理 当强缓存失效时,浏览器携带缓存标识向服务器请求验证。如果资源未改变,服务器返回304,浏览器使用本地缓存。 两种验证机制: Last-Modified / If-Modified-Since 基于文件最后修改时间 问题:1秒内多次修改无法识别,时间不精确 ETag / If-None-Match 基于文件内容生成的哈希值 优先级高于Last-Modified 强ETag:字节级变化就会改变 弱ETag(W/前缀):允许语义不变的内容变化 4.2 服务器验证流程 五、完整缓存流程图解 六、缓存策略最佳实践 6.1 不同资源类型的缓存策略 6.2 缓存更新策略 七、浏览器缓存位置 Memory Cache (内存缓存) 快速读取,标签页关闭即失效 较小资源,如样式、脚本 Disk Cache (磁盘缓存) 持久化存储,大文件 根据Cache-Control头部确定存储位置 Service Worker Cache 可编程缓存API 离线应用支持 八、实际开发注意事项 8.1 常见问题 缓存污染 :错误配置导致缓存旧版本 CDN边缘缓存 :注意CDN可能缓存304响应 用户强制刷新 :Ctrl+F5会跳过强缓存 8.2 调试技巧 九、总结对比 | 特性 | 强缓存 | 协商缓存 | |------|--------|----------| | 状态码 | 200 (from cache) | 304 Not Modified | | 是否请求 | 否 | 是 | | 相关头部 | Cache-Control, Expires | ETag/If-None-Match, Last-Modified/If-Modified-Since | | 性能 | 最优(无网络请求) | 次优(有请求但无响应体) | | 时效性 | 可能过期 | 实时验证 | | 适用场景 | 长期不变静态资源 | 经常变化资源 | 实际应用中通常组合使用: 这样的配置让浏览器在3600秒内使用强缓存,过期后通过ETag验证,实现性能和实时性的平衡。