目录
缓存的介绍
缓存的分类
浏览器缓存的特点
浏览器缓存策略图
浏览器缓存协议头介绍
Expires
Cache-Control
Last-Modified / If-Modified-Since
ETag / If-None-Match
Etag出现的原因
缓存的优先级、强制不缓存及更新缓存
浏览器缓存常规设置
浏览器缓存demo
缓存的介绍
缓存的分类:
DNS域名解析缓存
Web服务器缓存(如:Nginx、Apache、Tomcat等)
CDN内容分发缓存
终端缓存(如:浏览器缓存、客户端缓存等)
etc...
浏览器缓存的特点
浏览器缓存是依赖于http协议的
不同的浏览器稍微有点区别
缓存是保存在浏览器中的;所以同一个浏览器,就算新开tab也是返回304;把浏览器退出重新打开,也是返回304;
浏览器缓存策略图
浏览器缓存协议头介绍
Expires
设置资源的过期时间
Cache-Control
设置资源的缓存时间
Last-Modified / If-Modified-Since
设置资源的最后修改时间
ETag / If-None-Match
设置资源的内容hash
Expires
简介:
`http/1.0`规范定义,其值为某个日期,规定这个日期之前都返回缓存,不请求服务器;
Expires = max-age + "每次下载时的当前的request时间",所以一旦重新下载的页面后,expires就重新计算一次
缺点:
没过设置的时间时,就算资源更新了,还是返回缓存
其值为服务器端的时间,如果浏览器所在机器的时间与服务器的时间相差很大(比如更改客户端时间),那么误差就很大
例子:
Expires: Mon, 08 Jan 2018 03:24:01 GMT
Cache-Control
简介:
其值为秒数,规定资源缓存多少秒,存储的是更新间隔;
设置Cache-Control时,为了保证向前兼容,都会同时设置Expires;
缺点:
同样有Expires一样的缺点:没过设置的时间时,就算资源更新了,还是返回缓存
只能精确到秒,资源有可能在1秒钟修改多次,导致返回的数据不准确
例子:
Cache-Control:max-age=15552000
Last-Modified
简介:
对应请求头中的`If-Modified-Since`;
其值是某个日期,表示文档的最后修改时间;
最后修改时间没变,直接返回304,只返回头部,不返回资源body;
流程:
第一次请求时,服务器会将资源的最后修改时间返回给浏览器,再请求时,浏览器会发送`If-Modified-Since`到服务器再对比
缺点:
会影响性能,因为每次请求后端都需要获取文件夹的最后修改时间
也只能精确到秒,但是比Cache-Control精确,因为每次请求浏览器都会把`If-Modified-Since`发送给服务器对比,然后确定返回200还是304,而Cache-Control是直接规定了多少秒,没过这个秒,不发送请求,浏览器直接from cache
例子:
Last-Modified:Wed, 22 Nov 2017 03:54:37 GMT
ETag
简介:
对应请求头中的`If-None-Match`
资源内容的hash,内容变了,Etag就会变;
流程:
第一次请求时,服务器会对资源内容(全部内容或者部分内容)进行hash,并把其传给浏览器,再请求时,浏览器会发送`If-None-Match`到服务器再对比,然后确定返回200还是304
缺点:
会影响性能,因为每次请求后端都需要读取文件内容并hash
例子:
Etag:QJ8ihycuJKpVTLT5xiQQhNT1Iec=
Etag出现的原因
Last-Modified已经足以让浏览器知道本地的缓存副本是否足够新,为什么还需要Etag?
`Last-Modified`标注的最后修改只能精确到秒级,如果某些文件在1秒钟以内,被修改多次的话,它将不能准确标注文件的新鲜度
如果某些文件会被定期生成,当有时内容并没有任何变化,但`Last-Modified`却改变了,导致文件没法使用缓存
有可能存在服务器没有准确获取文件修改时间,或者与代理服务器(如Nginx)时间不一致等情形
缓存的优先级、强制不缓存及更新缓存
优先级
ETag(Last-Modified) > Cache-Control > Expires
Last-Modified与ETag同时使用时,浏览器会同时发送If-Modified-Since和If-None-Match,按照http/1.1规范,服务端必须两个都验证通过后才能返回304
强制不缓存
`Expires: 0` && `Cache-Control: 'no-cache,no-store'`
动态给资源添加版本控制,如:'index.js?v=' + Date.now()
强制更新缓存
如果文件变化了,我们可以给资源加版本号强制浏览器请求服务器(此时浏览器一定会下载资源返回200,因为URI变更后浏览器会当其为一个新资源)
浏览器缓存常规设置
首先设置**Expires** 和 **Cache-Control**,可以直接from cache (from memory cache 或 from disk cache),不用http链接;
`from memory cache`直接从内存读取缓存,从chrome中看,其请求时间都为0;退出进程时(关闭浏览器),数据会被清空
`from disk cache`是从硬盘读取缓存,从chrome中看,其请求时间都大于0;退出进程时(关闭浏览器),数据不会被清空
设置**Last-Modified**
设置Last-Modified的主要原因是:资源没变,但是Cache-Control的时间已经到了,这时浏览器不会fromcache,而是请求服务器,这时直接返回304,以节省带宽
浏览器缓存demo
Mid框架地址:https://github.com/xudeming208/mid
Etag测试demo地址:https://github.com/xudeming208/learning/tree/master/nodeJS/demo/cache/Etag
Expires、Cache-Control及Last-Modified
更改Mid框架中的配置文件,debug改为false
将静态文件服务器jserver.js中的maxAge改为30(秒)
启动Mid框架
观察network:
第一次为200(第一次请求下载资源)
第二为from cache(因为设置了Expires和Cache-Control)
等待30秒后,刷新浏览器,此时静态资源都变成304了(此时Cache-Control超过了30秒,缓存过时了,浏览器不会from cache,而会请求服务器,但是资源没变化,所以命中了Last-Modified,返回304)
Etag
node node.js
打开浏览器观察,第一次应该返回200,response headers中有Etag字段,request headers中没有If-None-Match字段
刷新页面,返回304,response headers中没有Etag字段,request headers中有If-None-Match字段,其值是第一次Etag的值
改变test.js的内容,再刷新页面,返回200,代表重新返回内容了,这时response headers中有Etag字段,但是值变了,request headers中有If-None-Match字段,其值还是第一次返回的Etag的值,两个值不一样
在刷新页面,结果和第三步一样