瀏覽器快取,想說愛你不容易

2022-07-04 00:54:10 字數 3353 閱讀 5492

今天小微開店寶在測試環境發布更新的時候,同事問:「為什麼我需要手動清理瀏覽器快取才能看到變更?難道系統上線後也需要客戶自己清理瀏覽器快取嗎!」看來,這個坑需要我來填了。

瀏覽器快取(brower caching)是瀏覽器在本地磁碟對使用者最近請求過的文件進行儲存,當訪問者再次訪問同一頁面時,瀏覽器就可以直接從本地磁碟載入文件。

瀏覽器快取的優點有:

減少了冗餘的資料傳輸,節省了網費

減少了伺服器的負擔,大大提公升了**的效能

加快了客戶端載入網頁的速度

在前端開發面試中,瀏覽器快取是web效能優化面試題中很重要的乙個知識點,從而說明瀏覽器快取是提公升web效能的一大利器,但是瀏覽器快取如果使用不當,也會產生很多問題,正所謂是,想說愛你,並不是很容易的事。所以,結合最近遇到的案例,本文對瀏覽器快取相關的知識進行總結歸納,希望對讀者有所幫助。

瀏覽器快取主要有兩類:快取協商徹底快取,也有稱之為協商快取強快取

瀏覽器在第一次請求發生後,再次請求時:

瀏覽器會先獲取該資源快取的header資訊,根據其中的expirescahe-control判斷是否命中強快取,若命中則直接從快取中獲取資源,包括快取的header資訊,本次請求不會與伺服器進行通訊;

如果沒有命中強快取,瀏覽器會傳送請求到伺服器,該請求會攜帶第一次請求返回的有關快取的header欄位資訊(last-modified/if-modified-since、etag/if-none-match),由伺服器根據請求中的相關header資訊來對比結果是否命中協商快取,若命中,則伺服器返回新的響應header資訊更新快取中的對應header資訊,但是並不返回資源內容,它會告知瀏覽器可以直接從快取獲取;否則返回最新的資源內容

強快取是利用http的返回頭中的expires或者cache-control兩個欄位來控制的,用來表示資源的快取時間。

expires

該字段是http1.0時的規範,它的值為乙個絕對時間的gmt格式的時間字串,比如expires:mon,18 oct 2066 23:59:59gmt。這個時間代表著這個資源的失效時間,在此時間之前,即命中快取。這種方式有乙個明顯的缺點,由於失效時間是乙個絕對時間,所以當伺服器與客戶端時間偏差較大時,就會導致快取混亂。

cache-control

cache-control是http1.1時出現的header資訊,主要是利用該字段的max-age值來進行判斷,它是乙個相對時間,例如cache-control:max-age=3600,代表著資源的有效期是3600秒。cache-control除了該字段外,還有下面幾個比較常用的設定值:

public:可以被所有的使用者快取,包括終端使用者和cdn等中間**伺服器。

private:只能被終端使用者的瀏覽器快取,不允許cdn等中繼快取伺服器對其快取。

cache-control與expires可以在服務端配置同時啟用,同時啟用的時候cache-control優先順序高。

協商快取就是由伺服器來確定快取資源是否可用,所以客戶端與伺服器端要通過某種標識來進行通訊,從而讓伺服器判斷請求資源是否可以快取訪問,這主要涉及到下面兩組header欄位,這兩組搭檔都是成對出現的,即第一次請求的響應頭帶上某個字段(last-modified或者etag),則後續請求則會帶上對應的請求字段(if-modified-since或者if-none-match),若響應頭沒有last-modified或者etag欄位,則請求頭也不會有對應的字段。

last-modify/if-modify-since

瀏覽器第一次請求乙個資源的時候,伺服器返回的header中會加上last-modify,last-modify是乙個時間標識該資源的最後修改時間,例如last-modify: thu,31 dec 2037 23:59:59 gmt。

當瀏覽器再次請求該資源時,request的請求頭中會包含if-modify-since,該值為快取之前返回的last-modify。伺服器收到if-modify-since後,根據資源的最後修改時間判斷是否命中快取。

如果命中快取,則返回304,並且不會返回資源內容,並且不會返回last-modify。

etag/if-none-match

與last-modify/if-modify-since不同的是,etag/if-none-match返回的是乙個校驗碼。etag可以保證每乙個資源是唯一的,資源變化都會導致etag變化。伺服器根據瀏覽器上送的if-none-match值來判斷是否命中快取。

與last-modified不一樣的是,當伺服器返回304 not modified的響應時,由於etag重新生成過,response header中還會把這個etag返回,即使這個etag跟之前的沒有變化。

為什麼要有etag

你可能會覺得使用last-modified已經足以讓瀏覽器知道本地的快取副本是否足夠新,為什麼還需要etag呢?http1.1中etag的出現主要是為了解決幾個last-modified比較難解決的問題:

last-modified與etag是可以一起使用的,伺服器會優先驗證etag,一致的情況下,才會繼續比對last-modified,最後才決定是否返回304。

強快取與協商快取的區別可以用下表來表示:

獲取資源形式

狀態碼傳送請求到伺服器

強快取從快取取

200(from cache)

否,直接從快取取

協商快取

從快取取

304(not modified)

否,通過伺服器來告知快取是否可用

使用者操作

expires/cache-control

last-modied/etag

位址列回車

有效有效

頁面鏈結跳轉

有效有效

新開視窗

有效有效

前進回退

有效有效

f5重新整理

無效有效

ctrl+f5強制重新整理

無效無效

如文章開頭所屬,**更新到線上後使用者瀏覽器不能自行更新,我們不能要求客戶在系統更新後都進行一次快取清理的操作。

到底該如何解決呢?

這樣做是不是最完美的呢?很遺憾,不是。

IT 想說愛你不容易

檢查了半天,也跟蹤了伺服器端的執行日誌,沒有發現什麼問題,重啟伺服器程序,繼續跟蹤排程程序和執行程序,依舊沒有看出什麼問題,後來根據日誌中的select語句又到資料庫裡面查了一下,嘿!居然沒有資料。估計是命令解析的時候出了錯誤,看來是程式問題了,在伺服器上找到執行程序的源程式,make clean ...

ROR TDD,想說愛你不容易

tdd,也就是 test driven development 測試驅動開發,其實是一種開發方式的巨大提高。它 提出了一種新的開發方式 以測試為驅動。在此,我仍然想引用乙個曾經看過的thoughtworks的 乙個人的blog中的一句話 什麼是tdd?tdd就是把你的需求用測試給描述出來。這句話一下...

東航,想說愛你不容易

我坐東航的航班是小概率事件。自05年6月做諮詢以來,平均每月飛行12次,到現在大概有600次的飛行記錄,坐東航的航班大概有10次。在10次的記錄中,印象裡只有一次準點,因此,在我印象裡 東航準點也是小概率事件,所以,除非萬不得已,我不坐東航的航班。從今年五一到現在,今天是第三次坐東航的航班,次次晚點...