您的当前位置:首页第7题-浏览器缓存命中策略

第7题-浏览器缓存命中策略

2024-12-13 来源:哗拓教育

面试题目:

答案解析:

浏览器缓存是性能优化中简单高效的一种方式,按照缓存位置划分为以下几种类型:

  1. service Worker
  2. Memory Cache
  3. Disk Cache
  4. Push Cache

浏览器请求时,会按照如上的优先级顺序,进行查找缓存,都没有命中时,才会去请求网络。

面试过程中问到的浏览器缓存相关问题,一般是针对Disk Cache而言的,也就是硬盘缓存,下面我们主要对硬盘缓存进行详细解析下。

硬盘缓存分为以下两种类型

  1. 强缓存
  2. 协商缓存

强缓存

强缓存特点是:不需要向服务器发出请求,直接从硬盘缓存中读取想要的资源。在Chrome调试面板 Network面板中,能看到该类请求会返回200状态码,Size 字段显示 from disk cache,如下图所示:

硬盘缓存

当我们自己打开一个web页面查看的时候,会发现第一次打开一般都是请求的服务器,然后点击刷新按钮,刷新当前页面,发现 Size 字段并没有出现from disk cache,而是显示from memory cache,这是为什么呢?

Memory Cache

这是因为浏览器请求资源时,命中了memory cache,也就是所谓的内存缓存,内存缓存的优先级高于硬盘缓存,也比硬盘缓存的速度快。

如何复现出 disk cache 呢?

重新打开一个浏览器的tab栏,输入页面地址打开,这个时候就会看到 disk cache 了。原因是每个tab栏都会启动新的进程,所以就不会共享内存,也就不会命中memory cache了。

强缓存有两个头字段控制:ExpiredCache-Control

Expired

比如Expires:Thu,31 Dec 2037 23:59:59 GMT。这个时间代表着这个资源的失效时间,也就是说在2037年12月31日23点59分59秒之前都是有效的,即命中缓存。这种方式有一个明显的缺点,由于失效时间是一个绝对时间,所以当客户端本地时间被修改以后,服务器与客户端时间偏差变大以后,就会导致缓存混乱。于是发展出了Cache-Control。

Expired

Cache-Control

Cache-Control是一个相对时间,例如Cache-Control:3600,代表着资源的有效期是3600秒。由于是相对时间,并且都是与客户端时间比较,所以服务器与客户端时间偏差也不会导致问题。
Cache-ControlExpires可以在服务端配置同时启用或者启用任意一个,同时启用的时候Cache-Control优先级高。

Cache-Control 可以由多个字段组合而成,主要有以下几个取值:

  1. max-age 指定一个时间长度,在这个时间段内缓存是有效的,单位是s。例如设置 Cache-Control:max-age=31536000,也就是说缓存有效期为(31536000 / 24 / 60 * 60)天,第一次访问这个资源的时候,服务器端也返回了 Expires 字段,并且过期时间是一年后。在没有禁用缓存并且没有超过有效时间的情况下,再次访问这个资源就命中了缓存,不会向服务器请求资源而是直接从浏览器缓存中取。
Cache-Control
  1. s-maxage 同 max-age,覆盖 max-age、Expires,但仅适用于共享缓存,在私有缓存中被忽略。

  2. public 表明响应可以被任何对象(发送请求的客户端、代理服务器等等)缓存。

  3. private 表明响应只能被单个用户(可能是操作系统用户、浏览器用户)缓存,是非共享的,不能被代理服务器缓存。

  4. no-cache 强制所有缓存了该响应的用户,在使用已缓存的数据前,发送带验证器的请求到服务器。不是字面意思上的不缓存。

  5. no-store 禁止缓存,每次请求都要向服务器重新获取数据。

  6. must-revalidate指定如果页面是过期的,则去服务器进行获取。这个指令并不常用,就不做过多的讨论了。

协商缓存

Last-Modified/If-Modified-Since

浏览器第一次请求一个资源的时候,服务器返回的header中会加上Last-Modify,Last-Modified是一个时间标识该资源的最后修改时间,例如Last-Modified: Thu,31 Dec 2037 23:59:59 GMT

Last-Modified

当浏览器再次请求该资源时,发送的请求头中会包含If-Modified-Since,该值为缓存之前返回的Last-Modified。服务器收到If-Modified-Since后,根据资源的最后修改时间判断是否命中缓存。

ETag/If-None-Match

Last-Modified/If-Modified-Since不同的是,Etag/If-None-Match返回的是一个校验码(ETag: entity tag)。ETag可以保证每一个资源是唯一的,资源变化都会导致ETag变化。ETag值的变更则说明资源状态已经被修改。服务器根据浏览器上发送的If-None-Match值来判断是否命中缓存。

既然last-modify可以识别出资源是否更新,为什么还需要ETag呢?

  1. Last-Modified标注的最后修改只能精确到秒级,如果某些文件在1秒钟以内,被修改多次的话,它将不能准确标注文件的修改时间

  2. 如果某些文件会被定期生成,但内容并没有任何变化,Last-Modified却改变了,导致该文件被认为更新了,无法使用缓存。

由于ETag是服务器生成的唯一标识符,能够更加准确的控制缓存,所以ETag的优先级高于last-Modified

总结

浏览器请求时的大致过程描述如下:

  1. 浏览器发出http请求前,先根据Cache-ControlExpired 字段判断缓存是否过期(两个字段同时存在的情况下,根据Cache-Control判断,该字段不存在时根据Expired判断)。如果没有过期,浏览器不发出http请求,直接从硬盘缓存中读取资源;如果已过期,则进行第2步逻辑;
  2. 向服务器发出http请求,其中request headers上会携带If-none-matchIf-Modified-since字段,服务器收到请求后,会将If-none-match字段和本地的资源的ETag进行比较,如果二者不相等,则资源已更新,会返回200状态码和资源数据,响应头也会带上最新的资源ETag;如果二者相等,则命中缓存,返回304,浏览器收到响应后会读取本地缓存资源。如果If-none-match字段不存在,服务器会根据if-Modified-since字段进行比对资源的最后修改时间,处理逻辑基本和If-none-match一致。
流程图

补充

浏览器缓存行为还有用户的行为有关!!!

用户操作 Expires/Cache-Control Expires/Cache-Control
地址栏回车 有效 有效
页面链接跳转 有效 有效
新开窗口 有效 有效
前进、后退 有效 有效
F5刷新 无效 有效
Ctrl+F5刷新 无效 无效

扫一扫 关注我的公众号【前端名狮】,更多精彩内容陪伴你!

【前端名狮】
显示全文