今天小微開店寶在測試環境發布更新的時候,同事問:「為什麼我需要手動清理瀏覽器快取才能看到變更?難道系統上線後也需要客戶自己清理瀏覽器快取嗎!」看來,這個坑需要我來填了。
瀏覽器快取(brower caching)
是瀏覽器在本地磁碟對使用者最近請求過的文件進行儲存,當訪問者再次訪問同一頁面時,瀏覽器就可以直接從本地磁碟載入文件。
瀏覽器快取的優點有:
減少了冗餘的資料傳輸,節省了網費
減少了伺服器的負擔,大大提公升了**的效能
加快了客戶端載入網頁的速度
在前端開發面試中,瀏覽器快取是web效能優化面試題中很重要的乙個知識點,從而說明瀏覽器快取是提公升web效能的一大利器,但是瀏覽器快取如果使用不當,也會產生很多問題,正所謂是,想說愛你,並不是很容易的事。所以,結合最近遇到的案例,本文對瀏覽器快取相關的知識進行總結歸納,希望對讀者有所幫助。
瀏覽器快取主要有兩類:快取協商
和徹底快取
,也有稱之為協商快取
和強快取
。
瀏覽器在第一次請求發生後,再次請求時:
瀏覽器會先獲取該資源快取的header資訊,根據其中的expires
和cahe-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:59
gmt。這個時間代表著這個資源的失效時間,在此時間之前,即命中快取。這種方式有乙個明顯的缺點,由於失效時間是乙個絕對時間,所以當伺服器與客戶端時間偏差較大時,就會導致快取混亂。
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次的記錄中,印象裡只有一次準點,因此,在我印象裡 東航準點也是小概率事件,所以,除非萬不得已,我不坐東航的航班。從今年五一到現在,今天是第三次坐東航的航班,次次晚點...