“两次请求”帮你理解浏览器缓存策略

其实以前一篇《WebView缓存原理分析和应用》学习笔记,其中已经提到了浏览器缓存机制是“经过 HTTP 协议 header 里的Cache-Control(或Expires)和Last-Modified(或Etag)等字段来控制文件缓存的机制”。html

今天继续将这整个过程详细梳理了一遍,绘图以下:git

为了方便理解,咱们 假设浏览器发起两次请求 来分析这整个过程:github

第一次请求

很显然,第一次请求,你们都理解,这时候浏览器端是 没有缓存 的,因此会直接向服务器发送请求,且 不携带任何缓存相关参数web

此时,服务器接收到资源请求时,会在 响应头 中加入以下 几类 参数(注意:这些参数对于浏览器而言是有优先级的!且对应着“浏览器端不一样的缓存策略”)segmentfault

第一类:浏览器

  • Expires:服务端设置的一个“资源过时时间”,可是由于客户端和服务端时间有偏差,会致使缓存命中的偏差,所以优先级较低
  • Cache-Control:控制缓存的行为,通常取值有 private(默认)、public、no-cache、max-age,no-store,但咱们通常常见的值是 max-age,缓存的内容将在多少秒后失效

第二类:缓存

  • Last-Modified:资源的最后修改时间。
  • ETag:资源在服务器的惟一标识(生成规则由服务器决定,例如内容的hash值)

对于浏览器接收到这些头参数的优先级是:Cache-Control > Expires > ETag > Last-Modified服务器

ok,至此,服务端就将携带缓存头参数的信息返回给了浏览器,浏览器接收以后,一方面解析加载到浏览器上,另外一方面会存储下来。post

第二次请求

那第二次请求的时候,首先就会 先判断本地是否有缓存,没有的话,就回到第一次请求的流程。学习

固然,在咱们这里是有缓存的。

这里首先会判断 缓存是否过时 => 其实这里是所谓的 “强制缓存策略”。 若是没过时,很显然,都 不须要发出请求,直接使用缓存资源便可

若是过时了就会检查 ETag 和 Last-Modified 这两个参数,不管如何都会再次向服务器发出请求。 => “对比缓存策略”。 ETag 对应头参数 If-None-Match,Last-Modified 对应头参数 If-Modified-Since,其中前者优先级更高。

向服务端发起携带缓存头参数(If-None-Match 和(或)If-Modified-Since )的请求后,服务端会决策浏览器端缓存的资源是不是最新的。若是是(也便是其实缓存资源和服务端相同,未修改过),就会返回只带响应头的响应报文,且状态码是咱们常见的304。不然就会和第一次请求同样,从新返回最新的资源。

固然,不管是200仍是304,都还会携带缓存资源的 Expires 或 Cache-Control 以及缓存时间信息 。(此处不肯定,待查验)

好像并无,疑惑ing,这样下次不仍是会判断过时吗,会一直304。想不通...

关于 304 状态码参照:RFC 7232 - Hypertext Transfer Protocol (HTTP/1.1): Conditional Requests

另外,须要注意的是,若是“有缓存,且未过时”,在Chrome中的状态也会是200,点开看会发现是 “200 (from memory cache)”

参考资料:

( 原文发布在个人知乎专栏“乱码一通”:zhuanlan.zhihu.com/p/47737334

相关文章
相关标签/搜索