浏览器缓存

浏览器缓存类型

  • 本地缓存,也叫强缓存。使用本地缓存时,浏览器可以直接从本地的内存或磁盘中获取内容,不需要与服务器产生实际的交互
  • 协商缓存,也叫弱缓存。使用协商缓存时,浏览器需要先向服务器验证缓存内容的有效性,如缓存内容还是最新的,则浏览器可以使用该缓存

浏览器缓存控制

HTTP 1.1风格

服务器在返回资源到浏览器时,通过在HTTP响应头增加Cache-Control属性控制浏览器缓存

image-20220608142659449

例子

Cache-Control: max-age=31536000 开启浏览器缓存,缓存有效时间max-age,单位为秒。在缓存有效期间,命中本地缓存,不需要发送网络请求到服务器获取资源,而是直接取浏览器本地资源。缓存过期后,命中协商缓存,要通过服务器认证,确认缓存还是最新版本,才允许浏览器使用。如缓存并不是最新版本,则服务器返回完整资源。

Cache-Control: no-store 不开启任何浏览器缓存

Cache-Control: no-cache 不开启浏览器本地缓存,开启浏览器协商缓存,每次都要先通过服务器认证,确认缓存还是最新版本,才允许浏览器使用。如缓存并不是最新版本,则服务器返回完整资源

Cache-Control: public 资源可以被任何对象缓存,包括代理服务器等

Cache-Control: private 资源只可以被单个用户缓存,一般是指本地浏览器缓存

Cache-Control: must-revalidate 当资源需要服务器认证是否为最新版本时,假如连接不上服务器,则不能使用过期缓存。 反过来,不开启must-revalidate 则会使用过期缓存

HTTP 1.0风格

服务器在返回资源到浏览器时,通过在HTTP响应头增加Expires属性开启浏览器本地缓存。相当于HTTP 1.1风格的max-age

如果在Cache-Control响应头设置了 max-age 或者 s-max-age 指令,那么 Expires 头会被忽略

例子

Expires: Wed, 21 Oct 2015 07:28:00 GMT

隐式开启

也叫启发式缓存。服务器在返回资源到浏览器时,通过在HTTP响应头增加Last-Modified属性开启浏览器协商缓存,同时隐式开启本地缓存。根据HTTP规范算法,本地缓存时间为Date响应头的时间减去Last-Modified的时间,得出的时长再除以10

假如已通过前两种方式开启浏览器缓存,即使用了Cache-ControlExpires,隐式开启将被忽略

服务器认证缓存是否为最新版本

在浏览器本地缓存过期,或开启了no-cache的情况下,浏览器不会直接使用本地缓存,而是使用协商缓存,先向服务器发送请求,以确认缓存是否为最新版本。在这次请求中,服务器将会带上If-None-MatchIf-Modified-Since,属性的值分别对应获取当前浏览器缓存内容的那次响应的ETag值和Last-Modified值。同时存在的情况下,If-None-Match的优先级高于If-Modified-Since

ETag

服务器端开启ETag后,第一次请求资源,会通过某种算法计算ETag,然后将ETag放到响应头里面。浏览器将会缓存此ETag,如果浏览器再次请求同一资源,会把ETag的值放到请求头的If-None-Match属性里面。服务器接收第二次请求后,把将要返回的内容再次计算ETag,然后与请求头的If-None-Match的值比对。如果前后两次请求需要返回的内容有变化,则ETag的值也不同,服务器会返回完整的响应,响应状态码为200。否则,服务器返回不完整的响应,响应状态码为304

Last-Modified

ETag类似,只是不需要计算一个ETag,而直接取用资源的修改时间来代替。Last-Modified的优点是免去了计算ETag的消耗,缺点是修改时间一般只能精确到秒,还有Last-Modified值不同有可能资源内容却相同

通过Chrome的Network查看是否使用缓存

Status Size  
200 (from memory cache) 使用浏览器本地缓存,且缓存在内存中
200 (from disk cache) 使用浏览器本地缓存,且缓存在磁盘中
304 报文大小 使用浏览器协商缓存,且通过服务器验证,缓存为最新版本后,浏览器使用缓存
200 报文大小 没有使用浏览器缓存,或协商缓存不是最新版本,从服务器获取最新资源

使用浏览器查看缓存状态时,不要在开发者工具中勾选Disable cache

默认情况

在没有定义Cache-ControlLast-Modified的情况下,需要重新验证缓存有效性,相当于

Cache-Control: no-cache
# 或
Cache-Control: max-age=0, must-revalidate

参考文档