浏览器缓存机制

前言

缓存是性能优化中简单高效的优化方式,可以缩短网页请求资源的距离,减少延迟,并且由于缓存文件可以重复利用,还可以减少带宽,降低网络负荷,可以极大的提升用户体验。

为什么可以优化性能呢?若浏览器已经将资源缓存下来,那么再次需要资源时,可以直接使用缓存而不发送请求或发起请求后但浏览器缓存与服务器存储内容一样则不必再将数据传回。

image

缓存位置

一共有4个缓存位置,存在优先级,当依次查找都未命中时,才会去请求网络。

  • Service Worker
  • Memory Cache
  • Disk Cache
  • Push Cache

Service Worker

Service Worker是运行在浏览器背后的独立线程,一般用来实现缓存功能。要使用Service Worker的话,要求传输协议必须为HTTPS。Service Worker 的缓存与浏览器其他内建的缓存机制不同,它可以让我们自由控制缓存哪些文件、如何匹配缓存、如何读取缓存,并且缓存是持续性的

Service Worker 实现缓存功能一般分为三个步骤:首先需要先注册 Service Worker,然后监听到 install 事件以后就可以缓存需要的文件,那么在下次用户访问的时候就可以通过拦截请求的方式查询是否存在缓存,存在缓存的话就可以直接读取缓存文件,否则就去请求数据。

Memory Cache

Memory Cache是内存中的缓存,主要包含的是当前页面中已经抓取到的资源。例如页面上已下载的样式、脚本、图片等。读取速度快,但容量小且持续时间短,一旦关闭Tab页面,内存中的缓存即被释放。

Disk Cache

Disk Cache即存储在硬盘中的缓存,读取速度慢,但容量的,存储时效长。

Memory Cache Disk Cache
相同点 只能存储一些派生类资源文件 只能存储一些派生类资源文件
不同点 退出进程时数据会被清除 退出进程时数据不会被清除
存储资源 一般脚本、字体、图片会存在内存当中 一般非脚本会存在内存当中,如css等

Push Cache

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

缓存机制

对于浏览器的缓存来讲,缓存规则是在HTTP协议头部和HTML页面的Meta标签中定义的。分别从新鲜度和校验值两个维度来规定浏览器是否可以直接使用缓存中的副本,还是需要去源服务器获取新版本。

过期机制

指的是缓存副本的有效期。一个缓存的副本必须满足以下任一条件,浏览器会认为它是有效的,足够新的,可以使用的:

  1. 含有完整的过期时间控制头信息(HTTP协议报头),并且仍在有效期内
  2. 浏览器已经使用过这个缓存副本,并且会在一个会话中已经检查过新鲜度(即服务器上的资源是否发生改变)

校验值

服务器返回资源的时候有时在控制头信息带上这个资源的实体标签Etag(Entity Tag),可以用来作为浏览器再次请求过程中的校验标识,如果发现不匹配,说明资源已经被修改或过期,浏览器需要重新获取资源内容。

缓存过程分析

浏览器缓存在已经将资源缓存下来的条件下才成立。在浏览器第一次请求某资源时,由于其从未缓存过,所以是另一套缓存流程。

浏览器每次发送请求,都会先在浏览器缓存中查找该请求的结果和缓存标识。

浏览器每次拿到返回的请求结果都会将该结果和缓存标识存入浏览器缓存中。

img

我们根据是否需要向服务器重新发起HTTP请求将缓存过程分为两种方式:强缓存和协商缓存。

强缓存 协商缓存
定义 用户发送请求,直接从客户端缓存中获取,不发送请求到服务器,不与服务器发生交互行为 用户发送请求,发送到服务端之后,由服务器判断是否从缓存中获取资源
共同 客户端最后获取的数据都是从客户端缓存中获得 客户端最后获取的数据都是从客户端缓存中获得
区别 不与服务器发生交互 需要与服务器发生交互

强缓存

强缓存不会向服务器发送请求,直接从缓存中读取资源。可以通过设置两种HTTP Header实现:Expires和Cache-Control。

Expires

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

Cache-Control

HTTP/1.1新增,主要用于控制网页缓存。可以在请求头或响应头中设置,并且可以组合使用多种指令。

imgimg

对比

所处HTTP版本不同,Expires是过时的产物,当两者同时存在时,Cache-Control优先级高于Expires。

强缓存不关心服务器端的文件是否更新,这可能会导致加载文件不是服务端最新内容,此时就需要协商缓存策略。

协商缓存

协商缓存就是在强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程,主要情况分为协商缓存生效和协商缓存失效。

  • 协商缓存生效,返回304和Not Modified,表示服务端内容未更新,可以直接使用浏览器中缓存的内容

    img

  • 协商缓存失败,返回200和请求结果,表示服务端内容更新,重新返回请求结果

    img

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

Last-Modified和If-Modified-Since

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

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

img

弊端:

  • 如果本地打开缓存文件,即使没有对文件进行修改,但还是会造成 Last-Modified 被修改,服务端不能命中缓存导致发送相同的资源
  • 因为 Last-Modified 只能以秒计时,如果在不可感知的时间内修改完成文件,那么服务端会认为资源还是命中了,不会返回正确的资源
ETag和If-None-Match

ETag是服务器响应请求时,返回当前资源文件的一个唯一标识(由服务器生成),只要资源变化,ETag就会重新生成。浏览器在下一次加载资源向服务器发送请求时,会将上一次返回的Etag值放到request header里的If-None-Match里,服务器只需要比较客户端传来的If-None-Match跟自己服务器上该资源的ETag是否一致,就能很好地判断资源相对客户端而言是否被修改过了。如果服务器发现ETag匹配不上,那么直接以常规GET 200回包形式将新的资源(当然也包括了新的ETag)发给客户端;如果ETag是一致的,则直接返回304知会客户端直接使用本地缓存即可。

img

对比
  • 在精确度上,ETag优于Last-Modified
  • 在性能上,ETag差于Last-Modified,因为ETag需要服务器通过算法计算出一个hash值
  • 在优先级上,服务器校验优先考虑ETag

流程

浏览器请求到展示资源的整个过程

图片61.png

参考

深入理解浏览器的缓存机制

浅谈 Web 缓存


HeXuan
9 声望1 粉丝