關於瀏覽器緩存我知道多少

原文連接:關於瀏覽器緩存我知道多少前端

歡迎star~git


在前端開發中,咱們在提到性能優化的時候總會提到一點:合理設置緩存。咱們該如何從這方面入手來考慮提升網站性能呢?github

前言

咱們都知道 HTML5 引入了應用程序緩存,能夠在沒有網絡的狀況下進行訪問,同時,HTML5 還引入了 storage 本地存儲。這些都屬於應用緩存。瀏覽器

本篇文章主要內容是和瀏覽器緩存相關的,也能夠說是 HTTP 緩存。緩存

什麼是瀏覽器緩存

MDN 上是這樣解釋瀏覽器緩存的:性能優化

A browser cache holds all document downloaded via HTTP by the user 。。。 without requiring an additional trip to the server.服務器

意思就是,瀏覽器緩存保存着用戶經過 HTTP 獲取的全部資源,再下一次請求時能夠避免重複向服務器發出多餘的請求。網絡

通俗的說,就是在你訪問過一次某個網站以後,這個站點的文字、圖片等全部資源都被下載到本地了,下次再訪問該網站時判斷是否知足緩存條件,若是知足就不用再花費時間去等待資源的獲取了。ide

瀏覽器緩存的分類

通常來講瀏覽器緩存能夠分爲兩類:性能

  • 強緩存
  • 協商緩存(對比緩存)

咱們須要知道的是,瀏覽器在加載資源時,會先判斷是否命中強緩存再驗證是命中協商緩存

其它的的具體細節,稍後會展開來講。

強緩存

瀏覽器在加載資源時,會先根據本地緩存資源的 header 中的信息判斷是否命中強緩存,若是命中則直接使用緩存中的資源不會再向服務器發送請求。

從圖中能夠看出,強緩存通常是這樣一個流程:

  1. 查看 header 頭中的 ExpireCache-control 來判斷是否知足規則;
  2. 若是知足規則,就返回緩存的數據;
  3. 若是不知足規則,就向服務器發送請求;
  4. 服務器返回數據;
  5. 將新數據存入緩存。

因此咱們主要就是關注 ExpireCache-control 這兩個字段。

Expire

一樣地,咱們看看MDN中如何解釋這個字段:

The Expires header contains the date/time after which the response is considered stale.

這個字段包含了一個時間,過了這個時間,響應將會失效。

也就是說,Expire 這個字段表示緩存到期時間,咱們來打開一個網站並查看 Response Header 看看這個字段:

Expires:Fri, 27 Oct 2017 07:55:30 GMT

可能在你查看這的時候發現時間不對啊,怎麼都已是過去了 ~

GMT 表示的是格林威治時間,和北京時間相差8小時。

上面的這個時間表示的是 2017年10月27日15:55:30

經過設置 Expire 來設置緩存有一個致命缺點:

能夠看出,這個是個絕對時間,也就是說,若是我修改了客戶端的本地時間,是否是就會致使判斷緩存失效了呢。

Cache-Control

既然不能設置絕對時間,那我就設置個相對時間唄。

HTTP/1.1 中,增長了一個字段 Cache-Control ,它包含一個 max-age 屬性,該字段表示資源緩存的最大有效時間,這就是一個相對時間。

Cache-Control:max-age=600

這個表示的就是最大有效時間是 600s ,對的,它的單位是秒。

Cache-Control 除了 max-age 屬性以外還有一些屬性:

  • no-cache:須要進行協商緩存,發送請求到服務器確認是否使用緩存。
  • no-store:禁止使用緩存,每一次都要從新請求數據。
  • public:默認設置。
  • private:不能被多用戶共享。

如今基本上都會同時設置 ExpireCache-ControlCache-Control 的優先級別更高。

協商緩存

當強緩存沒有命中的時候,瀏覽器會發送一個請求到服務器,服務器根據請求頭中的部分信息來判斷是否命中緩存。若是命中,則返回 304 ,告訴瀏覽器資源未更新,可以使用本地的緩存。

從圖中能夠看出,協商緩存通常是這樣一個流程:

  1. 把資源標識,好比 If-Modify-SinceEtag 發送到服務器,確認資源是否更新;
  2. 若是資源未更新,請求響應返回的http狀態爲 304 而且會顯示一個 Not Modified 的字符串,告訴瀏覽器使用本地緩存;
  3. 若是資源已經更新,返回新的數據;
  4. 將新數據存入緩存。

Last-Modified,If-Modified-Since

瀏覽器第一次請求資源的時候,服務器返回的 header 上會帶有一個 Last-Modified 字段,表示資源最後修改的時間。

Last-Modified: Fri, 27 Oct 2017 07:55:30 GMT

一樣的,這是一個 GMT 的絕對時間。

當瀏覽器再次請求該資源時,請求頭中會帶有一個 If-Modified-Since 字段,這個值是第一次請求返回的 Last-Modified 的值。服務器收到這個請求後,將 If-Modified-Since 和當前的 Last-Modified 進行對比。若是相等,則說明資源未修改,返回 304,瀏覽器使用本地緩存。

well,這個方法也是有缺點的:

  • 最小單位是秒。也就是說若是我短期內資源發生了改變,Last-Modified 並不會發生變化;
  • 週期性變化。若是這個資源在一個週期內修改回原來的樣子了,咱們認爲是能夠使用緩存的,可是 Last-Modified 可不這樣認爲。

因此,後來又引入一個 Etag

Etag

Etag 通常是由文件內容 hash 生成的,也就是說它能夠保證資源的惟一性,資源發生改變就會致使 Etag 發生改變。

一樣地,在瀏覽器第一次請求資源時,服務器會返回一個 Etag 標識。當再次請求該資源時, 會經過 If-no-match 字段將 Etag 發送回服務器,而後服務器進行比較,若是相等,則返回 304 表示未修改。

Last-ModifiedEtag 是能夠同時設置的,服務器會優先校驗 Etag,若是 Etag 相等就會繼續比對 Last-Modified,最後纔會決定是否返回 304

總結

當瀏覽器再次訪問一個已經訪問過的資源時,它會這樣作:

  1. 看看是否命中強緩存,若是命中,就直接使用緩存了;
  2. 若是沒有命中強緩存,就發請求到服務器檢查是否命中協商緩存;
  3. 若是命中協商緩存,服務器會返回 304 告訴瀏覽器使用本地緩存;
  4. 不然,返回最新的資源。
相關文章
相關標籤/搜索