前端缓存主要是分为 HTTP缓存 和 浏览器缓存。
其中HTTP缓存是在HTTP请求传输时用到的缓存,主要在服务器代码上设置;而浏览器缓存则主要由前端开发在前端js上进行设置。
缓存可以说是性能优化中简单高效的一种优化方式了。一个优秀的缓存策略可以缩短网页请求资源的距离,减少延迟,并且由于缓存文件可以重复利用,还可以减少带宽,降低网络负荷。
缓存过程分析
浏览器第一次向服务器发起该请求后拿到请求结果,会根据 响应报文 中 HTTP头的缓存标识,决定是否缓存结果,是则将请求结果和缓存标识存入浏览器缓存中,
由上图我们可以知道:
浏览器每次发起请求,都会先在浏览器缓存中查找该请求的结果以及缓存标识
浏览器每次拿到返回的请求结果都会将该结果和缓存标识存入浏览器缓存中
强制缓存
强制缓存就是向浏览器缓存查找该请求结果,并根据该结果的缓存规则来决定是否使用该缓存结果的过程。
强制缓存的情况主要有三种,如下:
①不存在该缓存结果和缓存标识,强制缓存失效,则直接向服务器发起请求(跟第一次发起请求一致),如下图:
②存在该缓存结果和缓存标识,但该结果已失效,强制缓存失效,则使用协商缓存,如下图
③存在该缓存结果和缓存标识,且该结果尚未失效,强制缓存生效,直接返回该结果,如下图
那么强制缓存的缓存规则是什么?
Expires
Expires是HTTP/1.0控制网页缓存的字段,其值为服务器返回该请求结果缓存的到期时间,即再次发起该请求时,如果客户端的时间小于Expires的值时,直接使用缓存结果。
到了HTTP/1.1,Expire已经被Cache-Control替代,原因在于Expires控制缓存的原理是使用客户端的时间与服务端返回的时间做对比,那么如果客户端与服务端的时间因为某些原因(例如时区不同;客户端和服务端有一方的时间不准确)发生误差,那么强制缓存则会直接失效,这样的话强制缓存的存在则毫无意义。
Cache-Control
在HTTP/1.1中,Cache-Control是最重要的规则,主要用于控制网页缓存,主要取值为:
- public:所有内容都将被缓存(客户端和代理服务器都可缓存)
- private:所有内容只有客户端可以缓存,Cache-Control的默认取值
- no-cache:客户端缓存内容,但是是否使用缓存则需要经过协商缓存来验证决定
- no-store:所有内容都不会被缓存,即不使用强制缓存,也不使用协商缓存
- max-age=xxx (xxx is numeric):缓存内容将在xxx秒后失效
接下来,我们直接看一个例子,如下:
由上面的例子我们可以知道:
①HTTP响应报文中expires的时间值,是一个绝对值
②HTTP响应报文中Cache-Control为max-age=600,是相对值
由于Cache-Control的优先级比expires高,那么直接根据Cache-Control的值进行缓存,意思就是说在600秒内再次发起该请求,则会直接使用缓存结果,强制缓存生效。
注:在无法确定客户端的时间是否与服务端的时间同步的情况下,Cache-Control相比于expires是更好的选择,所以同时存在时,只有Cache-Control生效。
了解强制缓存的过程后,我们进行下一步思考:浏览器的缓存存放在哪里,如何在浏览器中判断强制缓存是否生效?
这里我们以博客的请求为例,状态码为灰色的请求则代表使用了强制缓存,请求对应的Size值则代表该缓存存放的位置,分别为 from memory cache 和 from disk cache。
么from memory cache 和 from disk cache又分别代表的是什么呢?什么时候会使用from disk cache,什么时候会使用from memory cache呢?
from memory cache代表使用内存中的缓存,
from disk cache则代表使用的是硬盘中的缓存,
浏览器读取缓存的顺序为memory –> disk –> 服务器请求。
那么接下来我们一起详细分析一下缓存读取问题,这里仍让以我的博客为例进行分析:
首次访问页面

关闭博客的标签页,重新打开页面

刷新页面

内存缓存(from memory cache):内存缓存具有两个特点,分别是速度快和时间限制。
硬盘缓存(from disk cache):硬盘缓存则是直接将缓存写入硬盘文件中,读取缓存需要对该缓存存放的硬盘文件进行I/O操作,然后重新解析该缓存内容,读取复杂,速度比内存缓存慢。
协商缓存
协商缓存就是强制缓存失效后(这里只是失效,不是不存在了),浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程,主要有以下两种情况:
①协商缓存生效,返回304,如下

②协商缓存失效,返回200和请求结果结果,如下

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

Etag / If-None-Match
Etag是服务器响应请求时,返回当前资源文件的一个唯一标识(由服务器生成),如下。


总结
