- 304
- 强制缓存
- Expires/Cache-Control
- no-cache
- 对比缓存
- Last-Modifed与if-modified-since
- Etag与if-none-match
- 两种缓存一起使用
- 浏览器行为
- Memory Cache 和 Disk Cache的区别
- f5和ctrl+f5
[TOC]
## 304
```
res.statusCode = 304;
```
当我们在响应信息中回复304时,浏览器会自动从本地的缓存数据库中拿取数据。
嗯,这句其实是缓存中最关键的一句,其它的获取设置缓存相关的头都是再为是否输出这一句话做铺垫。
## 强制缓存
### Expires/Cache-Control
```
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是一个数字,是一个相对时间,单位为**秒**。
#### no-cache
当`Cache-Control`置为`no-cache`时,客户端每次请求都**会先忽略本地缓存**直接向服务端询问是否要采用缓存。
## 对比缓存
### Last-Modifed与if-modified-since
根据文件的修改时间是否发生改变来决定是否采取缓存。
```
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);
}
```
>**注意:** 这个时间格式并没有强制的限制,但我们要注意在使用中要保持格式的一致。
### Etag与if-none-match
根据文件的内容是否发生改变来决定是否采取缓存。
```
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的区别
Memory Cache 和 Disk Cache 是浏览器缓存的两种模式。
笔者也不是很了解,这里抛出只是为了完善体系,这里给出一些社区的回答
![](https://box.kancloud.cn/4d387e06b77aebbe85d80e928dd2b195_1650x488.png)
> [原文](https://stackoverflow.com/questions/44596937/chrome-memory-cache-vs-disk-cache
)
### f5和ctrl+f5
f5:跳过强制缓存,但是会检查协商缓存
ctrl+f5:跳过强制缓存和协商缓存,服务器重新发送数据给浏览器