强缓存与协商缓存

 

强缓存与协商缓存

浏览器缓存其实是http缓存,主要是通过http请求头或响应头中的某些字段控制的

这篇文章中,讲解了http请求发起到响应的整体过程,流程图大概如下

缓存过程

第一次发起http请求的时候,浏览器会首先去缓存中查找是否有该请求的资源,没有的话才会真正的去服务器请求。

强缓存

与强缓存有关的http响应头字段为Cache-ControlExpires , 如果响应头中同时包含这两个字段,那么Cache-Control的优先级要高于Expires

Cache-Control

Cache-ControlHTTP/1.1中的重要规则,主要用于控制网页缓存,主要有以下几个属性

  • public: 所有内容都可以缓存(客户端和代理服务器都可以缓存)
  • private: 所有内容只有客户端可以缓存(默认值)
  • no-cache: 客户端缓存内容,但每次使用之前都必须去服务器验证缓存是否过期,是否有最新版本
  • no-store: 不允许缓存
  • must-revalidate: 缓存如果没过期就可以继续使用,过期还想用必须去服务器验证
  • max-age: 缓存在xxx秒后过期

Expires

ExpiresHTTP/1.0中控制网页缓存的字段,其值为服务器返回该请求结果缓存的到期时间,当再次发起该请求时,如果客户端的时间小于Expires时,直接使用缓存。

Expires是存在问题的,当客户端和服务器端的时间不一致时,例如客户端自己调整过时间或者时区不一致,可能会导致强制缓存失效。

协商缓存

当强缓存失效以后,就会启用协商缓存,与协商缓存有关的响应头字段为Last-ModifiedETag, 请求头字段为If-Modified-SinceIf-None-Match , 当响应头中同时包含这两个字段时,ETag字段优先级大于Last-Modified

Last-Modified/If-Modified-Since

Last-Modified是服务器响应请求时, 返回该资源在服务器上最后的修改时间, 当客户端再次发起该请求时, 会在请求头上带上If-Modified-Since字段,值为上次请求返回的Last-Modified的值。通过此字段是为了告诉服务器上次请求时该资源的最后修改时间。服务器接收到该请求后,发现有If-Modified-Since字段,则会读取该字段与服务器上该资源最后修改时间做对比,如果相等,则状态码返回304,告诉客户端可以继续用缓存里的资源,并更新一下缓存有效期,否则,状态码返回200, 并返回最新资源以及重新存入缓存。

Last-Modified


If-Modified-Since

但是这两个字段判断缓存也是有问题的

  1. 文件非内容的修改,这个时候我们并不希望客户端认为这个文件修改了,从而重新请求
  2. 某些文件修改的特别频繁,1s内修改好几次,If-Modified-Since能检查的时间粒度是秒级的,这种修改无法判断
  3. 某些服务器不能精确的得到文件的最后修改时间

ETag/If-None-Match

为了解决上述问题, 所以HTTP/1.1才会增加了ETag/If-None-Match两个字段

ETag是服务返回请求时,响应头中所携带的字段,代表该资源的一个唯一标识符(由服务器生成),当文件内容修改以后,该值就会发生变化,类似使用MD5、SHA等生成的唯一标识符。

当客户端再次发起该请求时,会在请求头中携带If-None-Match字段,该字段的值为上次请求时ETag的值,当服务器接收到该请求时,发现请求头中有If-None-Match字段,会自动读取该字段,与服务器上该资源的唯一标识符进行比较,如果相等,则状态码返回304,告诉客户端缓存还可以用,浏览器会更新缓存有效期,否则返回200, 重新返回最新资源,并重新缓存。

ETag


If-None-Match

总结

强缓存优先级大于协商缓存,当强缓存有效时,直接使用缓存里的资源加载页面,如果强缓存失效,则启用协商缓存,协商缓存是由服务器决定缓存是否有效的,如果服务器判断缓存有效,会返回状态码304,告诉客户端可以继续使用缓存,否则,状态码为200, 并返回最新资源。

缓存流程图