對(duì)于一個(gè)數(shù)據(jù)請(qǐng)求來(lái)說(shuō),可以分為發(fā)起網(wǎng)絡(luò)請(qǐng)求、后端處理、瀏覽器響應(yīng)三個(gè)步驟,瀏覽器緩存可以幫助我們?cè)诘谝徊胶偷谌街袃?yōu)化性能。例如直接使用緩存,不發(fā)起請(qǐng)求,或者發(fā)起了請(qǐng)求但是后端存儲(chǔ)的數(shù)據(jù)和前端一致,就沒(méi)有必要再將數(shù)據(jù)傳輸回來(lái),這樣就減少了響應(yīng)數(shù)據(jù)。
瀏覽器緩存分為兩類(lèi):
強(qiáng)緩存:
如果資源沒(méi)過(guò)期,就取緩存,如果過(guò)期了,則請(qǐng)求服務(wù)器。強(qiáng)緩存的規(guī)則主要看response header。
Cache-Control(規(guī)則可以同時(shí)多個(gè)存在)
- private: jin瀏覽器可以緩存;
- 瀏覽器和代理服務(wù)器都可以緩存(前端可認(rèn)為private和public一樣);
- max-age=xxx : 過(guò)期時(shí)間;
- no-cache: 不進(jìn)行強(qiáng)緩存;
- no-store: 不強(qiáng)緩存,也不協(xié)商緩存。
所以判斷該資源是否命中強(qiáng)緩存,就看response中Cache-Control的值,如果有max-age=xxx秒,則命中強(qiáng)緩存;如果Cache-Control的值是no-cache,說(shuō)明沒(méi)命中強(qiáng)緩存,是協(xié)商緩存。

協(xié)商緩存:
觸發(fā)條件為Cache-Control的值為no-cache(不強(qiáng)緩存);或者max-age過(guò)期了
- ETag:每個(gè)文件有一個(gè),改動(dòng)了文件就變了,可以看似md5;
- Last-Modified:文件的修改時(shí)間;
每次服務(wù)器返回的response header中的ETag和Last-Modified,在下次請(qǐng)求時(shí),request header 就把這兩個(gè)帶上,但是改變了名字(ETag -> If-None-Match,Last-Modified -> If-Modified-Since),服務(wù)器把request header帶過(guò)來(lái)的資源目前的標(biāo)識(shí)與服務(wù)器中的進(jìn)行對(duì)比,然后判斷資源是否更改;
每次請(qǐng)求資源時(shí),把用戶本地資源的ETag同時(shí)帶到服務(wù)端,服務(wù)端和最新資源做對(duì)比;如果資源沒(méi)更改,返回304,瀏覽器讀取本地緩存;如果資源有更改,返回200,返回最新的資源;
協(xié)商緩存無(wú)論結(jié)果,都需要向服務(wù)端發(fā)起請(qǐng)求,如果資源未更改時(shí),返回的是header信息,size很小,如果資源有更新,還要返回body數(shù)據(jù),size很大。
為什么要有 ETag
ETag 是服務(wù)器響應(yīng)請(qǐng)求時(shí),返回當(dāng)前資源文件的一個(gè)唯一標(biāo)識(shí)(由服務(wù)器生成),只要資源有變化,ETag就會(huì)重新生成;http 中 ETag 的出現(xiàn)是為了解決幾個(gè)Last-Modified難解決的問(wèn)題:
- 有些文件也許會(huì)周期性的更改,但是它的內(nèi)容并不改變(僅改變修改時(shí)間),這時(shí)不希望客戶端認(rèn)為這個(gè)文件被修改了,而重新請(qǐng)求;
- 某些文件修改非常頻繁,例如在秒以下的時(shí)間進(jìn)行修改,If-Modified-Since能檢查到的粒度是s級(jí)的,所以這種修改無(wú)法判斷;
- 某些服務(wù)器不能精準(zhǔn)的得到文件的最后修改時(shí)間
用戶行為對(duì)緩存的影響
- 打開(kāi)網(wǎng)頁(yè),地址欄輸入地址: 查找disk cache 中是否有匹配,如果有則使用;如果沒(méi)有則發(fā)起網(wǎng)絡(luò)請(qǐng)求;
- F5刷新:跳過(guò)強(qiáng)緩存規(guī)則,直接走協(xié)商緩存;Ctrl+F5;
- 跳過(guò)所有緩存規(guī)則,和第一次請(qǐng)求一樣,重新獲取資源,發(fā)送的請(qǐng)求頭部帶有 Cache-Control: no-cache
如果什么緩存策略都設(shè)置,那么瀏覽器會(huì)采用一個(gè)啟發(fā)式的算法,取響應(yīng)頭中的Date 減去 Last-Modified 值的 10% 作為緩存時(shí)間