基於http協議講解緩存頭Cache-Control在服務中的應用

先思考兩個問題?

在頁面中引入靜態資源文件,為什麼靜態資源文件改變後,再次發起請求還是之前的內容,沒有變化呢?在使用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服務器,告訴代理服務器不要隨意改動返回的內容

示例

cache-control.html

<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);

第一次運行

瀏覽器運行結果,沒有什麼問題,正常響應

控制檯運行結果

修改cache-control.js返回值

...

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就會發生變化,這樣就可以達到一個更新緩存的目的,這也是目前前端來說比較常見的一個靜態資源方案。