浏览器缓存机制

缓存

缓存是网页性能优化中简单高效的一种优化方式,一个优秀的缓存策略可以缩短网页的请求资源的距离,减少延迟,并且由于缓存文件可以重复利用,还可以减少贷款,降低网络复核。

对于一个数据请求,可以分为 发起网络请求,后端处理,浏览器响应三个步骤。浏览起缓存可以帮助我们在第一和第三阶段优化性能。例如直接使用缓存而不乏其请求,或者发起请求了但后端存储的数据和前端一致,那么没必要在将数据回传回来,这样减少数据响应。

缓存位置

从缓存的位置的分为4种,并且各有优先级,当一次查找缓存且都没有的时候才会去请求网络.

  • Service Worker
  • Memory Cache
  • Disk Cache
  • Push Cache
  1. Service Worker 是运行在浏览器背后的独立线程,一般可以用来实现缓存功能。使用 Service Worker的话,传输协议必须为 HTTPS

  2. Memory Cache 也就是内存中的缓存,主要包含的是当前中页面中已经抓取到的资源,例如页面上已经下载的样式、脚本、图片等。读取内存中的数据肯定比磁盘快,内存缓存虽然读取高效,可是缓存持续性很短,会随着进程的释放而释放。

  3. Disk Cache 也就是存储在硬盘中的缓存,读取速度慢点,但是什么都能存储到磁盘中,比Memory Cache 胜在容量和存储时效性上,存储在硬盘中的缓存,读取速度慢点,但是什么都能存储到磁盘中,比之 Memory Cache 胜在容量和存储时效性上

  4. Push Cache(推送缓存)是 HTTP/2 中的内容,当以上三种缓存都没有命中时,它才会被使用。它只在会话(Session)中存在,一旦会话结束就被释放,并且缓存时间也很短暂。

缓存过程分析

浏览器与服务器通信的方式为应答模式,即:浏览器发起HTTP请求-服务器响应请求。那么浏览器怎么确定一个资源该不该被缓存,如何缓存? 浏览器在第一次向服务器发起请求,在拿到请求结果后,浏览器把请求结果和缓存标识放在浏览器缓存中。浏览器对于缓存的处理是根据第一次请求资源时返回的响应头来确定的。

  • 强缓存
  • 协商缓存
  1. 强缓存 不会向服务器发送请求,直接从缓存中读取资源,在chrome 控制台中的network 选项中可以看到该请求返回200 的状态码,并且在 size 显示 from disk cache 或者 from memory cache.强缓存可以通过设置两种 HTTP Header 实现:expires 和 cache-control。

    • Expires 缓存过期时间,用来指定资源到期的时间,是服务器端的具体的时间点。也就是说,Expires=max-age + 请求时间,需要和Last-modified结合使用。Expires是Web服务器响应消息头字段,在响应http请求时告诉浏览器在过期时间前浏览器可以直接从浏览器缓存取数据,而无需再次请求。

    • Cache-Control 在HTTP 1.1 中最重要的规则,主要控制网页缓存。比如当cache-control:max-age = 300 时,则代表在这个请求正确返回时间(浏览器也会记录先来)的300 秒 内在此加载,就会命中强缓存。Cache-Control 的指令组合图

    • Expires 和 Cache-Control两者对比
      其实这两者区别不大,区别在于 Expires 是http1.0 的产物,Cache-Control 是http 1.1 的产物,两者同时存在的话 cache-control 的优先级高于Expires;在某些不支持HTTP1.1 的环境下,Expires 就会发挥用处。 强缓存判断的一句句来自于时候超出某个时间段或者时间值,而不关心服务器端文件是否已经更新,这可能导致加载文件不是 服务端最新的内容,那我们如何获知服务器端内容是否是已经发生更新?此时我们需要用到协商缓存策略。

  2. 协商缓存
    协商缓存就是 强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定时候使用缓存的过程,主要有以下两种情况:

    • 协商缓存生效 返回 304 和 Not Modified
    • 协商缓存失效,返回200 和 数据结果

    协商缓存可以通过设置两种HTTP header 实现Last-Modified 和 ETag

    1. last-modified
      浏览器在第一次访问资源时,服务器返回资源的同时,在 response header 中添加 last-modified 的header, 值就是 这个资源在 服务器上的最后修改时间,浏览器接受后缓存文件 和 header

      Last-Modified: Fri, 22 Jul 2016 01:47:00 GMT

      浏览器下一次请求这个资源时,浏览器检测到有 Last-Modified 这个header,于是添加 if-Modifiled-Since 这个header ,值就是 last-midified 中的值;服务器再次受到这个资源请求,会根据 if-modified-since 中的值与 服务器中这个资源最后修改的时间比较,如果没有变化,返回 304 和空的响应体,直接从缓存读取,如果 if-midified-since的时间小于 服务器中的这个资源的最后修改时间,说明文件更新,返回200 和最新的资源

      但是 Last-Modified 存在一些弊端

      • 如果本地打开缓存文件,及时没有对文件进行修改,但还是会造成 Last-Modified被修改,服务端不能命中缓存导致发送相同的资源

      • 因为 Last-Modified 只能以 秒计时 ,如果在不可感知 的时间内修改完成文件,那么服务端会认为资源还是命中,不能返回正确的资源

    2. 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

缓存机制

强制缓存有心于协商缓存进行,若强制缓存(Expires和Cache-Control)生效则直接使用缓存,若不生效则进行协商缓存(Last-Modified / If-Modified-Since和Etag / If-None-Match),协商缓存由服务器决定是否使用缓存,若协商缓存失效,那么代表请求的缓存失效,返回200,重新返回资源和缓存标识,在存入浏览器缓存中;生效则返回304 ,继续使用缓存 缓存流程图

用户行为对浏览器缓存的影响

用户对浏览器的影响,指用户在浏览器如何操作时,会触发怎样的缓存策略主要有一下3种:

  • 打开网页,地址栏输入地址:查找 disk cache 中是否匹配,如果有则使用;没有则发送网络请求
  • 普通刷新(F5):因为TAB 并没有关闭,因此 memory cache 是可用的,会被优先使用(如果匹配的话)。其次才是disk cache
  • 强制刷新(Ctrl + F5):浏览器不使用缓存,因此发送的请求头部均带有Cache-control: no-cache(为了兼容,还带了 Pragma: no-cache),服务器直接返回 200 和最新内容。

参考文章

浏览器缓存机制;
谈谈WEB 缓存;

你可能感兴趣的:(浏览器缓存机制)