先思考兩個問題?
在頁面中引入靜態資源文件,為什麼靜態資源文件改變後,再次發起請求還是之前的內容,沒有變化呢?在使用webpack等一些打包工具時,為什麼要加上一串hash碼?緩存頭Cache-Control的一些特性
可緩存性
public http經過的任何地方都可以進行緩存private 只有發起請求的這個瀏覽器才可以進行緩存no-cache 任何一個節點都不可以緩存到期
max-age=<seconds> 設置緩存到多少秒過期/<seconds>s-maxage=<seconds> 會代替max-age,只有在代理服務器才會生效/<seconds>max-stale=<seconds> 是發起請求方主動帶起的一個頭,是代表即便緩存過期,但是在max-stale這個時間內還可以使用過期的緩存,而不需要願服務器請求新的內容/<seconds>重新驗證
must-revalidate 如果max-age設置的內容過期,必須要向服務器請求重新獲取數據驗證內容是否過期proxy-revalidate 主要用在緩存服務器,指定緩存服務器在過期後重新從原服務器獲取,不能從本地獲取其它
no-store 本地和代理服務器都不可以存儲這個緩存,永遠都要從服務器拿body新的內容使用no-transform 主要用於proxy服務器,告訴代理服務器不要隨意改動返回的內容示例
<title>cache-control/<title>
cache-control.js
瀏覽器輸入http://localhost:3010/ 加載cache-control.html文件,該文件會請求http://localhost:3010/script.js,在url等於/script.js設置cache-control的max-age進行瀏覽器緩存
const http = require('http');
const fs = require('fs');
const port = 3010;
http.createServer((request, response) => {
console.log('request url: ', request.url);
if (request.url === '/') {
const html = fs.readFileSync('./example/cache/cache-control.html', 'utf-8');
response.writeHead(200, {
'Content-Type': 'text/html',
});
response.end(html);
} else if (request.url === '/script.js') {
response.writeHead(200, {
'Content-Type': 'text/javascript',
'Cache-Control': 'max-age=200'
});
response.end("console.log('script load')");
}
}).listen(port);
console.log('server listening on port ', port);
第一次運行瀏覽器運行結果,沒有什麼問題,正常響應
控制檯運行結果
...
response.writeHead(200, {
'Content-Type': 'text/javascript',
'Cache-Control': 'max-age=200'
});
response.end("console.log('script load !!!')");
...
中斷上次程序,第二次運行瀏覽器運營結果
第二次運行,從memory cahce讀取,瀏覽器控制檯並沒有打印修改過的內容
控制檯運營結果
指請求了/ 並沒有請求 /script.js
以上結果瀏覽器並沒有返回給我們服務端修改的結果,這是為什麼呢?是因為我們請求的url/script.js沒有變,那麼瀏覽器就不會經過服務端的驗證,會直接從客戶端緩存去讀,就會導致一個問題,我們的js靜態資源更新之後,不會立即更新到我們的客戶端,這也是前端開發中常見的一個問題,我們是希望瀏覽器去緩存我們的靜態資源文件(js、css、img等)我們也不希望服務端內容更新了之後客戶端還是請求的緩存的資源, 解決辦法也就是我們在做js構建流程時,把打包完成的js文件名上根據它內容hash值加上一串hash碼,這樣你的js文件或者css文件等內容不變,這樣生成的hash碼就不會變,反映到頁面上就是你的url沒有變,如果你的文件內容有變化那麼嵌入到頁面的文件url就會發生變化,這樣就可以達到一個更新緩存的目的,這也是目前前端來說比較常見的一個靜態資源方案。