欢迎光临散文网 会员登陆 & 注册

前端面试八股文之浏览器缓存

2021-06-03 22:37 作者:坏蛋Dan丶  | 我要投稿

这一题应该也是很容易碰到的。

首先要说明下浏览器缓存只是web缓存体系中的一小个

图:

web缓存体系


然后我们得知道缓存的是什么东西:HTML文档、图片、CSS和JS等文件。对于一些不经常变的内容,浏览器会将他们保存在本地的文件中,下次访问相同网站的时候,直接加载这些资源,加速访问。

这些被浏览器保存的文件就被称为缓存(不是指Cookie或者Localstorage)。


面试官可能会问:为什么需要浏览器缓存?

答:

  1. 尽量拿浏览器本地缓存的数据,降低带宽消耗。

  2. 不需要每次都从服务器拿数据,降低服务器压力。

  3. 减少等待时间,提升用户体验感。

问完作用后会开始问你有哪些缓存方法呢?

答:

  1. 强缓存。

  2. 协商缓存。

然后面试官会让你分别解释下或者说下浏览器缓存机制等。

在这之前我们得知道能否缓存以及缓存多久都是由服务器来定义的,通过设置响应头的几个关键属性。

我们将会接触到的几个header的属性:

  1. Cache-Control

  2. Expires(存在问题,http1.0遗物)

  3. Last-Modified

  4. Etag

  5. If-None-Match

  6. If-Modified-Since


1. 强缓存

由服务器设置两个属性:Expires以及Cache-Control。

服务器在返回数据时会发送Expires以及Cache-Control来通知浏览器我是要缓存。

那么浏览器在下次请求时会先判断是否符合Expires以及Cache-Control,如果满足则直接从本地获取数据。

其中Expires是通过绝对时间来判断的,当浏览器判断时间在Expires设置的时间之前,就满足缓存条件,直接从本地获取数据。但这也存在弊端,当用户修改客户端时间时缓存可能就会失效。因此后面多用Cache-Control来配合Expires设置缓存。

Cache-Control具有以下属性:

max-age=xxx:缓存的内容将在 xxx 秒后失效,这个时间是个时间间隔相对时间。
public:所有内容都将被缓存(客户端和代理服务器都可缓存)
private:内容只缓存到私有缓存中(仅客户端可以缓存,代理服务器不可缓存)
no-cache:必须先与服务器确认返回的响应是否被更改,然后才能使用该响应来满足后续对同一个网址的请求。因此,如果存在合适的验证令牌(ETag),no-cache 会发起往返通信来验证缓存的响应,如果资源未被更改,可以避免下载
no-store:所有内容都不会被缓存或 Internet 临时文件中
must-revalidation/proxy-revalidation:如果缓存的内容失效,请求必须发送到服务器/代理以进行重新验证

其中max-age是设置的一段时间间隔,不会涉及到日期,因此不存在Expires中的问题。

Cache-Control优先级高于Expires。

响应头中的Cache-Control以及Expires


2. 协商缓存

既然有了强缓存,为什么还要协商缓存呢?

答:强缓存所设置的时间不能是太长,太长了会发生数据更新了但依旧在展示旧数据的问题。如果强缓存失效了,那么每次请求都一定会返回数据,不管数据是否发生了改变,这会造成不必要的服务器压力。

什么情况下会走协商缓存呢?

当然是在强缓存不满足的情况。

曾经被问到一个问题,为什么有协商缓存一定会有强缓存呢?

答:如果没有强缓存只有协商缓存,那么就不会有数据缓存在浏览器中,并且每次请求都会发送两次造成严重浪费。

当浏览器发现超出Cache-Control的时间间隔时会向服务器发送请求,此时的请求只是告诉服务器强缓存失效了,询问服务器是否需要更新资源。

此时是否需要更新看服务器那边的情况,如果需要更新,浏览器会再发送一次请求告诉服务器他所需要的数据,服务器会发送数据给浏览器,然后再次缓存数据。

如果服务器通知不需要更新(返回304Not Modified),那么浏览器会直接从本地拿缓存。

那么通过什么来让服务器判断是否需要更新数据呢?

答:服务器在发送数据时会在响应头中添加Last-Modified以及Etag,浏览器在协商缓存过程中会在请求头中添加If-Modified-Since以及If-None-Match传给服务器,让服务器判断是否需要更新。

其中

Last-Modified为最后一次更新的时间,时间精度为秒。

Last-Modified-Since就是浏览器缓存数据时的Last-Modified。

Etag为一段字符串,每个文件都有属于自己的字符串,(分布式系统中会导致每个文件都有不同的Etag让缓存失效)。

If-None-Match为缓存时的Etag字符串。

Last-Modified和If-Modified-Since两个是HTTP1.0的属性

Etag和If-None-Match是HTTP1.1中引入的新属性

Etag优先级高于Last-Modified

其中面试官可能会问你为什么要在HTTP1.1引入Etag和If-None-Match?

答:前面说过Last-Modified时间精度为秒,那么就可能存在服务器文件修改了(在更小的时间间隔内改变),但是时间却没变的问题。而Etag使用的是唯一标识符,一段字符串。当文件改动时会立即更新Etag,因此不会有上述问题。

3. 浏览器缓存机制


1)浏览器在加载资源时,先根据这个资源的一些http header判断它是否命中强缓存,强缓存如果命中,浏览器直接从自己的缓存中读取资源,不会发请求到服务器。比如:某个css文件,如果浏览器在加载它所在的网页时,这个css文件的缓存配置命中了强缓存,浏览器就直接从缓存中加载这个css,连请求都不会发送到网页所在服务器;

2)当强缓存没有命中的时候,浏览器一定会发送一个请求到服务器,通过服务器端依据资源的另外一些http header验证这个资源是否命中协商缓存,如果协商缓存命中,服务器会将这个请求返回,但是不会返回这个资源的数据,而是告诉客户端可以直接从缓存中加载这个资源,于是浏览器就又会从自己的缓存中去加载这个资源;

3)强缓存与协商缓存的共同点是:如果命中,都是从客户端缓存中加载资源,而不是从服务器加载资源数据;区别是:强缓存不发请求到服务器,协商缓存会发请求到服务器

4)当协商缓存也没有命中的时候,浏览器直接从服务器加载资源数据。

图:

浏览器缓存流程图


其实前端可以通过设置meta标签控制缓存,但兼容性不好

// 必须是 GMT 格式 

<meta http-equiv="expires" content="Fri,12 Jan 2001 15:15:15 GMT">

// 是否设置缓存 

<meta http-equiv="pragma" content="no-cache">


不足之处麻烦指出,谢谢!


整理自:

https://www.jianshu.com/p/7531c98a6933

https://www.cnblogs.com/keeperdog/p/11498918.html

https://segmentfault.com/a/1190000017553812

侵删。

前端面试八股文之浏览器缓存的评论 (共 条)

分享到微博请遵守国家法律