面试:
缓存主要分为强缓存和协议缓存,在浏览器加载资源的时候,会根据请求头判断是否命中强缓存,如果命中强缓存的话,会直接从缓存中读取数据而不发送请求。
判断强缓存的方式的话,需要判断请求头中是否有cache-control或者expires字段,这两个字段分别规定了以秒为单位的生存时长,和gmt格式的过期日期,如果在缓存未过期的时间内,就能命中强缓存,优先级的话是cache-control优先于expires
如果没有命中强缓存就要看看是否命中协议缓存,协议缓存需要两组请求头并通过服务器进行校验,如果命中协议缓存都话,就会返回304,否则就返回请求的资源。判断是否命中协议缓存需要用两组请求头来判断,第一次向服务器发送请求,服务器返回字段中会包含ETag或者Last-Modified,再次发起请求的时候,如果强缓存已经过期,并且资源中ETag和Last-modified声明,就会在请求中带上对应的 If-none-match和if-modified-since字段
如果是Etag,第二次请求就会带if-none-match,他的值就是etag的值,服务器收到后发现如果有if-none-match字段,就个服务器端的相应校验串进行对比,没有更改就返回304
如果是last-modified。第二次请求就会带上if-modified-since,他的值就是last-modified的值,服务器将该值与被请求资源的最后修改时间进行对比,如果服务器 的资源的最后修改时间比较新,说明被修改过,就返回200和新资源,如果一致说明没有修改过,返回304
过程
浏览器加载资源时,会根据请求的header头部判断是否命中强缓存,如果命中直接从缓存中读取数据而不发送请求,200(from cache)
命中规则:
如果请求头中有cache-control(1.1)或者expires(1.0)字段,分别规定了生存时长(以秒为单位)和绝对过期日期(GMT时间格式),如果请求在缓存未过期内,则能命中缓存
过程:
通过两组请求头,服务器进行校验,如果命中协议缓存,返回304,否则返回新资源以及200
命中规则:
用两组请求头来判断,
① 第一次向服务器发送请求,服务器返回字段中包含ETag和Last-Modified。、
② 再次发起请求时,如果Cache-Control缓存过期,并且资源有ETag和Last-Modified声明,则带上分别对应的If-None-Match和If-Modified-Since
用于强缓存,直接从缓存中取数而不向服务器发请求,有多个参数可以决定是否走缓存、缓存存活时间等
可缓存性:
到期时间:
expires提供一个GMT格式的过期日期,在该日期之前都会使用缓存而非请求
如 Expires:Sun, 08 Nov 2009 03:37:26 GMT
注意:
expires是1.0的方法,现在大多使用1.1
ETag/If-None-match需要配合cache-control使用,当cache-concrol过期后,才使用ETag。
ETag: 资源在服务器的唯一标识(由服务器决定如何生成)。在Apache中,ETag的值默认是对文件的索引节(INode)、大小(size)和最后修改时间(MTime)进行hash得到的。可以从文件内容进行判断是否进行过更改
If-None-Match: 当缓存过期的时候,发现资源有ETag字段,则在请求头中带上If-None-Match,其值就是ETag的值,问问服务器资源有没有更改,服务器把请求里的If-None-Match值与资源在服务器的校验值进行对比,
Last-Modified/If-Modified-Since需要配合cache-control使用,当cache-concrol过期后,才使用Last-Modified。优先级低于Etag
last-modified: 资源最后修改时间
if-modified-since: 当cache-control过期后,发现资源有last-modified字段,就在请求中加入if-modified-since。其值是last-modified的值,服务器接到请求后对比最后修改时间,服务器端的比较新就说明有更改返回200和资源,一致说明未更改返回304
① last-modified只能精确到秒级,如果资源在一秒内多次修改,不能准确标注文件的修改时间
② 有些文件会定期生成,但是内容并没有发生变化,但是last-modified变了不能使用缓存
③ 可能存在服务器没有准确获取资源最后修改时间,或者与代理服务器时间不一致的情况
200OK不向服务器发送请求,直接使用缓存
304 则是想服务器发请求咨询,服务器认为文件没有更改,不需要重新获取,使用浏览器的缓存即可
200OK出现情景:
① 地址栏回车
② 页面链接跳转
③ 前进、后退
304出现情景:
① F5刷新
② 新开窗口
清除缓存:
① meta标签中令cache-control为no-cache或者expires为0
//不缓存
<META HTTP-EQUIV="pragma" CONTENT="no-cache">
<META HTTP-EQUIV="Cache-Control" CONTENT="no-cache, must-revalidate">
<META HTTP-EQUIV="expires" CONTENT="0">
② ajax请求清除
用ajax请求服务器最新文件,并加上请求头If-Modified-Since和Cache-Control
$.ajax({
url:'www.haorooms.com',
dataType:'json',
data:{},
beforeSend :function(xmlHttp){
xmlHttp.setRequestHeader("If-Modified-Since","0");
xmlHttp.setRequestHeader("Cache-Control","no-cache");
},
success:function(response){
//操作
}
async:false
});
或者cache:false
$.ajax({
url:'www.haorooms.com',
dataType:'json',
data:{},
cache:false,
ifModified :true ,
success:function(response){
//操作
}
async:false
});
不能缓存:
① http头中cache-control为no-cache或者为max-age: 0
② 需要根据cookie,和输入内容的动态请求
③ 经过https加密的请求
④ post请求不可以被缓存
⑤ http响应头中不含Last-Modified/Etag,也不包含Cache-Control/Expires的请求无法被缓存