HTTP缓存
缓存机制
浏览器在发送请求前,会根据HTTP响应头部信息进行强缓存判定是否从缓存中直接获取资源。如果没有匹配上强缓存规则,则开始发送请求到服务器,进行协商缓存判定是否从缓存中获取资源,如果前两步都没有匹配成功,则开始从服务器获取资源。
强缓存
当浏览器向服务器发起请求时,服务器会将缓存规则放入HTTP响应报文的HTTP头中和请求结果一起返回给浏览器,控制强制缓存的字段分别是Expires
和Cache-Control
,其中Cache-Control
优先级比Expires
高
注:第一次请求,不存在缓存标识,会直接向服务器发送请求
Expires是HTTP1.0的产物,现如今已经基本放弃使用Expires(本文暂不讨论)
Cache-Control
用于控制网页缓存的字段,规则可以一个或者多个,依次进行判定,主要取值有:
- public:所有内容都会被缓存(客户端和代理服务器都可缓存)
- private (默认值) :所有内容只有客户端可以换成。 (对于前端而言,private和public基本一样)
- max-age=xxx:缓存内容将在xxx秒后过期
- no-cache:客户端缓存内容,但是否使用缓存需要经过协商缓存的验证来决定
- no-store:所有内容都不会被缓存,既不强缓存,也不协商缓存
- must-revalidate:客户端缓存过期前使用缓存,过期后则需要去服务器进行相对应的验证 (与no-cache类似,但更严格,强制意味更明显)
关于max-age=0、no-cache和must-revalid的区别
max-age=0 表示一个立即过期的响应(直接标记为陈旧状态)
no-cache 表示浏览器强制进行新鲜度验证(不管是否新鲜),待服务器确认新鲜度以后,再使用缓存
must-revalidate 只有在缓存过期之后,浏览器才会去服务器验证缓存的新鲜度
这样看来,似乎max-age=0、no-cache和must-revalid基本上是可以画等号了,但是要注意细微的差别
在执行must-revalidate时,若浏览器第二次去请求服务器来做新鲜度验证,结果服务器挂了,无法访问,那么缓存需要返回一个504 Gateway Timeout的错误
而如果是no-cache,当验证新鲜度时,服务器挂了,则会照样使用本地缓存显示给用户(有的总比没的好,当然有可能显示的就是旧的文档了)
结论:must-revalidate用在对事务要求比较严苛的情况下使用(比如支付)
缓存位置
主要有硬盘缓存from disk cache和内存
缓存from memory cache
两种
一般js文件和图片等文件解析后存放在内存缓存中;css文件则会存放在硬盘缓存中
浏览器读取缓存的顺序为memory –> disk
内存缓存from memory cache
的特点
- 快速读取
- 时效性:一旦进程关闭,该进程的内存会被清空
硬盘缓存from disk cache
的特点
- 写入硬盘文件
- 进行I/O操作
- 速度比内存缓存慢
协商缓存
协商缓存就是强缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程,主要分为两种情况:
- 协商缓存生效,返回304和Not Modified
- 协商缓存失效,返回200和请求结果
控制协商缓存的字段分别有:Last-Modified / If-Modified-Since
和Etag / If-None-Match
,其中Etag / If-None-Match
的优先级比Last-Modified / If-Modified-Since
高,同时存在则只有Etag / If-None-Match
生效。
Last-Modified / If-Modified-Since
Last-Modified是服务器响应请求时,返回改资源文件的最后修改时间
If-Modified-Since则是客户端再次请求服务器时,携带上次请求时返回的Last-Modified值到服务器进行比对,如果服务器上的资源最后修改时间与请求带回来的If-Modified-Since值不匹配,则重新返回资源,状态码为200;否则返回304,代表缓存文件可继续被使用。
缺点:
- 保存的时间是以秒为单位的,1秒内多次修改是无法捕捉到的
- 各机器读取到的时间不一致,就有出现误差的可能性
Etag / If-None-Match
Etag是服务器响应请求时,返回当前资源文件的一个唯一标识(由服务器生成),只要资源有变化,Etag就会重新生成。
客户端再次发送请求时,会将上一次服务器返回的Etag值放在If-None-Match里,如果服务器上改资源的Etag与客户端If-None-Match里带来的值不一致,则重新返回资源以及新的Etag,状态码为200;否则返回304,客户端使用缓存文件即可。
优缺点:
- 性能不如Last-Modified / If-Modified-Since
- 精度高于Last-Modified / If-Modified-Since