- 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://stackoverflow.com/questions/44596937/chrome-memory-cache-vs-disk-cache
)
### f5和ctrl+f5
f5:跳過強制緩存,但是會檢查協商緩存
ctrl+f5:跳過強制緩存和協商緩存,服務器重新發送數據給瀏覽器