> 技术文档 > HTTP强制缓存与协商缓存详解

HTTP强制缓存与协商缓存详解

HTTP 缓存有两种实现方式,分别是强制缓存和协商缓存

两种缓存方式的核心差异

  • 强制缓存(Freshness / 强缓存)
    浏览器根据响应里给的“新鲜度”判断是否还能直接用本地副本。命中时不发请求
    关键响应头:Cache-Control(最重要)、Expires(备选,老标准)。
  • 协商缓存(Revalidation / 协商)
    没有新鲜度或已过期时,浏览器会带上条件请求去问服务器“我这份是否还有效?”。若没变更,服务器回 304 Not Modified,省下响应体。
    关键响应头(服务端回):ETagLast-Modified
    关键请求头(客户端发):If-None-Match(对应 ETag)、If-Modified-Since(对应 Last-Modified)。

简单记:强缓存=0 次网络,协商缓存=1 次轻量网络(304)

1. 强制缓存技术

HTTP响应头部维护两个字段来表示强制缓存分别是:

  • Cache-Control, 是一个相对时间
  • Expires,是一个绝对时间;

优先级:Cache-Control > Expires

当浏览器第一次请求访问服务器资源时,服务器会在返回这个资源的同时,在 Response 头部加上Cache-Control,Cache-Control 中设置了过期时间大小;

浏览器再次请求访问服务器中的该资源时,会先通过请求资源的时间与 Cache-Control 中设置的过期时间大小,来计算出该资源是否过期,如果没有,则使用该缓存,否则重新请求服务器;

服务器再次收到请求后,会再次更新 Response 头部的 Cache-Control。

2. 协商缓存技术

2.1. If-Modified-Since Last-Modified

响应头部中的Last-Modified:标示这个响应资源的最后修改时间;


请求头部中的If-Modified-Since:当资源过期了,发现响应头中具有Last-Modified 声明,则再次发起请求的时候带上 Last-Modified 的时间,服务器收到请求后发现有 If-Modified-Since 则与被请求资源的最后修改时间进行对比(Last-Modified),如果最后修改时间较新(大),说明资源又被改过,则返回最新资源,HTTP 200 OK;如果最后修改时间较旧(小),说明资源无新修改,响应 HTTP 304 走缓存。

2.2. f-None-Match ETag

响应头部中Etag:唯一标识响应资源;

请求头部中的If-None-Match:当资源过期时,浏览器发现响应头里有 Etag,则再次向服务器发起请求时,会将请求头 If-None-Match 值设置为 Etag 的值。服务器收到请求后进行比对,如果资源没有变化返回 304,如果资源变化了返回 200。


2.3. 区别

第一种实现方式是基于时间实现的,第二种实现方式是基于一个唯一标识实现的,相对来说后者可以更加
准确地判断文件内容是否被修改,避免由于时间篡改导致的不可靠问题。
如果在第一次请求资源的时候,服务端返回的 HTTP 响应头部同时有 Etag 和 Last-Modified 字段,那么客户端再下一次请求的时候,如果带上了 ETag 和Last-Modified 字段信息给服务端,这时 Etag 的优先级更
高,也就是服务端先会判断 Etag 是否变化了,如果 Etag 有变化就不用在判断Last-Modified 了,如果
Etag 没有变化,然后再看Last-Modified。

3. 总结

协商缓存这两个字段都需要配合强制缓存中 Cache-Control 字段来使用,只有在未能命中强制缓存的时候,才能发起带有协商缓存字段的请求。