HTTP 缓存策略

强缓存和协商缓存的工作原理、区别及应用场景

问题

HTTP 缓存策略有哪些,它们有什么区别,分别解决了什么问题?

解答

缓存机制概述

浏览器缓存分为强缓存协商缓存两种,强缓存优先级更高。缓存从第二次请求开始生效:

  1. 第一次请求时,服务器返回资源和缓存策略(通过 response header)
  2. 第二次请求时,浏览器先检查强缓存,命中则直接返回 200;未命中则发送请求头到服务器验证协商缓存,命中返回 304

强缓存

强缓存命中时直接读取本地资源,不发送请求,Network 面板显示 from memory cachefrom disk cache

Expires(HTTP/1.0)

服务器返回一个绝对过期时间:

Expires: Mon, 10 Nov 2024 09:10:11 GMT

优点: 简单易用,兼容 HTTP/1.0

缺点:

  • 依赖客户端时间,时间不同步会导致缓存失效
  • 无法感知到期前的资源更新

Cache-Control(HTTP/1.1)

使用相对时间,优先级高于 Expires:

Cache-Control: max-age=3600

常用指令:

# 可缓存性
Cache-Control: public          # 客户端和代理服务器都可缓存
Cache-Control: private         # 仅客户端可缓存(默认值)
Cache-Control: no-cache        # 需要验证后才能使用缓存
Cache-Control: no-store        # 完全不缓存

# 过期时间
Cache-Control: max-age=3600           # 缓存有效期 3600 秒
Cache-Control: s-maxage=7200          # CDN 等共享缓存的有效期
Cache-Control: must-revalidate        # 过期后必须向服务器验证

优点:

  • 使用相对时间,避免时间不同步问题
  • 提供丰富的缓存控制选项

缺点: 无法感知到期前的资源更新

协商缓存

强缓存失效后,浏览器携带缓存标识向服务器验证资源是否更新。服务器返回 304 表示未修改,浏览器使用本地缓存;返回 200 则返回新资源。

Last-Modified / If-Modified-Since(HTTP/1.0)

服务器首次返回资源的最后修改时间:

Last-Modified: Mon, 10 Nov 2024 09:10:11 GMT

浏览器再次请求时携带该时间:

If-Modified-Since: Mon, 10 Nov 2024 09:10:11 GMT

服务器对比时间,相同返回 304,不同返回 200 和新资源。

优点: 每次请求都会验证,避免使用过期资源

缺点:

  • 只要文件修改就返回新资源,即使内容未实质变化
  • 精度只到秒,无法识别 1 秒内的多次修改
  • 动态生成的文件每次修改时间都不同,无法有效缓存

ETag / If-None-Match(HTTP/1.1)

服务器返回资源的唯一标识(通常是内容 hash):

ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"

浏览器再次请求时携带该标识:

If-None-Match: "33a64df551425fcc55e4d42a148795d9f25f89d4"

服务器对比 ETag,相同返回 304,不同返回 200 和新资源。ETag 优先级高于 Last-Modified。

优点:

  • 基于内容判断,更精确
  • 可识别 1 秒内的多次修改

缺点:

  • 计算 hash 有性能开销
  • 分布式环境下不同服务器的 ETag 算法可能不一致

缓存策略示例

# 静态资源(带版本号):强缓存 1 年
Cache-Control: public, max-age=31536000, immutable

# HTML 文件:协商缓存
Cache-Control: no-cache

# API 接口:不缓存
Cache-Control: no-store

关键点

  • 强缓存直接使用本地资源不发请求,协商缓存需要向服务器验证返回 304 或 200
  • Cache-Control 优先级高于 Expires,ETag 优先级高于 Last-Modified
  • Expires 使用绝对时间存在时间不同步问题,Cache-Control 使用相对时间解决了这个问题
  • Last-Modified 精度只到秒且基于修改时间,ETag 基于内容 hash 更精确但有计算开销
  • 实际应用中通常组合使用:静态资源用强缓存,HTML 用协商缓存,API 不缓存