浏览器之缓存

1. 浏览器缓存的作用

1)减少网络请求,优化性能,提升用户体验;
2)减少网络带宽消耗,降低运营成本;
3)减轻服务器压力;

1.1. 缓存过程分析

1.1.1. 浏览器第一次请求时:

在这里插入图片描述

1.1.2. 浏览器后续在进行请求时:

在这里插入图片描述
从上图可以知道,浏览器缓存包含两种类型,即强缓存(也叫本地缓存)和协商缓存,浏览器在第一次请求发生后,再次请求时:

  • 浏览器在请求某一资源时,会先获取该资源缓存的header信息,判断是否命中强缓存(cache-control和expires信息),若命中直接从缓存中获取资源信息,包括缓存header信息;本次请求根本就不会与服务器进行通信;在firebug下可以查看某个具有强缓存资源返回的信息,例如本地firebug查看的一个强缓存js文件:
    在这里插入图片描述
  • 如果没有命中强缓存,浏览器会发送请求到服务器,请求会携带第一次请求返回的有关缓存的header字段信息(Last-Modified/If-Modified-Since和Etag/If-None-Match),由服务器根据请求中的相关header信息来比对结果是否协商缓存命中;若命中,则服务器返回新的响应header信息更新缓存中的对应header信息,但是并不返回资源内容,它会告知浏览器可以直接从缓存获取;否则返回最新的资源内容。

1.1.3. 缓存读写顺序

当浏览器对一个资源(比如一个外链的 a.js)进行请求的时候会发生什么?请从缓存的角度大概说下:

在这里插入图片描述

  1. 调用 Service Worker 的 fetch 事件获取资源;
  2. 查看 memory cache;
  3. 查看 disk cache; 这里又细分:
  • 如果有强制缓存且未失效,则使用强制缓存,不请求服务器。这时的状态码全部是 200;
  • 如果有强制缓存但已失效,使用协商缓存,比较后确定 304 还是 200;
  1. 发送网络请求,等待网络响应;
  2. 把响应内容存入 disk cache (如果请求头信息配置可以存的话);
  3. 把响应内容的引用存入 memory cache (无视请求头信息的配置,除了 no-store 之外);
  4. 把响应内容存入 Service Worker 的 Cache Storage (如果 Service Worker 的脚本调用了 cache.put());

2. 缓存位置

缓存有4个位置:

2.1. Service Worker

是一个注册在特定源和路径下的事件驱动Worker,可以用于离线缓存,主要有5个特点是:
1)允许我们自己操控缓存;
2)运行在Worker上下文中,不能访问DOM;
3)独立于主线程之外,不会造成堵塞;
4)设计是完全异步的,同步API不能在Worker中使用;
5)处于安全考虑,必须使用HTTPS协议;

2.2. Memory Cache

是浏览器内存缓存,读取速度快,但是容量小、缓存时效低,一旦关闭浏览器页签,内存缓存就会被清楚。
当HTTP头设置了Cache-Control: no-store 或者 浏览器开发者工具设置了Disabled Cache 时,
资源将不会被缓存。
当从Memory Cache中查找资源时,不仅要匹配资源的URL还要看Content-Type是否相同。

2.3. Disk Cache

磁盘缓存,和内存缓存相比,存储控件大、缓存时效长,但是读取速度较慢。网站中绝大部分资源都存储在磁盘缓存中。
一般来说,大文件大概率会缓存在磁盘中;如果内存使用频率过高,资源也会缓存在磁盘中;

2.4. Push Cache

这个存储位置要求协议必须是HTTP/2,这种协议在国内使用不多。

3. 访问缓存的优先级

Service Worker > Memory Cache > Disk Cache
Dish Cache中有两种缓存策略:强缓存和协商缓存,强缓存的优先级大于协商缓存。

3.1. 如何知道资源是从哪里获取到的

在浏览器开发者工具的Network面板下,查看资源的Size属性。

statusSize说明
200from memory cache请求内存中的资源,一般脚本,字体,图片会存在内存中
200from disk cache请求磁盘中的资源,一般非脚本(例如,css)会存在中磁盘中
200文件大小从服务器请求到的资源
304报文大小请求服务器发现资源没有改变,使用本地资源

4. 缓存策略

在这里插入图片描述
感谢布兰同学的图片

根据HTTP header中的字段可以将缓存策略分为:强缓存和协商缓存。

强缓存可以直接从缓存中读取资源返回给浏览器而不需要向服务器发送请求;
协商缓存是当强缓存失效后(过了过期时间),浏览器需要携带缓存标识向服务器发送请求,服务器根据缓存标识决定是否使用缓存的过程。

4.1. 强缓存

强制缓存就是向浏览器缓存查找该请求结果,并根据该结果的缓存规则来决定是否使用该缓存结果的过程,强制缓存的情况主要有三种(暂不分析协商缓存过程),如下:

1)第一次请求,不存在缓存结果和缓存标识,直接向服务器发送请求:
感谢陈祥同学提供的图片
感谢陈祥同学提供的图片
2)存在缓存标识和缓存结果,但是已经失效,没有命中强制缓存,则使用协商缓存(暂不分析)
在这里插入图片描述
3)存在该缓存结果和缓存标识,且该结果尚未失效,强制缓存生效,直接返回该结果
在这里插入图片描述

4.1.1. 标识字段:Expires、Cache-Control

4.1.2. Expires

Expires 是 HTTP/1.0 的字段,缓存过期时间,用来指定资源到期的时间,是服务器端的具体的时间点。Expires是Web服务器响应消息头字段,如果发送请求的时间在expires之前,那么本地缓存始终有效,否则就会发送请求到服务器来获取资源。

Expires 受限于本地时间,如果修改了本地时间,可能会造成缓存失效。

4.1.3. Cache-Control

  1. max-age: 最大缓存时间,值的单位是秒,在该时间内,浏览器不需要向浏览器请求。是一个相对值;资源第一次的请求时间和Cache-Control设定的有效期,计算出一个资源过期时间,再拿这个过期时间跟当前的请求时间比较,如果请求时间在过期时间之前,就能命中缓存,否则就不行。这个设置解决了 Expires 中由于客户端系统时间不准确而导致缓存失效的问题;
  2. public 响应可以被任何对象(客户端、代理服务器等)缓存;
  3. private 响应只能被客户端缓存;
  4. no-cache 跳过强缓存,直接进入协商缓存阶段;
  5. no-store 不缓存任何内容,设置了这个后资源也不会被缓存到内存和硬盘;

需要注意的是,no-cache这个名字有一点误导。设置了no-cache之后,并不是说浏览器就不再缓存数据,只是浏览器在使用缓存数据时,需要先确认一下数据是否还跟服务器保持一致,也就是协商缓存。而no-store才表示不会被缓存,即不使用强制缓存,也不使用协商缓存。

当 Expires 和 Cache-Control 都被设置的时候,浏览器会优先考虑后者。
当资源过期、Cache-Cache的值为must-revalidate、no-cache 时,进入协商缓存。

4.2. 协商缓存

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

1)协商缓存生效,返回304和Not Modified
在这里插入图片描述
2)协商缓存失效,返回200和请求结果
在这里插入图片描述

4.2.1. 标识字段:Last-Modified 和 ETag:

4.2.2. Last-Modified和If-Modified-Since

二者的值都是GMT格式的时间字符串。

  1. 浏览器第一次向服务器请求资源后,服务器会在响应头中加上Last-Modified字段,表明该资源最后一次的修改时间;
  2. 浏览器再次请求该资源时,会在请求报文头中添加If-Modified-Since字段,它的值就是上次服务器响应报文中的Last-Modified的值;
  3. 服务器会比对Last-Modified与If-Modified-Since的值是否一致,如果不一致,服务器则接受请求,返回更新后的资源;如果一致,表明资源未更新,则返回状态码为304的响应,可继续使用本地缓存,与ETag不同的是:此时响应头中不会再添加Last-Modified字段。

4.2.3. ETag和If-None-Match

二者的值都是服务器为每份资源分配的唯一标识字符串。

  1. 浏览器请求资源,服务器会在响应报文头中加入ETag字段。资源更新时,服务器端的ETag值也随之更新;
  2. 浏览器再次请求资源时,会在请求报文头中添加If-None-Match字段,它的值就是上次响应报文中的ETag的值;
  3. 服务器会比对ETag与If-None-Match的值是否一致,如果不一致,服务器则接受请求,返回更新后的资源;如果一致,表明资源未更新,则返回状态码为304的响应,可继续使用本地缓存,要注意的是,此时响应头会加上ETag字段,即使它没有变化。

二者对比 :

  • 精确度上:Etag要优于Last-Modified。
  1. 一些文件也许会周期性的更改,但是他的内容并不改变(仅仅改变的修改时间),这个时候我们并不希望客户端认为这个文件被修改了,而重新GET;
  2. 某些文件修改非常频繁,比如在秒以下的时间内进行修改,(比方说1s内修改了N次),If-Modified-Since能检查到的粒度是s级的,这种修改无法判断(或者说UNIX记录MTIME只能精确到秒);
  3. 某些服务器不能精确的得到文件的最后修改时间。
  • 优先级上:服务器校验优先考虑Etag。
  • 性能上:Etag要逊于Last-Modified,etag每次服务端生成都需要进行读写操作,而last-modified只需要读取操作

Last-Modified与ETag是可以一起使用的,服务器会优先验证ETag,一致的情况下,才会继续比对Last-Modified,最后才决定是否返回304。

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

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

6. 材料来源

  1. 一文读懂浏览器缓存
  2. 浏览器缓存看这一篇就够了
  3. 强缓存VS弱缓存
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值