浏览器 缓存
浏览器缓存是啥?
首先,浏览器缓存是指浏览器会把用户访问页面时,从服务器请求回来的东西保存在用户的本地,这些保存在本地的东西就是缓存。当用户再次访问刚才页面时, 浏览器不会真的再次去访问页面所对应该的服务器,而从原来保存在本地的内容中返回用户页面里需要的东西。
注意一下, 这个请求过程是指缓存存在并且有效的时候
浏览器缓存有啥作用?
从上面的请求过程发现,缓存最明显的作用就是减少了页面请求服务器的次数,浏览器性能得到优化,其它的作用还有:
- 缩短网页请求资源的时间
- 减少延迟
- 减少带宽
- 降低网络负荷
- 等。。。
但是,好是好,浏览器缓存有时候也会带来问题:
有时候就会碰到服务器的资源文件更新了,但是我们页面访问的时候,浏览器还是从本地缓存拿的内容,这个时候,就不是我们想要的结果了。解决方法就是把浏览器的缓存清掉,主要是刷新,强制刷新,再不行就打开控制台,右击页面刷新图标,点清空缓存并硬性重新加载
浏览器缓存是怎样工作的?
先来看一个张浏览器发起一个 http 请求的图片
看完这个图片之后,很清楚的就明白了
浏览器每次发起请求,都会先在浏览器缓存中查找该请求的结果以及缓存标识
浏览器每次拿到返回结果的时候,都会将该结果和缓存标识存入浏览器缓存中
以上两点结论就是浏览器缓存机制的关键,它确保了每个请求的缓存存入与读取
浏览器缓存分为强缓存跟协商缓存
强缓存:不会向服务器重新发起 HTTP 请求,直接从缓存中读取资源
协商缓存: 强缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程
强缓存
强缓存:不会向服务器发送请求,直接从缓存中读取资源,强缓存分为下面三种情况:
- 不存在该缓存结果和缓存标识,强制缓存失效,则直接向服务器发起请求
- 存在该缓存结果和缓存标识,但该结果已失效,强制缓存失效,则使用协商缓存
- 存在该缓存结果和缓存标识,且该结果尚未失效,强制缓存生效,直接返回该结果
当浏览器向服务器发起请求时,服务器会将缓存规则放入 HTTP 响应报文的 HTTP 头中和请求结果一起返回给浏览器,控制强制缓存的字段分别是 Expires 和 Cache-Control,其中 Cache-Control 优先级比 Expires 高。
1.Expires
缓存过期时间,用来指定资源到期的时间,是服务器端的具体的时间点
也就是说,Expires=max-age + 请求时间,需要和 Last-modified 结合使用。Expires 是 Web 服务器响应消息头字段,在响应 http 请求时告诉浏览器在过期时间前浏览器可以直接从浏览器缓存取数据,而无需再次请求。
Expires 是 HTTP/1 的产物,受限于本地时间,如果修改了本地时间,可能会造成缓存失效。Expires: Wed, 22 Oct 2018 08:41:00 GMT 表示资源会在 Wed, 22 Oct 2018 08:41:00 GMT 后过期,需要再次请求。
2.Cache-Control
http1.1 的产物, 由多个指令共同决定,主要用于控制网页缓存
public:所有内容都将被缓存(客户端和代理服务器都可缓存)
private:所有内容只有客户端可以缓存,表示中间节点(代理服务器)不允许缓存,Cache-Control 的默认取值
no-cache:客户端缓存内容,是否使用缓存则需要经过协商缓存来验证决定
设置了 no-cache 之后,并不是说浏览器就不再缓存数据,只是浏览器在使用缓存数据时,需要先确认一下数据是否还跟服务器保持一致。
no-store:所有内容都不会被缓存,即不使用强制缓存,也不使用协商缓存
max-age:max-age=xxx (xxx is numeric)表示缓存内容将在 xxx 秒后失效
s-maxage(单位为 s):同 max-age 作用一样,只在代理服务器中生效(比如 CDN 缓存)
max-stale:能容忍的最大过期时间
min-fresh:能够容忍的最小新鲜度
协商缓存
协商缓存就是强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程
- 协商缓存生效,返回 304 和 Not Modified
- 协商缓存失效,返回 200 和请求结果
同样,协商缓存的标识也是在响应报文的 HTTP 头中和请求结果一起返回给浏览器的,控制协商缓存的字段分别有:Last-Modified / If-Modified-Since 和 Etag / If-None-Match,其中 Etag / If-None-Match 的优先级比 Last-Modified / If-Modified-Since 高。
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 是客户端再次发起该请求时,携带上次请求返回的唯一标识 Etag 值,通过此字段值告诉服务器该资源上次请求返回的唯一标识值。
服务器收到该请求后,发现该请求头中含有 If-None-Match,则会根据 If-None-Match 的字段值与该资源在服务器的 Etag 值做对比,一致则返回 304,代表资源无更新,继续使用缓存文件;不一致则重新返回资源文件,状态码为 200
注:Etag / If-None-Match 优先级高于 Last-Modified / If-Modified-Since,同时存在则只有 Etag / If-None-Match 生效。
总结
强制缓存优先于协商缓存进行,若强制缓存(Expires 和 Cache-Control)生效则直接使用缓存,若不生效则进行协商缓存(Last-Modified / If-Modified-Since 和 Etag / If-None-Match),协商缓存由服务器决定是否使用缓存,若协商缓存失效,那么代表该请求的缓存失效,重新获取请求结果,再存入浏览器缓存中;生效则返回 304,继续使用缓存