其实以前一篇《WebView缓存原理分析和应用》学习笔记,其中已经提到了浏览器缓存机制是“经过 HTTP 协议 header 里的Cache-Control(或Expires)和Last-Modified(或Etag)等字段来控制文件缓存的机制”。html
今天继续将这整个过程详细梳理了一遍,绘图以下:git
为了方便理解,咱们 假设浏览器发起两次请求 来分析这整个过程:github
很显然,第一次请求,你们都理解,这时候浏览器端是 没有缓存 的,因此会直接向服务器发送请求,且 不携带任何缓存相关参数。web
此时,服务器接收到资源请求时,会在 响应头 中加入以下 几类 参数(注意:这些参数对于浏览器而言是有优先级的!且对应着“浏览器端不一样的缓存策略”)segmentfault
第一类:浏览器
第二类:缓存
对于浏览器接收到这些头参数的优先级是: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 )