「福利」 ✿✿ ヽ(°▽°)ノ ✿:文章最后有抽奖,转转纪念 T 恤一件或转转随机手办一个,走过路过不要错过哦
说起缓存,每个前端开发者都不会陌生。它是很常见的前端性能优化手段之一,无论在节省带宽、提高加载和渲染速度、减少网络阻塞,以及提高用户体验上,都发挥着很重要的作用。
页面的加载,可能会经历如上图所示的缓存过程。之所以会说可能,是因为有些缓存在一次请求中,不会经历。比如:如果请求命中了强缓存,那浏览器就直接返回结果了,不会进入协商缓存流程。下面我们会详细讲述下这些缓存的作用以及区别。
通常,我们在访问一个网站时,会先在浏览器地址栏中输入一串URL,这个URL的格式大概是这个样子的:协议://域名或IP地址:端口/路径?参数
。从URL中,我们可以看到域名
和IP地址
都可以帮我们定位到指定的服务主机上。IP地址
就是每一台物理机的唯一逻辑地址,可以很快找到对应主机,但是域名
就不同了,它和IP地址
是映射关系,它可以对应一个或多个IP地址
。那我们想要通过域名
查找到对应的服务器,就需要先找到它映射的IP地址
是哪个,再跟进这个IP地址
找到服务器。
域名
查找IP地址
的过程会对网络请求带来一定的损耗,所以浏览器在第一次获取到IP地址
后,会将其缓存起来。下次相同域名再次发起请求时,浏览器会先查找本地缓存,如果缓存有效,则会直接返回该IP地址
,否则会继续开始寻址之旅。
本着操作系统先读内存,再读硬盘的常理,浏览器会先从memory cache
中读取缓存,再去disk cache
中读取。由于memory cache
是短期存储,在浏览器tab关闭后,缓存便会失效。当数据量过大,即使tab不关闭,缓存依然会失效。
那哪些资源会存入memory cache
中呢?答:几乎所有资源。
看上面这张图的资源加载,全部通过preload
的方式加载资源,在第一次加载时,全部存储到了disk cache
中,如下图:
而在我刷新页面后(f5刷新),script
资源会存储到了memory cache
中,而stylesheet
依然存储在disk cache
中。
另外,prefetch
加载的资源,通常也会放入disk cache
。
硬盘缓存又叫HTTP缓存,它也是浏览器缓存中最重要的内容。
disk cache是永久缓存,根据HTTP协议头的缓存相关字段来判断缓存是否有效。它又分为两种:强缓存
和协商缓存
。HTTP缓存的详细过程如下图:
浏览器发起请求时,首先检测有没有缓存,若没有缓存,直接向服务端发起请求,若有,则会遵循HTTP缓存规则,在命中强缓存或协商缓存时,会将缓存结果返回,不然则从服务端获取数据。
对于强缓存,控制它的字段分别是:Expires
和Cache-Control
,其中Cache-Control
优先级比Expires
高。
Expires
是HTTP1.0
控制网页缓存的字段,其值为服务器返回该请求结果缓存的到期时间,形如:Mon, 23 Nov 2020 08:39:58 GMT
,即再次发起该请求时,如果客户端的时间小于Expires
的值时,直接使用缓存结果。
Expires
控制缓存的原理是使用客户端的时间与服务端返回的时间做对比,那么如果客户端与服务端的时间因为某些原因(例如时区不同;客户端和服务端有一方的时间不准确)发生误差,那么强制缓存则会直接失效,这样的话强制缓存的存在则毫无意义。
基于上述Expires
的缺陷,在HTTP1.1
中,用Cache-Control
替代了Expires
。当然,为了兼容HTTP1.0
和HTTP1.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
字段,将资源最后一次修改的时间告知客户端Last-Modified
和资源内容一起缓存起来Last-Modified
的值写入到请求头的If-Modified-Since
字段。If-Modified-Since
的值与Last-Modified
字段进行对比。如果相等,则表示未修改,响应304,不会返回任何内容,告知客户端可以使用缓存;反之,则表示修改了,响应200,并返回数据。Last-Modified
缓存起来。如果资源在1s内有多次修改的话,Last-Modified
是监听不到的,因为它的缓存时间是以s为过期时间单位的。对于这种情况,HTTP1.1
引入了以hash形式记录资源内容是否修改的ETag
来更准确的判断是否命中缓存。
ETag
的验证方法与Last-Modified
是一致的,只是ETag
是以hash生成的特殊标识。服务端会将浏览器请求头中的If-None-Match
与ETag
进行比较,若相等,则命中缓存,返回304;否则返回200和最新的资源内容。
ETag
的优先级是高于Last-Modified
的,为了兼容不同版本的协议,通常项目中,都会把两者都设置。
CDN作为一种服务端缓存方案,在我们平时的工作中,并不陌生。CDN旨在解决的最重要的问题就是网络延迟,CDN服务商会将源站的资源缓存到遍布全国的高性能加速节点上,当用户访问相应的业务资源时,用户会被调度至最接近的节点最近的节点IP返回给用户,在web性能优化中,它主要起到了,缓解源站压力,优化不同用户的访问速度与体验的作用。
前面我们了解到,每次的资源请求发起时,浏览器都会检测本地是否有缓存并且未过期,如果是,则直接使用缓存,否则则会向服务端发起请求。如果此时在浏览器和服务器之间增加一层CDN服务,整个访问过程会是什么样的呢?
如上图所示,客户端浏览器先检查是否有本地缓存是否过期,如果过期,则向CDN边缘节点发起请求,CDN边缘节点会检测用户请求数据的缓存是否过期,如果没有过期,则直接响应用户请求,此时一个完成http请求结束;如果数据已经过期,那么CDN还需要向源站发出回源请求(back to the source request),来拉取最新的数据。
可以看出,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 恤一件或转转随机手办一个,可任选其一,大家快转发起来吧~
或