HTTP强制缓存与协商缓存详解
HTTP 缓存有两种实现方式,分别是强制缓存和协商缓存。
两种缓存方式的核心差异
- 强制缓存(Freshness / 强缓存)
浏览器根据响应里给的“新鲜度”判断是否还能直接用本地副本。命中时不发请求。
关键响应头:Cache-Control
(最重要)、Expires
(备选,老标准)。 - 协商缓存(Revalidation / 协商)
没有新鲜度或已过期时,浏览器会带上条件请求去问服务器“我这份是否还有效?”。若没变更,服务器回 304 Not Modified,省下响应体。
关键响应头(服务端回):ETag
或Last-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 字段来使用,只有在未能命中强制缓存的时候,才能发起带有协商缓存字段的请求。