瀏覽器緩存(Brower Caching)是瀏覽器在本地磁盤對(duì)用戶最近請(qǐng)求過的文檔進(jìn)行存儲(chǔ),當(dāng)訪問者再次訪問同一頁面時(shí),瀏覽器就可以直接從本地磁盤加載文檔。
瀏覽器緩存的優(yōu)點(diǎn)有:
在前端開發(fā)面試中,瀏覽器緩存是web性能優(yōu)化面試題中很重要的一個(gè)知識(shí)點(diǎn),從而說明瀏覽器緩存是提升web性能的一大利器,但是瀏覽器緩存如果使用不當(dāng),也會(huì)產(chǎn)生很多問題,正所謂是,想說愛你,并不是很容易的事。所以,結(jié)合最近遇到的案例,本文對(duì)瀏覽器緩存相關(guān)的知識(shí)進(jìn)行總結(jié)歸納,希望對(duì)讀者有所幫助。
瀏覽器緩存的分類瀏覽器緩存主要有兩類:緩存協(xié)商和徹底緩存,也有稱之為協(xié)商緩存和強(qiáng)緩存。
瀏覽器在第一次請(qǐng)求發(fā)生后,再次請(qǐng)求時(shí):
強(qiáng)緩存是利用http的返回頭中的Expires或者Cache-Control兩個(gè)字段來控制的,用來表示資源的緩存時(shí)間。
Expires
該字段是http1.0時(shí)的規(guī)范,它的值為一個(gè)絕對(duì)時(shí)間的GMT格式的時(shí)間字符串,比如Expires:Mon,18 Oct 2066 23:59:59 GMT。這個(gè)時(shí)間代表著這個(gè)資源的失效時(shí)間,在此時(shí)間之前,即命中緩存。這種方式有一個(gè)明顯的缺點(diǎn),由于失效時(shí)間是一個(gè)絕對(duì)時(shí)間,所以當(dāng)服務(wù)器與客戶端時(shí)間偏差較大時(shí),就會(huì)導(dǎo)致緩存混亂。
Cache-Control
Cache-Control是http1.1時(shí)出現(xiàn)的header信息,主要是利用該字段的max-age值來進(jìn)行判斷,它是一個(gè)相對(duì)時(shí)間,例如Cache-Control:max-age=3600,代表著資源的有效期是3600秒。cache-control除了該字段外,還有下面幾個(gè)比較常用的設(shè)置值:
Cache-Control與Expires可以在服務(wù)端配置同時(shí)啟用,同時(shí)啟用的時(shí)候Cache-Control優(yōu)先級(jí)高。
協(xié)商緩存就是由服務(wù)器來確定緩存資源是否可用,所以客戶端與服務(wù)器端要通過某種標(biāo)識(shí)來進(jìn)行通信,從而讓服務(wù)器判斷請(qǐng)求資源是否可以緩存訪問,這主要涉及到下面兩組header字段,這兩組搭檔都是成對(duì)出現(xiàn)的,即第一次請(qǐng)求的響應(yīng)頭帶上某個(gè)字段(Last-Modified或者Etag),則后續(xù)請(qǐng)求則會(huì)帶上對(duì)應(yīng)的請(qǐng)求字段(If-Modified-Since或者If-None-Match),若響應(yīng)頭沒有Last-Modified或者Etag字段,則請(qǐng)求頭也不會(huì)有對(duì)應(yīng)的字段。
Last-Modify/If-Modify-Since
瀏覽器第一次請(qǐng)求一個(gè)資源的時(shí)候,服務(wù)器返回的header中會(huì)加上Last-Modify,Last-modify是一個(gè)時(shí)間標(biāo)識(shí)該資源的最后修改時(shí)間,例如Last-Modify: Thu,31 Dec 2037 23:59:59 GMT。
當(dāng)瀏覽器再次請(qǐng)求該資源時(shí),request的請(qǐng)求頭中會(huì)包含If-Modify-Since,該值為緩存之前返回的Last-Modify。服務(wù)器收到If-Modify-Since后,根據(jù)資源的最后修改時(shí)間判斷是否命中緩存。
如果命中緩存,則返回304,并且不會(huì)返回資源內(nèi)容,并且不會(huì)返回Last-Modify。
ETag/If-None-Match
與Last-Modify/If-Modify-Since不同的是,Etag/If-None-Match返回的是一個(gè)校驗(yàn)碼。ETag可以保證每一個(gè)資源是唯一的,資源變化都會(huì)導(dǎo)致ETag變化。服務(wù)器根據(jù)瀏覽器上送的If-None-Match值來判斷是否命中緩存。
與Last-Modified不一樣的是,當(dāng)服務(wù)器返回304 Not Modified的響應(yīng)時(shí),由于ETag重新生成過,response header中還會(huì)把這個(gè)ETag返回,即使這個(gè)ETag跟之前的沒有變化。
為什么要有Etag
你可能會(huì)覺得使用Last-Modified已經(jīng)足以讓瀏覽器知道本地的緩存副本是否足夠新,為什么還需要Etag呢?HTTP1.1中Etag的出現(xiàn)主要是為了解決幾個(gè)Last-Modified比較難解決的問題:
Last-Modified與ETag是可以一起使用的,服務(wù)器會(huì)優(yōu)先驗(yàn)證ETag,一致的情況下,才會(huì)繼續(xù)比對(duì)Last-Modified,最后才決定是否返回304。
強(qiáng)緩存與協(xié)商緩存的區(qū)別可以用下表來表示:
?|獲取資源形式|狀態(tài)碼|發(fā)送請(qǐng)求到服務(wù)器
------|------------|------|----------------
強(qiáng)緩存|從緩存取 |200(from cache)|否,直接從緩存取
協(xié)商緩存|從緩存取|304(Not Modified)|否,通過服務(wù)器來告知緩存是否可用
地址欄回車 | 有效 | 有效 |
頁面鏈接跳轉(zhuǎn) | 有效 | 有效 |
新開窗口 | 有效 | 有效 |
前進(jìn)回退 | 有效 | 有效 |
F5刷新 | 無效 | 有效 |
Ctrl+F5強(qiáng)制刷新 | 無效 | 無效 |
如文章開頭所屬,代碼更新到線上后用戶瀏覽器不能自行更新,我們不能要求客戶在系統(tǒng)更新后都進(jìn)行一次緩存清理的操作。
到底該如何解決呢?
在資源請(qǐng)求的URL中增加一個(gè)參數(shù),比如:js/mian.js?ver=0.7.1。這個(gè)參數(shù)是一個(gè)版本號(hào),每一次部署的時(shí)候變更一下,當(dāng)這個(gè)參數(shù)變化的時(shí)候,強(qiáng)緩存都會(huì)失效并重新加載。這樣一來,靜態(tài)資源,部署以后就需要重新加載。這樣就比較完美的解決了問題。
進(jìn)一步思考這樣做是不是最完美的呢?很遺憾,不是。
百度張?jiān)讫埥o出了這樣做的弊端,有興趣可參照下文:
靜態(tài)資源版本更新與緩存
謝謝!
聲明:本網(wǎng)頁內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。TEL:0731-84117792 E-MAIL:11247931@qq.com