- 304
- 強制快取
- Expires/Cache-Control
- no-cache
- 對比快取
- Last-Modifed與if-modified-since
- Etag與if-none-match
- 兩種快取一起使用
- 瀏覽器行為
- Memory Cache 和 Disk Cache的區別
- f5和ctrl+f5
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 是瀏覽器快取的兩種模式。
筆者也不是很瞭解,這裡丟擲只是為了完善體系,這裡給出一些社群的回答
f5和ctrl+f5
f5:跳過強制快取,但是會檢查協商快取
ctrl+f5:跳過強制快取和協商快取,伺服器重新傳送資料給瀏覽器