前端隐秘角落 - 缓存知多少

「福利」 ✿✿ ヽ(°▽°)ノ ✿:文章最后有抽奖,转转纪念 T 恤一件或转转随机手办一个,走过路过不要错过哦

说起缓存,每个前端开发者都不会陌生。它是很常见的前端性能优化手段之一,无论在节省带宽、提高加载和渲染速度、减少网络阻塞,以及提高用户体验上,都发挥着很重要的作用。

缓存过程

页面的加载,可能会经历如上图所示的缓存过程。之所以会说可能,是因为有些缓存在一次请求中,不会经历。比如:如果请求命中了强缓存,那浏览器就直接返回结果了,不会进入协商缓存流程。下面我们会详细讲述下这些缓存的作用以及区别。

DNS缓存

通常,我们在访问一个网站时,会先在浏览器地址栏中输入一串URL,这个URL的格式大概是这个样子的:协议://域名或IP地址:端口/路径?参数。从URL中,我们可以看到域名IP地址都可以帮我们定位到指定的服务主机上。IP地址就是每一台物理机的唯一逻辑地址,可以很快找到对应主机,但是域名就不同了,它和IP地址是映射关系,它可以对应一个或多个IP地址。那我们想要通过域名查找到对应的服务器,就需要先找到它映射的IP地址是哪个,再跟进这个IP地址找到服务器。

域名查找IP地址的过程会对网络请求带来一定的损耗,所以浏览器在第一次获取到IP地址后,会将其缓存起来。下次相同域名再次发起请求时,浏览器会先查找本地缓存,如果缓存有效,则会直接返回该IP地址,否则会继续开始寻址之旅。

memory cache

本着操作系统先读内存,再读硬盘的常理,浏览器会先从memory cache中读取缓存,再去disk cache中读取。由于memory cache是短期存储,在浏览器tab关闭后,缓存便会失效。当数据量过大,即使tab不关闭,缓存依然会失效。

那哪些资源会存入memory cache中呢?答:几乎所有资源。

看上面这张图的资源加载,全部通过preload的方式加载资源,在第一次加载时,全部存储到了disk cache中,如下图:

而在我刷新页面后(f5刷新),script资源会存储到了memory cache中,而stylesheet依然存储在disk cache中。

另外,prefetch加载的资源,通常也会放入disk cache

disk cache

硬盘缓存又叫HTTP缓存,它也是浏览器缓存中最重要的内容。

disk cache是永久缓存,根据HTTP协议头的缓存相关字段来判断缓存是否有效。它又分为两种:强缓存协商缓存。HTTP缓存的详细过程如下图:

浏览器发起请求时,首先检测有没有缓存,若没有缓存,直接向服务端发起请求,若有,则会遵循HTTP缓存规则,在命中强缓存或协商缓存时,会将缓存结果返回,不然则从服务端获取数据。

强缓存

对于强缓存,控制它的字段分别是:ExpiresCache-Control,其中Cache-Control优先级比Expires高。

  • Expires

ExpiresHTTP1.0控制网页缓存的字段,其值为服务器返回该请求结果缓存的到期时间,形如:Mon, 23 Nov 2020 08:39:58 GMT,即再次发起该请求时,如果客户端的时间小于Expires的值时,直接使用缓存结果。

Expires控制缓存的原理是使用客户端的时间与服务端返回的时间做对比,那么如果客户端与服务端的时间因为某些原因(例如时区不同;客户端和服务端有一方的时间不准确)发生误差,那么强制缓存则会直接失效,这样的话强制缓存的存在则毫无意义。

  • Cache-Control

基于上述Expires的缺陷,在HTTP1.1中,用Cache-Control替代了Expires。当然,为了兼容HTTP1.0HTTP1.1,在实际应用中,这两个值都会设置。Cache-Control的指令分为:缓存请求指令缓存响应指令,值分别如下:

  • 缓存请求指令

Cache-Control含义
max-age设置缓存存储的最大周期,超过这个时间缓存被认为过期(单位秒)。与Expires相反,时间是相对于请求的时间。
max-stale表明客户端愿意接收一个已经过期的资源。可以设置一个可选的秒数,表示响应不能已经过时超过该给定的时间。
min-fresh表示客户端希望获取一个能在指定的秒数内保持其最新状态的响应
no-cache在发布缓存副本之前,强制要求缓存把请求提交给原始服务器进行验证(协商缓存验证)。
no-store缓存不应存储有关客户端请求或服务器响应的任何内容,即不使用任何缓存。
no-transform不得对资源进行转换或转变。
only-if-cached表明客户端只接受已缓存的响应,并且不要向原始服务器检查是否有更新的拷贝。

  • 缓存响应指令

Cache-Control含义
no-cache在发布缓存副本之前,强制要求缓存把请求提交给原始服务器进行验证(协商缓存验证)。
no-store缓存不应存储有关客户端请求或服务器响应的任何内容,即不使用任何缓存。
no-transform不得对资源进行转换或转变。
public表明响应可以被任何对象(包括:发送请求的客户端,代理服务器,等等)缓存,即使是通常不可缓存的内容。
private表明响应只能被单个用户缓存,不能作为共享缓存(即代理服务器不能缓存它)。私有缓存可以缓存响应内容,比如:对应用户的本地浏览器。
must-revalidate一旦资源过期(比如已经超过max-age),在成功向原始服务器验证之前,缓存不能用该资源响应后续请求。
proxy-revalidate与must-revalidate作用相同,但它仅适用于共享缓存(例如代理),并被私有缓存忽略。
max-age设置缓存存储的最大周期,超过这个时间缓存被认为过期(单位秒)。与Expires相反,时间是相对于请求的时间。
s-maxage覆盖max-age或者Expires头,但是仅适用于共享缓存(比如各个代理),私有缓存会忽略它。

协商缓存

从前面介绍的内容,我们知道,浏览器在发起请求时,会先判断是否命中强缓存,如果没有命中,则会去验证协商缓存是否被命中。协商缓存有两对字段,他们的验证方法分别如下:

  • Last-Modified & If-Modified-Since

  1. 服务器通过Last-Modified字段,将资源最后一次修改的时间告知客户端

  2. 浏览器将Last-Modified和资源内容一起缓存起来

  3. 在浏览器下一次请求相同资源时,会从自己的缓存中找出“不确定是否过期的”缓存。因此在请求头中将上次的Last-Modified的值写入到请求头的If-Modified-Since字段。

  4. 此时,服务器会将If-Modified-Since的值与Last-Modified字段进行对比。如果相等,则表示未修改,响应304,不会返回任何内容,告知客户端可以使用缓存;反之,则表示修改了,响应200,并返回数据。

  5. 浏览器会将新的内容和Last-Modified缓存起来。

  • ETag & If-None-Match

如果资源在1s内有多次修改的话,Last-Modified是监听不到的,因为它的缓存时间是以s为过期时间单位的。对于这种情况,HTTP1.1引入了以hash形式记录资源内容是否修改的ETag来更准确的判断是否命中缓存。

ETag的验证方法与Last-Modified是一致的,只是ETag是以hash生成的特殊标识。服务端会将浏览器请求头中的If-None-MatchETag进行比较,若相等,则命中缓存,返回304;否则返回200和最新的资源内容。

ETag的优先级是高于Last-Modified的,为了兼容不同版本的协议,通常项目中,都会把两者都设置。

CDN缓存

CDN作为一种服务端缓存方案,在我们平时的工作中,并不陌生。CDN旨在解决的最重要的问题就是网络延迟,CDN服务商会将源站的资源缓存到遍布全国的高性能加速节点上,当用户访问相应的业务资源时,用户会被调度至最接近的节点最近的节点IP返回给用户,在web性能优化中,它主要起到了,缓解源站压力,优化不同用户的访问速度与体验的作用。

前面我们了解到,每次的资源请求发起时,浏览器都会检测本地是否有缓存并且未过期,如果是,则直接使用缓存,否则则会向服务端发起请求。如果此时在浏览器和服务器之间增加一层CDN服务,整个访问过程会是什么样的呢?

如上图所示,客户端浏览器先检查是否有本地缓存是否过期,如果过期,则向CDN边缘节点发起请求,CDN边缘节点会检测用户请求数据的缓存是否过期,如果没有过期,则直接响应用户请求,此时一个完成http请求结束;如果数据已经过期,那么CDN还需要向源站发出回源请求(back to the source request),来拉取最新的数据。

可以看出,CDN的优点很明显了:

  1. CDN节点解决了跨运营商和跨地域访问的问题,访问延时大大降低;

  2. 大部分请求在CDN边缘节点完成,CDN起到了分流作用,减轻了源站的负载。

总结

以上讲述了普通业务中,一次请求经历的直接相关缓存内容。还有其他的缓存,比如Service Worker,Nginx缓存等。有兴趣的同学可以自己去了解下,有很多挺不错的分享文章。

参考文章

[1].一文读懂前端缓存 - https://juejin.im/post/6844903747357769742?utm_source=gold_browser_extension

[2].Cache Control MDN - https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Cache-Control

[3].A Tale of Four Cache - https://calendar.perfplanet.com/2016/a-tale-of-four-caches/

[4].浏览器缓存机制剖析- http://louiszhai.github.io/2017/04/07/http-cache/

[5].一文读懂前端缓存(超详细) - https://www.jianshu.com/p/227cee9c8d15?from=singlemessage


文末福利

转发本文并留下评论,我们将抽取第 10 名留言者(依据公众号后台排序),转转纪念 T 恤一件或转转随机手办一个,可任选其一,大家快转发起来吧~

 或

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值