天天看點

浏覽器緩存機制一 前言二 優先級三 Memory Cache四 Disk Cache五 緩存的應用模式

一 前言

  基本的網絡請求有三個步驟:請求 ⇒ 處理 ⇒ 響應。“處理”階段的優化主要集中在後端,前端緩存則主要集中在“請求”和“響應”上。在“請求”步驟中,浏覽器也可以通過存儲結果的方式直接使用資源,省去了發送請求;而“響應”步驟需要浏覽器和伺服器共同配合,通過減少響應内容來縮短傳輸時間。

浏覽器緩存機制一 前言二 優先級三 Memory Cache四 Disk Cache五 緩存的應用模式

二 優先級

Memory Cache > Disk Cache > 網絡請求

三 Memory Cache

  Memory Cache,顧名思義,記憶體緩存,關閉浏覽器TAB頁則緩存丢失,是浏覽器為了加快讀取緩存速度而進行的自身的優化行為,多個相同請求隻會被請求最多一次。幾乎所有的請求資源 都能進入 memory cache,在從 memory cache 擷取緩存内容時,浏覽器會忽視例如 max-age=0, no-cache 等頭部配置,如果确實不需要某個請求被緩存到Memory Cache,則需設定響應頭 “Cache-Control: no-cache”,比如後端的查詢服務,這樣可以確定每次都會去伺服器查詢最新資料。

四 Disk Cache

  Disk Cache,顧名思義,硬碟緩存,緩存于檔案系統中。disk cache 會嚴格根據 HTTP 頭資訊中的各類字段來判定哪些資源可以緩存,哪些資源不可以緩存;哪些資源是仍然可用的,哪些資源是過時需要重新請求的。當命中緩存之後,浏覽器會從硬碟中讀取資源,雖然比起從記憶體中讀取慢了一些,但比起網絡請求還是快了不少的。絕大部分的緩存都來自 disk cache。過時的緩存會被浏覽器自動清理。我們平時所說的“強制緩存”和“協商緩存”都屬于Disk Cache。

4.1 強制緩存

  強制緩存就是向浏覽器緩存查找該請求結果,并根據該結果的緩存規則來決定是否使用該緩存結果的過程,強制緩存的情況主要有三種:

   (1) 不存在該緩存結果和緩存辨別,強制緩存失效,則直接向伺服器發起請求并緩存

   (2) 存在該緩存結果和緩存辨別,但是結果已經失效,強制緩存失效,則使用協商緩存

   (3) 存在該緩存結果和緩存辨別,且該結果沒有還沒有失效,強制緩存生效,直接傳回結果

  強制緩存直接減少請求數,是提升最大的緩存政策。它的優化涵蓋了網絡請求三步驟中的全部。可以設定強制緩存的響應頭有兩個:

  • Expires:

      Expires是HTTP/1.0控制網頁緩存的字段,其值為伺服器傳回該請求的結果緩存的到期時間,是一個絕對時間。再次發送請求時,如果用戶端的時間小于Expires的值時,直接使用緩存結果。如:

  但是,這個字段設定時有兩個缺點:

  • 由于是絕對時間,使用者可能會将用戶端本地的時間進行修改,而導緻浏覽器判斷緩存失效,重新請求該資源。此外,即使不考慮自行修改,時差或者誤差等因素也可能造成用戶端與服務端的時間不一緻,緻使緩存失效。
  • 寫法太複雜了。表示時間的字元串多個空格,少個字母,都會導緻非法屬性進而設定失效。
  • Cache-Control

      在 HTTP/1.1 中,增加了一個字段Cache-Control,該字段表示資源緩存的最大有效時間,是一個相對時間,在該時間内,用戶端不需要向伺服器發送請求。如:

  下面列舉一些 Cache-control 字段常用的值:

  • public: 所有内容都可以被緩存,包括用戶端和代理伺服器,如CDN
  • private: 所有内容隻有用戶端可以緩存,代理伺服器不能緩存,預設值
  • no-cache: 協商緩存,是否使用緩存取決于請求的響應狀态碼,304則使用緩存
  • no-store: 不緩存,包括Memory Cache和Disk Cache
  • max-age: 最大有效時間,機關:秒

  注:在HTTP 1.0 中如果不想使用緩存,需設定 “Program: no-cache” (非标準規範)。

  Cache-control 的優先級高于 Expires,為了相容 HTTP/1.0 和 HTTP/1.1,項目中可能兩個字段都會設定。

4.2 協商緩存

  協商緩存就是強制緩存失效後,浏覽器攜帶緩存辨別向伺服器發起請求,由伺服器根據緩存辨別決定是否使用緩存的過程,主要有以下兩種情況:

   (1) 協商緩存生效,傳回304,沒有響應體

   (2) 協商緩存失敗,傳回200和請求結果并更新緩存

   協商緩存有兩組響應頭:

4.2.1 Last-Modified & If-Modified-Since

  (1) Last-Modified是伺服器響應請求時,傳回該資源檔案在伺服器最後被修改的時間

  (2) If-Modified-Since則是用戶端再次發起該請求時,攜帶上次請求傳回的Last-Modified值,通過此字段值告訴伺服器該資源上次請求傳回的最後被修改時間。伺服器收到該請求,發現請求頭含有If-Modified-Since字段,則會根據If-Modified-Since的字段值與該資源在伺服器的最後被修改時間做對比,若伺服器的資源最後被修改時間大于If-Modified-Since的字段值,則重新傳回資源,狀态碼為200;否則則傳回304,代表資源無更新,可繼續使用緩存檔案

  但是,這種方式存在缺陷,如果檔案是通過伺服器動态生成的,那麼該方法的更新時間永遠是生成的時間,盡管檔案可能沒有變化,是以起不到緩存的作用,于是,有了下面的一組響應頭。

4.2.2 Etag & If-None-Match

   (1) Etag是伺服器響應請求時,傳回目前資源檔案的一個唯一辨別(由伺服器生成,如資源檔案的Hash或散列值)

   (2) If-None-Match是用戶端再次發起該請求時,攜帶上次請求傳回的唯一辨別Etag值,通過此字段值告訴伺服器該資源上次請求傳回的唯一辨別值。伺服器收到該請求後,發現該請求頭中含有If-None-Match,則會根據If-None-Match的字段值與該資源在伺服器的Etag值做對比,一緻則傳回304,代表資源無更新,繼續使用緩存檔案;不一緻則重新傳回資源檔案并緩存,狀态碼為200

   注:Etag / If-None-Match優先級高于Last-Modified / If-Modified-Since,同時存在則隻有Etag / If-None-Match生效

五 緩存的應用模式

5.2 不常變化的資源

  不常變化的資源,可以将max-age設定為一個合理的值,進而使用強制緩存。而為了解決更新的問題,就需要在檔案名(或者路徑)中添加 hash, 版本号等動态字元,通過更改動态字元,達到更改引用 URL 的目的,進而讓之前的強制緩存失效 。

5.2 經常變化的資源

Cache-Control: no-cache
           

  經常變化的資源,可以使用協商緩存。通過上述設定使浏覽器每次請求都找伺服器驗證緩存是否有效。

5.3 不需要緩存的資源

Cache-Control: no-store
           

  不需要緩存的資源,可以通過上述設定使浏覽器每次請求都從伺服器擷取最新的資料,比如後端服務請求。