本文全部代碼皆採用express搭建的簡單服務器css
Web 緩存是能夠自動保存常見文檔副本的 HTTP 設備。當 Web 請求抵達緩存時, 若是本地有「已緩存的」副本,就能夠從本地存儲設備而不是原始服務器中提取這 個文檔。(此結論來自http權威指南)html
優勢:web
缺點:express
from memory cache:字面理解是從內存中,其實也是字面的含義,這個資源是直接從內存中拿到的,不會請求服務器通常已經加載過該資源且緩存在了內存當中,當關閉該頁面時,此資源就被內存釋放掉了,再次從新打開相同頁面時不會出現from memory cache的狀況瀏覽器
from disk cache:同上相似,此資源是從磁盤當中取出的,也是在已經在以前的某個時間加載過該資源,不會請求服務器可是此資源不會隨着該頁面的關閉而釋放掉,由於是存在硬盤當中的,下次打開仍會from disk cache (來自:blog.csdn.net/garrettzxd/… )緩存
Expires,該值是一個GMT時間格式個字符串,瀏覽器進行第一次請求時,服務器會在返回頭部加上Expires,下次請求,若是在這個時間以前則命中緩存,bash
app.get('/', (req, res) => {
const cssContent = path.join(__dirname, './html/index.html');
fs.readFile(cssContent, function(err, data) {
res.setHeader("Expires", new Date(Date.now() + 2592000000).toUTCString());
res.end(data);
})
});
複製代碼
Cache-Control ,該值是利用max-age判斷緩存的生命週期,是以秒爲單位,如何在生命週期時間內,則命中緩存服務器
app.get('/', (req, res) => {
const cssContent = path.join(__dirname, './html/index.html');
fs.readFile(cssContent, function(err, data) {
res.setHeader("Cache-Control", "max-age=0");
res.end(data);
})
});
複製代碼
命中緩存: 網絡
Last-Modified: 表示爲爲實體頭部部分,response返回,表示爲資源的最後更新時間
If-Modified-Since:經過比較兩次的時間判斷,資源在請求期間是否有修改,假如沒有修改,則命中協商緩存,瀏覽器從緩存中讀取資源,若是沒有命中,資源有過修改,返回新的Last-Modified時間和服務器資源app
app.get('/', (req, res) => {
const cssContent = path.join(__dirname, './html/index.html')
fs.stat(cssContent, (err, start) => {
if (req.headers['if-modified-since'] === start.mtime.toUTCString()) {
res.writeHead(304, 'Not Modified');
res.end();
} else {
fs.readFile(cssContent, function (err, data) {
let lastModified = start.mtime.toUTCString();
res.setHeader('Last-Modified', lastModified);
res.writeHead(200, 'OK');
res.end(data);
})
}
})
});
複製代碼
有些狀況下僅判斷最後修改日期來驗證資源是否有改動是不夠的:
1,存在週期性重寫某些資源,但資源實際包含的內容並沒有變化;
2,被修改的信息並不重要,如註釋等;
3,Last-Modified沒法精確到毫秒,但有些資源更新頻率有時會小於一秒。
ETag:爲相應頭部字段,表示資源內容的惟一標識,隨服務器response返回;
If-None-Match: 服務器比較請求頭中的If-None-Match和當前資源中的etag是否一致,來判斷資源是否修改過,若是沒有修改,則命中緩存,瀏覽器從緩存中讀取資源,若是修改過,服務器會返回新的etag,並返回資源;
app.get('/home', (req, res) => {
const cssContent = path.join(__dirname, './html/index.html')
fs.stat(cssContent, (err, start) => {
let etag = md5(cssContent);
if (req.headers['if-none-match'] === etag) {
res.writeHead(304, 'Not Modified');
res.end();
} else {
fs.readFile(cssContent, function (err, data) {
res.setHeader('Etag', etag);
res.writeHead(200, 'OK');
res.end(data);
})
}
})
});
複製代碼
不推薦使用 Expires 首部,它指定的是實際的過時日期而不是秒數。HTTP 設計者 後來認爲,因爲不少服務器的時鐘都不一樣步,或者不正確,因此最好仍是用剩餘秒 數,而不是絕對時間來表示過時時間。
ETag解決了Last-Modified使用時可能出現的資源的時間戳變了但內容沒變及若是再一秒鐘之內資源變化但Last-Modified沒變的問題,感受ETag更加穩妥。
補充:根據瀏覽器緩存策略,Expire和Cache-Control用回車、後退、F5刷新會跳過本地緩存,每次都會從服務器中獲數據。