强缓存与内容协商

强缓存

强缓存:不用请求服务器,直接使用本地的缓存。

强缓存是利用 http 响应头中的ExpiresCache-Control实现的。

浏览器第一次请求一个资源时,服务器在返回该资源的同时,会把上面这两个属性放在 response header 中。比如:

注意:这两个 response header 属性可以只启用一个,也可以同时启用。当 response header 中,Expires 和 Cache-Control 同时存在时,Cache-Control 的优先级高于 Expires

下面讲一下二者的区别。

1、Expires:服务器返回的绝对时间。

是较老的强缓存管理 response header。浏览器再次请求这个资源时,先从缓存中寻找,找到这个资源后,拿出它的 Expires 跟当前的请求时间比较,如果请求时间在 Expires 的时间之前,就能命中缓存,否则就不行。

如果缓存没有命中,浏览器直接从服务器请求资源时,Expires Header 在重新请求的时候会被更新。

缺点:

由于Expires是服务器返回的一个绝对时间,存在的问题是:服务器的事件和客户端的事件可能不一致。在服务器时间与客户端时间相差较大时,缓存管理容易出现问题,比如随意修改客户端时间,就能影响缓存命中的结果。所以,在 http1.1 中,提出了一个新的 response header,就是 Cache-Control。

2、Cache-Control:服务器返回的相对时间。

http1.1 中新增的 response header。浏览器第一次请求资源之后,在接下来的相对时间之内,都可以利用本地缓存。超出这个时间之后,则不能命中缓存。重新请求时,Cache-Control会被更新。

协商缓存

协商缓存:浏览器发现本地有资源的副本,但是不太确定要不要使用,于是去问问服务器。

当浏览器对某个资源的请求没有命中强缓存(也就是说超出时间了),就会发一个请求到服务器,验证协商缓存是否命中。

协商缓存是利用的是两对 Header:

  • 第一对:Last-ModifiedIf-Modified-Since

  • 第二对:ETagIf-None-Match

ETag(Entity Tag):被请求变量的实体值”。

1、Last-ModifiedIf-Modified-Since。过程如下:

(1)浏览器第一次请求一个资源,服务器在返回这个资源的同时,会加上Last-Modified这个 response header,这个 header 表示这该资源在服务器上的最后修改时间:

(2)浏览器再次请求这个资源时,会加上If-Modified-Since这个 request header,这个 header 的值就是上一次返回的Last-Modified的值:

(3)服务器收到第二次请求时,会比对浏览器传过来的If-Modified-Since和资源在服务器上的最后修改时间Last-Modified,判断资源是否有变化。如果没有变化则返回 304 Not Modified,但不返回资源内容(此时,服务器不会返回 Last-Modified 这个 response header);如果有变化,就正常返回资源内容(继续重复整个流程)。这是服务器返回 304 时的 response header:

(4)浏览器如果收到 304 的响应,就会从缓存中加载资源。

缺点:

Last-ModifiedIf-Modified-Since一般来说都是非常可靠的,但面临的问题是:

  • 服务器上的资源变化了,但是最后的修改时间却没有变化。

  • 如果服务器端在一秒内修改文件两次,但产生的Last-Modified却只有一个值。

这一对 header 就无法解决这种情况。于是,下面这一对 header 出场了。

2、ETagIf-None-Match。过程如下:

(1)浏览器第一次请求一个资源,服务器在返回这个资源的同时,会加上ETag这个 response header,这个 header 是服务器根据当前请求的资源生成的唯一标识。这个唯一标识是一个字符串,只要资源有变化这个串就不同,跟最后修改时间无关,所以也就很好地补充了Last-Modified的不足。如下:

(2)浏览器再次请求这个资源时,会加上If-None-Match这个 request header,这个 header 的值就是上一次返回的ETag的值:

(3)服务器第二次请求时,会对比浏览器传过来的If-None-Match和服务器重新生成的一个新的ETag,判断资源是否有变化。如果没有变化则返回 304 Not Modified,但不返回资源内容(此时,由于 ETag 重新生成过,response header 中还会把这个 ETag 返回,即使这个 ETag 并无变化)。如果有变化,就正常返回资源内容(继续重复整个流程)。这是服务器返回 304 时的 response header:

参考链接:


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!