浏览器的缓存机制
通常浏览器缓存策略分为两种,强缓存和协商缓存。并且缓存策略都是通过设置HTTP Header来实现的
缓存过程分析
浏览器第一次向服务器发送请求后拿到请求结果,将请求结果和缓存标识存入浏览器缓存中,浏览器对于缓存的处理是根据第一次请求资源时返回的响应头来确定的
强缓存
不会向服务器发送请求,直接从缓存中读取资源,请求返回200的状态码,强缓存通过设置两种http header实现:Expires和 Cache=Control
Expires用来指定资源到期的时间,在响应http请求头时告诉浏览器在过期时间前可以直接从浏览器缓存取数据,而无需再次请求 Expires是Http 1的产物,受限于本地时间,如果本地资源修改了,会造成缓存失效
Cache-Control也是用来判断资源过期时间,但是里面有更多的配置
- public所有内容都将被缓存
- private所有内容只有客户端可以缓存
- no-cache是否缓存,需经过协商缓存来验证决定
- no-store所有内容都不会进行缓存,即不使用强缓存也不使用协商缓存
- max-age:30表示缓存内容将在30秒后失效
- s-maxage同max-age一样,只在代理服务器中生效(比如CDN缓存)
- max-stale能容忍的最大过期时间
- min-fresh能容忍的最小新鲜度
Expires和Cache-Control同时存在的话,Cache-Control的优先级高于Expires,强缓存判断是否缓存的依据来自于是否超过了某个时间或者某个时间段,而不关心服务端文件是否更新,这可能导致加载的文件不是服务端的最新内容,那我们如何获知服务器端内容是否已经发生了更新呢?此时我们需要用到协商缓存策略。
协商缓存
协商缓存就是强缓存失效后,浏览器携带缓存标识向服务器发起请求 协商缓存生效,返回304状态码 协商缓存失效,返回200
协商缓存可以通过设置HTTP Hearder实现last-Modified和Etag
last-Modified和if-Modified-Since
浏览器在第一次访问资源时,服务器返回资源的同时,在response header中添加 Last-Modified的header,值是这个资源在服务器上的最后修改时间,浏览器接收后缓存文件和header; 。
Last-Modified: Fri, 22 Jul 2016 01:47:00 GMT
浏览器下一次请求这个资源,浏览器检测到有 Last-Modified这个header,于是添加If-Modified-Since这个header,值就是Last-Modified中的值;服务器再次收到这个资源请求,会根据 If-Modified-Since 中的值与服务器中这个资源的最后修改时间对比,如果没有变化,返回304和空的响应体,直接从缓存读取,如果If-Modified-Since的时间小于服务器中这个资源的最后修改时间,说明文件有更新,于是返回新的资源文件和200
ETag和If-None-Match
Etag是服务器响应请求时,返回当前资源文件的一个唯一标识(由服务器生成),只要资源有变化,Etag就会重新生成。浏览器在下一次加载资源向服务器发送请求时,会将上一次返回的Etag值放到request header里的If-None-Match里,服务器只需要比较客户端传来的If-None-Match跟自己服务器上该资源的ETag是否一致,就能很好地判断资源相对客户端而言是否被修改过了。如果服务器发现ETag匹配不上,那么直接以常规GET 200回包形式将新的资源(当然也包括了新的ETag)发给客户端;如果ETag是一致的,则直接返回304知会客户端直接使用本地缓存即可。
3.两者之间对比:
- 首先在精确度上,Etag要优于Last-Modified。
Last-Modified的时间单位是秒,如果某个文件在1秒内改变了多次,那么他们的Last-Modified其实并没有体现出来修改,但是Etag每次都会改变确保了精度;如果是负载均衡的服务器,各个服务器生成的Last-Modified也有可能不一致。
- 第二在性能上,Etag要逊于Last-Modified,毕竟Last-Modified只需要记录时间,而Etag需要服务器通过算法来计算出一个hash值。
- 第三在优先级上,服务器校验优先考虑Etag