面试题锦(3) | 说说浏览器的缓存策略
前言
「面试题锦」的初衷是为了记录我的前端学习轨迹,在整理记录的过程中对我而言也是一种,欢迎你跟着我每周重点攻克一个前端面试重难点。在进阶的路上,共勉!
1. 说说浏览器的缓存策略
浏览器缓存位置和优先级
-
Service Worker -
Memory Cache(内存缓存) -
Disk Cache(硬盘缓存) -
Push Cache(推送缓存) -
以上缓存都没命中就会进行网络请求
不同缓存位置的差别
「Service Worker」:和Web Worker类似,是独立的线程,我们可以在这个线程中缓存文件,在主线程需要的时候读取这里的文件,Service Worker使我们可以自由选择缓存哪些文件以及文件的匹配、读取规则,并且缓存是持续性的。
「Memory Cache」:即内存缓存,内存缓存不是持续性的,缓存会随着进程释放而释放。
「Disk Cache」:即硬盘缓存,相较于内存缓存,硬盘缓存的持续性和容量更优,它会根据HTTP header的字段判断哪些资源需要缓存。
「Push Cache」:即推送缓存,是HTTP/2的内容,目前应用较少。
浏览器缓存策略
缓存分为「强缓存」和「协商缓存」。设置为强缓存,之后的请求都不访问服务器,直接从缓存中找,默认返回状态码是200,且默认强制缓存不缓存首页资源;设置为协商缓存后,每次请求仍然要向服务器询问缓存是否过期,返回状态码是304。「两种缓存机制同时存在时,强缓存高于协商缓存。」
❝强缓存(不要向服务器询问的缓存)
❞
-
「设置Expires(HTTP1.0)」:即过期时间,表示缓存会在这个时间后失效,这个过期日期是绝对日期,如果修改了本地日期,或者本地日期与服务器日期不一致,那么将导致缓存过期时间错误。
res.setHeader('Expires', new Date(Date.now()+3600*1000).toGMTString());
-
「设置Cache-Control(HTTP/1.1)」:HTTP/1.1新增字段,Cache-Control可以通过
max-age
字段来设置过期时间,除此之外Cache-Control
还有很多属性,不同的属性代表不同的含义: -
private:客户端可以缓存 -
public:客户端和代理服务器都可以缓存 -
max-age=t:缓存内容将在t秒后失效 -
「no-cache」: 「默认值」,需要使用协商缓存来验证缓存数据,意思不是不缓存,而是 「请求且缓存」。 -
「no-store」:真正不缓存,意思是 「请求但不缓存」。
res.setHeader('Cache-Control', 'max-age=3600');
res.setHeader('Cache-Control', 'no-cache');
请注意no-cache指令很多人误以为是不缓存,这是不准确的,no-cache的意思是可以缓存,但每次都会向服务器验证缓存是否可用。no-store才是不缓存。当在首部字段 Cache-Control 有指定 max-age 指令时,**Cache-Control的 max-age 优先级高于 Expires。**命中强缓存的表现形式:Firefox浏览器表现为一个灰色的200状态码。Chrome浏览器状态码表现为200 (from disk cache)或是200 OK (from memory cache)。
❝协商缓存(当缓存已经过期时,使用协商缓存)
❞
-
「Last-Modified & if-Modified-Since(HTTP/1.0)」:对比修改时间
「缺点」:内容没变时间变化了,也会重新读取内容;时间不精准,时间的最小粒度只到
s
,s
以内的改动无法检测到。 -
「Last-Modified」:即最后修改时间,浏览器第一次请求资源时,服务器会在响应头上加上
Last-Modified
,告诉浏览器资源的最后修改时间。 -
「if-Modified-Since」:当浏览器再次请求该资源时,浏览器会在请求头中带上
If-Modified-Since
字段,字段的值就是之前服务器返回的最后修改时间,服务器对比这两个时间,若相同,浏览器直接从缓存中获取数据信息。返回状态码304;若不同则返回新资源,返回状态码200,并更新Last-Modified
。 -
「Etag & If-None-Match」:对比唯一标识,这种比较方式比较精准,但是默认不会根据完整内容生成唯一标识;为了保证精确度,我们一般会用内容的一部分+文件的总大小来生成唯一标识。「Etag 的优先级高于 Last-Modified」。
「缺点」:文件内容越大,越耗性能
-
「Etag(HTTP/1.1)」:服务器响应请求时,通过此字段告诉浏览器当前资源在服务器生成的唯一标识(生成规则由服务器决定)。
-
「If-None-Match」:当浏览器再次请求该资源时,浏览器会在请求头中带上
If-None-Match
字段,字段的值就是在缓存中获取的唯一标识。服务器对比两次请求的标识,若相同说明资源没有被修改,浏览器直接从缓存中获取数据信息。返回状态码304;若不同则说明资源被改动过,响应整个资源内容,返回状态码200。
缓存场景
对于大部分的场景都可以使用强缓存配合协商缓存解决,但是在一些特殊的地方可能需要选择特殊的缓存策略
-
对于某些不需要缓存的资源,可以使用 Cache-control: no-store ,表示该资源不需要缓存 -
对于频繁变动的资源,可以使用 Cache-Control: no-cache 并配合 ETag 使用,表示该资源已被缓存,但是每次都会发送请求询问资源是否更新 -
对于代码文件来说,通常使用 Cache-Control: max-age=31536000 并配合策略缓存使用,然后对文件进行指纹处理,一旦文件名变动就会立刻下载新的文件
2. HTTP/1.0和HTTP/1.1有什么区别
-
「持久连接」:HTTP/1.1 支持持久连接和请求的流水线,在一个TCP连接上可以传送多个HTTP请求,只要浏览器或者服务器没有明确断开连接,那么该 TCP 连接会一直保持,这样的好处是避免了因为多次建立TCP连接的时间消耗,减少了服务器额外的负担,并提升整体 HTTP 的请求时长。目前浏览器中对于同一个域名,「默认允许同时建立 6 个 TCP 持久连接。」
-
-
「缓存处理」:HTTP/1.1 引入Entity tag,If-Unmodified-Since, If-Match, If-None-Match等新的请求头来控制缓存。
-
「对动态生成的内容提供了完美支持」:随着服务器端的技术发展,很多页面的内容都是动态生成的,因此在传输数据之前并不知道最终的数据大小,这就导致了浏览器不知道何时会接收完所有的文件数据。HTTP/1.1 通过引入 Chunk transfer 机制来解决这个问题,服务器会将数据分割成若干个任意大小的数据块,每个数据块发送时会附上上个数据块的长度,最后使用一个零长度的块作为发送数据完成的标志。这样就提供了对动态内容的支持。
-
「客户端 Cookie、安全机制」:HTTP1.1 引入了 cookie 安全机制。
-
「带宽优化及网络连接的使用」:HTTP1.1 则在请求头引入了 range 头域,支持断点续传功能。
3. 介绍一下HTTP/2.0新特性
-
「多路复用」:一个域名都通过一个 TCP 连接并发地完成。主要是为了规避 TCP 的慢启动,TCP 连接之间的竞争问题和队头阻塞问题。
-
「服务端推送」:服务端能够主动把资源推送给客户端。
-
「可以设置请求的优先级」:在发送请求时,标上该请求的优先级,这样服务器接收到请求之后,会优先处理优先级高的请求。
-
「新的二进制格式」:HTTP/2采用二进制格式传输数据,相比于HTTP/1.1的文本格式,二进制格式具有更好的解析性和拓展性。
-
「头部压缩」:HTTP/2压缩消息头,减少了传输数据的大小。
4. 说说HTTP/3.0
尽管HTTP/2解决了很多1.1的问题,但HTTP/2仍然存在一些缺陷,这些缺陷并不是来自于HTTP/2协议本身,而是来源于底层的TCP协议,我们知道TCP链接是可靠的连接,如果出现了丢包,那么整个连接都要等待重传,HTTP/1.1可以同时使用6个TCP连接,一个阻塞另外五个还能工作,但HTTP/2只有一个TCP连接,阻塞的问题便被放大了。
由于TCP协议已经被广泛使用,我们很难直接修改TCP协议,基于此,HTTP/3选择了一个折衷的方法——UDP协议,HTTP/2在UDP的基础上实现多路复用、0-RTT、TLS加密、流量控制、丢包重传等功能。
非常感谢您看完了这篇文章,如果您觉得这篇内容对您有些许作用,那就请长按二维码关注我吧!
喜欢就关注我吧!