res.statusCode = 304;
复制代码
当咱们在响应信息中回复304时,浏览器会自动从本地的缓存数据库中拿取数据。chrome
嗯,这句实际上是缓存中最关键的一句,其它的获取设置缓存相关的头都是再为是否输出这一句话作铺垫。数据库
res.setHeader('Expires',date.toUTCString());
res.setHeader('Cache-Control','max-age=10'); //以秒为单位
复制代码
Expires
和Cache-Control
都能起到强制缓存的做用,即在必定时间内客户端的请求会先走本地缓存而不是向服务器发起。浏览器
其中Expires是http1.0
协议中的头,咱们使用它通常都是为了兼容,值得注意的是Expires的值和Cache-Control的值是不同的。缓存
Expires的值要求必须是GMT格式(?嗯,印象中有人这么说过,反正我不用。。。),而Cache-Control值的格式则为max-age=xxx
,xxx是一个数字,是一个相对时间,单位为秒。bash
当Cache-Control
置为no-cache
时,客户端每次请求都会先忽略本地缓存直接向服务端询问是否要采用缓存。服务器
又称之为“协商缓存”ui
根据文件的修改时间是否发生改变来决定是否采起缓存。spa
res.setHeader('Last-Modified',stat.ctime.toUTCSting());
复制代码
let since = req.headers['if-modified-since'];
if(since){
if(since === stat.ctime.toUTCString()){ //没有被修改
res.statusCode = 304; //让它去缓存中找
res.end();
}else{
sendFile(req,res,p,stat);
}
}else{
sendFile(req,res,p,stat);
}
复制代码
注意: 这个时间格式并无强制的限制,但咱们要注意在使用中要保持格式的一致。code
根据文件的内容是否发生改变来决定是否采起缓存。cdn
function sendFile(req,res,p,stat){
res.setHeader('Cache-Control','no-cache'); //不走本地缓存,会向服务器询问
res.setHeader('Etag',r);
res.setHeader('Content-Type',mime.getType(p)+';charset=utf8');
...
}
复制代码
...
let md5 = crypto.createHash('md5');
let rs = fs.createReadStream(p);
rs.on('data',function(data){
md5.update(data);
});
rs.on('end',function(){
let r = md5.digest('hex'); //对当前文件进行摘要
let ifNoneMatch = req.headers['if-none-match'];
if(ifNoneMatch){
if(ifNoneMatch===r){
res.statusCode = 304;
res.end();
}else{
sendFile(req,res,p,r);
}
}else{
sendFile(req,res,p,r);
}
})
...
复制代码
若是文件过大时,进行摘要是很不实际的,So咱们通常选择ctime+size做为Etag
的值。
通常来讲会同时使用上以上两种缓存,这个时候会先看强制缓存是否过时,没有过时就会从本地缓存中拿数据,只有过时了才会向服务器询问,这样有利于减轻服务器的鸭梨。
Memory Cache 和 Disk Cache 是浏览器缓存的两种模式。
笔者也不是很了解,这里抛出只是为了完善体系,这里给出一些社区的回答
f5:跳过强制缓存,可是会检查协商缓存
ctrl+f5:跳过强制缓存和协商缓存,服务器从新发送数据给浏览器