歡迎光臨
每天分享高質量文章

瀏覽器快取看這一篇就夠了

 

瀏覽器快取作為性能優化的重要一環,對於前端而言,重要性不言而喻。以前總是一知半解的,所以這次好好整理總結了一下。

1、快取機制

首先我們來總體感知一下它的匹配流程,如下:

  1. 瀏覽器發送請求前,根據請求頭的expires和cache-control判斷是否命中(包括是否過期)強快取策略,如果命中,直接從快取獲取資源,並不會發送請求。如果沒有命中,則進入下一步。
  2. 沒有命中強快取規則,瀏覽器會發送請求,根據請求頭的last-modified和etag判斷是否命中協商快取,如果命中,直接從快取獲取資源。如果沒有命中,則進入下一步。
  3. 如果前兩步都沒有命中,則直接從服務端獲取資源。

 

 

2、強快取

 

強快取:不會向服務器發送請求,直接從快取中讀取資源。

 

2.1 強快取原理

 

強制快取就是向瀏覽器快取查找該請求結果,並根據該結果的快取規則來決定是否使用該快取結果的過程,強制快取的情況主要有三種(暫不分析協商快取過程),如下:

  • 第一次請求,不存在快取結果和快取標識,直接向服務器發送請求

 

  • 存在快取標識和快取結果,但是已經失效,強制快取是啊比,則使用協商快取(暫不分析)

 

 

  • 存在該快取結果和快取標識,且該結果尚未失效,強制快取生效,直接傳回該結果

 

 

那麼強制快取的快取規則是什麼?
當瀏覽器向服務器發起請求時,服務器會將快取規則放入HTTP響應報文的HTTP頭中和請求結果一起傳回給瀏覽器,控制強制快取的欄位分別是ExpiresCache-Control,其中Cache-Control優先級比Expires高。

2.1.1、 Expires

快取過期時間,用來指定資源到期的時間,是服務器端的具體的時間點。也就是說,Expires=max-age + 請求時間,需要和Last-modified結合使用。Expires是Web服務器響應訊息頭欄位,在響應http請求時告訴瀏覽器在過期時間前瀏覽器可以直接從瀏覽器快取取資料,而無需再次請求。

Expires 是 HTTP/1 的產物,受限於本地時間,如果修改了本地時間,可能會造成快取失效。

2.1.2、 Cache-Control

在HTTP/1.1中,Cache-Control是最重要的規則,主要用於控制網頁快取,主要取值為:

  • public:所有內容都將被快取(客戶端和代理服務器都可快取)
  • private:所有內容只有客戶端可以快取,Cache-Control的預設取值
  • no-cache:客戶端快取內容,但是是否使用快取則需要經過協商快取來驗證決定
  • no-store:所有內容都不會被快取,即不使用強制快取,也不使用協商快取
  • max-age=xxx (xxx is numeric):快取內容將在xxx秒後失效

需要註意的是,no-cache這個名字有一點誤導。設置了no-cache之後,並不是說瀏覽器就不再快取資料,只是瀏覽器在使用快取資料時,需要先確認一下資料是否還跟服務器保持一致,也就是協商快取。而no-store才表示不會被快取,即不使用強制快取,也不使用協商快取

2.1.3、設置

強快取需要服務端設置expirescache-control
nginx代碼參考,設置了一年的快取時間:

location ~ .*\.(ico|svg|ttf|eot|woff)(.*) {
  proxy_cache               pnc;
  proxy_cache_valid         200 304 1y;
  proxy_cache_valid         any 1m;
  proxy_cache_lock          on;
  proxy_cache_lock_timeout  5s;
  proxy_cache_use_stale     updating error timeout invalid_essay-header http_500 http_502;
  expires                   1y;
}

瀏覽器的快取存放在哪裡,如何在瀏覽器中判斷強制快取是否生效?這就是下麵我們要講到的from disk cachefrom memory cache

 

2.2、from disk cache和from memory cache

細心地同學在開發的時候應該註意到了Chrome的網絡請求的Size會出現三種情況from disk cache(磁盤快取)from memory cache(記憶體快取)、以及資源大小數值。

狀態 型別 說明
200 form memory cache 不請求網絡資源,資源在記憶體當中,一般腳本、字體、圖片會存在記憶體當中
200 form disk ceche 不請求網絡資源,在磁盤當中,一般非腳本會存在記憶體當中,如css等
200 資源大小數值 從服務器下載最新資源
304 報文大小 請求服務端發現資源沒有更新,使用本地資源

瀏覽器讀取快取的順序為memory –> disk。
以訪問https://github.com/xiangxingchen/blog為例
我們第一次訪問時

https://github.com/xiangxingchen/blog

 

關閉標簽頁,再此打開

https://github.com/xiangxingchen/blog

F5掃清時

 

簡單的對比一下

 

3、協商快取

協商快取就是強制快取失效後,瀏覽器攜帶快取標識向服務器發起請求,由服務器根據快取標識決定是否使用快取的過程,主要有以下兩種情況:

  • 協商快取生效,傳回304和Not Modified

 

  • 協商快取失效,傳回200和請求結果

 

3.1、Last-Modified和If-Modified-Since

 

  1. 瀏覽器首先發送一個請求,讓服務端在response essay-header中傳回請求的資源上次更新時間,就是last-modified,瀏覽器會快取下這個時間。
  2. 然後瀏覽器再下次請求中,request essay-header中帶上if-modified-since:[儲存的last-modified的值]。根據瀏覽器發送的修改時間和服務端的修改時間進行比對,一致的話代表資源沒有改變,服務端傳回正文為空的響應,讓瀏覽器中快取中讀取資源,這就大大減小了請求的消耗。

由於last-modified依賴的是儲存的絕對時間,還是會出現誤差的情況:

  1. 儲存的時間是以秒為單位的,1秒內多次修改是無法捕捉到的;
  2. 各機器讀取到的時間不一致,就有出現誤差的可能性。為了改善這個問題,提出了使用etag。

     

3.2、ETag和If-None-Match

etaghttp協議提供的若干機制中的一種Web快取驗證機制,並且允許客戶端進行快取協商。生成etag常用的方法包括對資源內容使用抗碰撞散列函式,使用最近修改的時間戳的哈希值,甚至只是一個版本號。 和last-modified一樣.

  • 瀏覽器會先發送一個請求得到etag的值,然後再下一次請求在request essay-header中帶上if-none-match:[儲存的etag的值]
  • 通過發送的etag的值和服務端重新生成的etag的值進行比對,如果一致代表資源沒有改變,服務端傳回正文為空的響應,告訴瀏覽器從快取中讀取資源。

etag能夠解決last-modified的一些缺點,但是etag每次服務端生成都需要進行讀寫操作,而last-modified只需要讀取操作,從這方面來看,etag的消耗是更大的。

二者對比

  • 精確度上:Etag要優於Last-Modified
  • 優先級上:服務器校驗優先考慮Etag
  • 性能上:Etag要遜於Last-Modified

 

4、用戶行為對瀏覽器快取的影響

 

  1. 打開網頁,地址欄輸入地址: 查找 disk cache 中是否有匹配。如有則使用;如沒有則發送網絡請求。
  2. 普通掃清 (F5):因為 TAB 並沒有關閉,因此 memory cache 是可用的,會被優先使用(如果匹配的話)。其次才是 disk cache
  3. 強制掃清 (Ctrl + F5):瀏覽器不使用快取,因此發送的請求頭部均帶有 Cache-control:no-cache(為了兼容,還帶了 Pragma:no-cache),服務器直接傳回 200 和最新內容。

 

5、總結

 

    赞(0)

    分享創造快樂