浏览器缓存总结

406 阅读6分钟

缓存策略

浏览器对所有请求的资源有一套完整的缓存策略,其主要分为三个部分,缓存存储策略,缓存失效策略以及缓存对比策略。

  • 缓存存储策略:发生在收到请求响应之后,用于决定是否对某个资源进行相应的缓存操作,以及能被哪些客户端存储。
  • 缓存失效策略:发生在请求发送到服务器之前。用于决定是从浏览器缓存中获取资源还是从服务器请求资源。涉及的缓存方法是 强制缓存启发式缓存
  • 缓存对比策略:一定会发送请求到服务器,但是资源的获取是根据服务器的返回决定从浏览器缓存获取还是从服务器获取。涉及的缓存方法是 协商缓存

注意:缓存失效策略和缓存对比策略的启用与否必须是建立在该资源存在缓存存储策略的基础上。

浏览器缓存流程图

HTTP 首部字段

首部字段 描述
Expires Expires: Sat, 24 Aug 2019 04:43:11 GMT 指定缓存过期的时间,与缓存储存策略和缓存过期策略相关,指定缓存过期的时间,绝对时间,存在服务器和客户端时期不一致进而导致缓存的不正确
Cache-Control 常用的值由 Cache-Control: max-age=60,public,private,no-cache,no-store,must-revalidate 该首部字段涉及了缓存存储策略,缓存过期策略以及缓存对比策略,比较复杂,下文单独说明
Last-Modified Last-Modified: Sat, 24 Aug 2019 04:43:11 GMT 响应首部字段,表示资源的最后修改时间
If-Modified-Since If-Modified-Since: Sat, 24 Aug 2019 04:43:11 GMT 请求的首部字段,其值由上一次响应的 Last-Modified 决定,如果资源在指定时间之后未发生修改,服务器返回 304 Not Modified,否则返回新的资源并更新浏览器缓存
If-Unmodified-Since If-Unmodified-Since: Sat, 24 Aug 2019 04:43:11 GMT 请求的首部字段,其值由上一次响应的 Last-Modified 决定,如果资源在指定时间之后发生修改,服务器返回 412 Precondition Failed,否则返回新的资源并更新浏览器缓存
Etag Etag: xxxxxx 请求资源的唯一标识字符串
If-No-Match If-No-Match: xxxxxx 缓存协商校验字段,请求资源的唯一标识字符串,为上次请求收到的ETag的值,如值没有发生变化,服务器返回 304 Not Modified,否则返回新的资源并更新浏览器缓存
If-Match If-Match: xxxxxx 缓存协商校验字段,请求资源的唯一标识字符串,为上次请求收到的ETag的值,如果值未发生变化,返回新的资源并更新浏览器缓存, 否则服务器返回 412 Precondition Failed

Cache-Control 首部字段

Cache-Control 用于指定资源的缓存策略,可以同时在请求头和响应头中设置。其同时涉及缓存存储,缓存过期以及缓存对比这三个策略,其取值如下:

  • max-age=xx: 设置缓存过期时间,是一个相对时间,单位为秒, 即在xx秒后缓存失效。此时采用强缓存方法,当 max-age=0 的时候采用协商缓存方法。当 Expires: xxxxxxxCache-Control: max-age=xxx 同时出现时, Cache-Control 的优先级更高;
  • public:该资源可以被客户端,代理服务器缓存,即缓存资源是所有人都可见的;
  • private:该资源只能被客户端缓存,代理服务器不允许缓存,即缓存资源只针对特定用户可见;
  • no-cache: 资源可以被缓存,但是每次请求时都必须向服务器发起协商缓存;其等价于 max-age=0;must-revalidate
  • no-store:该资源不允许被缓存,客户端,代理服务器都不允许缓存,每次都需要从服务器端获取资源;
  • must-revalidate:资源可缓存,浏览器必须向服务器发送请求,验证资源是否还有效存。

缓存方法

强制缓存

强制缓存:当客户端请求后,会先访问缓存数据库看缓存是否存在。如果存在则直接返回;不存在则请求真的服务器,响应后再写入缓存数据库。

与强制缓存相关的 HTTP 首部字段: ExpiresCache-Control;设置缓存过期的时间, Cache-Control 的优先级高于 Expires

启发式缓存

启发式缓存:当缓存过期时间的字段一个都没有的时候,浏览器下次并不会直接进入协商阶段,而是先进入启发式缓存阶段,你可以通过关闭服务器,刷新页面来观察。它根据响应头中2个时间字段 DateLast-Modified 之间的时间差值,取其值的 10% 作为缓存时间周期。也就是说,当存有 Last-Modified 字段的时候,即使是断网,且强缓存都失效后,也有一定时间是直接读取缓存文件的。

协商缓存

当浏览器对某一个资源没有命中强制缓存时,则会启动协商缓存,即向服务器发送一个请求验证该资源的是否有更新,没有更新则返回 304 Not Modified,并从浏览器本地缓存数据库获取资源,否则从服务器返回资源,并更新缓存数据库。

与协商缓存相关的 HTTP 首部字段:

  • Last-Modified & If-Modified-Since:浏览器第一次请求一个资源的时候,服务器返回的 header 中会加上Last-ModifyLast-modify 是一个时间标识该资源的最后修改时间,例如 Last-Modify: Thu,31 Dec 2037 23:59:59 GMT。当浏览器再次请求该资源时,request 的请求头中会包含 If-Modify-Since,该值为缓存之前返回的Last-Modify。服务器收到 If-Modify-Since 后,根据资源的最后修改时间判断是否命中缓存。如果命中缓存,则返回 304 Not Modified,并且不会返回资源内容,并且不会返回 Last-Modify
  • Etag & If-No-MatchEtag & If-None-Match返回的是一个校验码。ETag 可以保证每一个资源是唯一的,资源变化都会导致 ETag 变化。服务器根据浏览器上送的 If-None-Match 值来判断是否命中缓存。与 Last-Modified 不一样的是,当服务器返回 304 Not Modified 的响应时,由于 ETag 重新生成过,response header 中还会把这个 ETag 返回,即使这个 ETag 跟之前的没有变化。

Etag & If-No-Match 优先级高于 Last-Modified & If-Modified-Since

浏览器缓存xmind

参考文献

浅谈浏览器缓存机制
HTTP基于缓存策略三要素分解法
浏览器缓存策略之扫盲篇
一文读懂前端缓存