一、引

就是学,为了面试,所有见过的面试题“姿势”都要学。

二、介绍

前端的缓存大家都知道是有俩种:强缓存和协商缓存,下面就稍微分开介绍一下。

2.1强缓存

从名字上就可以看出来,强(制)缓存,意思就是在前端请求服务端的时候先去请求本地缓存,如果存在则强制性返回本地缓存的内容,而无需请求服务端。这样的话好处就达到了,在过期时间内,服务端的请求压力就被减小了,但是问题也显而易见,就是如果在过期时间内服务端的内容改变了,用户得到的数据还是本地缓存中没有更新的数据,失去了数据的时效性,如果在缓存时间内服务端接口被后端服务关闭了,前端也是无任何反应的。所有是有利也有弊。

2.2协商缓存

也从名字上看,这次前端请求的时候会去先“协商”,这个协商是和谁呢?是和服务器!每次请求本地缓存后,都问下服务器是否本地的缓存和服务端的一样,一样则缓存有效,反之就失效。非常棒!解决了前后端数据不一致的问题,但是每次请求都要走到服务端,那么缓存的意义就不明显了,根本就没减轻服务器端的压力呀…

三、原理

3.1 强缓存

强缓存的设置是通过HHTP请求的头部中 Cache-ControlExpries 字段来设置的。

Cache-Control: max-age :
max-age 定义了文档的最大使用时间,从第一次生成文档到文档无法使用为止,最大的合法生存时间(秒)。

Expires :
指定一个绝对的过期日期,如果过期日期已经过了,就说明文档不在新鲜了,不过由于我们可以去更改前端的时间,因此可以更改缓存命中的结果。因此优先级低于 Cache-Control

Cache-Control 有很多属性,不同的属性代表的意义也不同。
private:客户端可以缓存。
public:客户端和代理服务器都可以缓存。
max-age=t:缓存内容将在 t 秒后失效。
no-cache:需要使用协商缓存来验证缓存数据。
no-store:所有内容都不会缓存。

3.2协商缓存

协商缓存过期并不意味着数据已经过期,而是意味着又需要去检查数据是否一致了。如果一致,缓存会得到一份新的数据副本和其更新时间和过期时间等一系列信息。控制协商缓存的字段分别有:Last-Modified / If-Modified-SinceEtag / If-None-Match,其中Etag / If-None-Match的优先级比 Last-Modified / If-Modified-Since高。

Last-Modified 是服务器响应请求时,返回该资源文件在服务器最后被修改的时间。

If-Modified-Since 则是前端再次发起该请求时,携带上次请求返回的 Last-Modified 值,通过此字段值告诉服务端该资源上次请求返回的最后被修改时间。服务端收到该请求,发现请求头含有 If-Modified-Since 字段,则会根据 If-Modified-Since 的字段值与该数据在服务端的最后被修改时间做对比,若服务端的数据最后被修改时间大于 If-Modified-Since 的字段值,则重新返回数据,状态码为 200 ;否则则返回 304 ,代表数据无更新,可继续使用缓存。

Etag 是服务器响应请求时,返回当前资源文件的一个唯一标识。

If-None-Match 是前端再次发起该请求时,携带上次请求返回的唯一标识 Etag 值,通过此字段值告诉服务端该资源上次请求返回的唯一标识值。服务端收到该请求后,发现该请求头中含有 If-None-Match ,则会根据 If-None-Match 的字段值与该数据在服务器的 Etag 值做对比,一致则返回 304 ,代表数据无更新,继续使用缓存;不一致则重新返回数据,状态码为 200

四、总结

强制缓存优先于协商缓存进行,若强制缓存 (Expires和Cache-Control) 生效则直接使用缓存,若不生效则进行协商缓存 (Last-Modified / If-Modified-Since和Etag / If-None-Match) ,协商缓存由服务端决定是否使用缓存,若协商缓存失效,那么代表该请求的缓存失效,重新获取请求结果,再存入浏览器缓存中;生效则返回 304 继续使用缓存。