浏览器缓存
浏览器缓存可以分为强缓存以及协商缓存
强缓存
强缓存:不会向服务器发送请求,直接从缓存中读取资源,在chrome控制台的Network选项中可以看到该请求返回200的状态码,并且Size显示from disk cache或from memory cache。强缓存可以通过设置两种 HTTP Header 实现:Expires 和 Cache-Control。
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
在HTTP/1.1中,Cache-Control是最重要的规则,主要用于控制网页缓存。比如当Cache-Control:max-age=300时,则代表在这个请求正确返回时间(浏览器也会记录下来)的5分钟内再次加载资源,就会命中强缓存。
Cache-Control的指令
public:所有内容都将被缓存(客户端和代理服务器都可缓存)。
no-cache:客户端缓存内容,是否使用缓存则需要经过协商缓存来验证决定。表示不使用 Cache-Control的缓存控制方式做前置验证,而是使用 Etag 或者Last-Modified字段来控制缓存。需要注意的是,no-cache这个名字有一点误导。设置了no-cache之后,并不是说浏览器就不再缓存数据,只是浏览器在使用缓存数据时,需要先确认一下数据是否还跟服务器保持一致。
no-store:所有内容都不会被缓存,即不使用强制缓存,也不使用协商缓存。
max-age:max-age=xxx (xxx is numeric)表示缓存内容将在xxx秒后失效。
s-maxage(单位为s):同max-age作用一样,只在代理服务器中生效(比如CDN缓存)。比如当s-maxage=60时,在这60秒中,即使更新了CDN的内容,浏览器也不会进行请求。max-age用于普通缓存,而s-maxage用于代理缓存。s-maxage的优先级高于max-age。如果存在s-maxage,则会覆盖掉max-age和Expires header。
max-stale:能容忍的最大过期时间。max-stale指令标示了客户端愿意接收一个已经过期了的响应。如果指定了max-stale的值,则最大容忍时间为对应的秒数。如果没有指定,那么说明浏览器愿意接收任何age的响应(age表示响应由源站生成或确认的时间与当前时间的差值)。
min-fresh:能够容忍的最小新鲜度。min-fresh标示了客户端不愿意接受新鲜度不多于当前的age加上min-fresh设定的时间之和的响应。
协商缓存
协商缓存就是强缓存失效之后,浏览器重新发起HTTP请求(携带缓存标识),然后返屋企根据缓存标识决定是否使用缓存的过程,如下两种情况:
一.协商缓存生效,返回304和Not Modified
1.浏览器->发起HTTP请求->浏览器缓存
2.浏览器缓存->发现该请求的缓存结果失效->返回缓存标识
3.浏览器->携带该资源的缓存标识,发起HTTP请求->服务器
4.服务器->返回304,Not Modified->浏览器
5.浏览器->获取该请求的缓存结果->浏览器缓存
6.浏览器缓存->返回该请求的缓存结果
二.协商缓存失效,返回200和请求结果
1.浏览器->发起HTTP请求->浏览器缓存
2.浏览器缓存->发现该请求的缓存结果失效->返回缓存标识
3.浏览器->携带该资源的缓存标识,发起HTTP请求->服务器
4.服务器->返回200,资源更新了->浏览器
5.浏览器->将本次请求的结果以及缓存标识存入浏览器缓存中->浏览器缓存
缓存标识一般通过设置HTTP Header中的Last-Modified以及ETag实现。
一.Last-Modified和If-Modified-Since
1.浏览器第一次访问服务器资源时,服务器返回的response header里面带有Last-Modified,表示资源在服务器的最后修改时间
2.浏览器下一次访问这个资源,浏览器检测到有Last-Modified这个header,于是添加If-Modified-Since到header里(值伪上一次得到的Last-Modified),服务器拿到请求中的If-Modified-Since于服务器中资源的最后修改时间进行对比,若不变则返回304以及空的响应体,直接从缓存读取;如果小于服务器时间,则说明文件被更新了,则返回200以及新的资源文件。
Last-Modified的坏处:
如果客户本地打开缓存文件,导致Last-Modified被修改,因此服务器会以为是旧的资
源,则重复返回相同资源。
因为Last-Modified只能以秒进行计时,若在秒级内改变了资源,导致服务器没有发送最新的资源给客户端。
二.ETag和If-None-Match
由于文件修改时间并不靠谱,HTTP/1.1出现ETag和If-None-Match。
Etag是服务器响应请求时,返回当前资源文件的一个唯一标识(由服务器生成),只要资源有变化,Etag就会重新生成。
三.ETag与Last-Modified对比
在精确度上,ETag要优于Last-Modified,
在性能上,ETag要劣于Last-Modified,因为ETag需要服务器通过算法计算hash值。
在优先级,服务器先校验ETag。
缓存机制
先查看是否可以进行强缓存,再进行协商缓存。每次只用一种缓存。
如果什么缓存策略都没设置,那么浏览器会怎么处理?
对于这种情况,浏览器会采用一个启发式的算法,通常会取响应头中的 Date 减去 Last-Modified 值的 10% 作为缓存时间。
实际场景应用缓存策略
1.频繁变动的资源
对于频繁变动的资源,首先需要使用Cache-Control: no-cache 使浏览器每次都请求服务器,然后配合 ETag 或者 Last-Modified 来验证资源是否有效。这样的做法虽然不能节省请求数量,但是能显著减少响应数据大小。
2.不常变化的资源
通常在处理这类资源时,给它们的 Cache-Control 配置一个很大的 max-age=31536000 (一年),这样浏览器之后请求相同的 URL 会命中强制缓存。而为了解决更新的问题,就需要在文件名(或者路径)中添加 hash, 版本号等动态字符,之后更改动态字符,从而达到更改引用 URL 的目的,让之前的强制缓存失效 (其实并未立即失效,只是不再使用了而已)。
在线提供的类库 (如 jquery-3.3.1.min.js, lodash.min.js 等) 均采用这个模式。
用户行为对浏览器缓存的影响
所谓用户行为对浏览器缓存的影响,指的就是用户在浏览器如何操作时,会触发怎样的缓存策略。主要有 3 种:
打开网页,地址栏输入地址: 查找 disk cache 中是否有匹配。如有则使用;如没有则发送网络请求。
普通刷新 (F5):因为 TAB 并没有关闭,因此 memory cache 是可用的,会被优先使用(如果匹配的话)。其次才是 disk cache。
强制刷新 (Ctrl + F5):浏览器不使用缓存,因此发送的请求头部均带有 Cache-control: no-cache(为了兼容,还带了 Pragma: no-cache),服务器直接返回 200 和最新内容。

浙公网安备 33010602011771号