簡易筆記:瀏覽器緩存策略

HTTP頭信息

首先咱們從資源被請求時,請求行爲和資源緩存的不一樣來看下HTTP頭信息的表現:html

資源的首次請求: node

頁面刷新-資源緩存未過時: web

頁面刷新-資源緩存已過時-資源未變動: npm

頁面刷新-資源緩存已過時-資源已變動: json

資源被再次請求時-緩存未過時: segmentfault

緩存策略

當瀏覽器請求資源文件時,默認會將源資文件緩存到本地以便重複使用,加快網頁的加載速度。瀏覽器

瀏覽器的資源緩存分爲 from disk cachefrom memory cache 兩類。當首次訪問網頁時,資源文件被緩存在內存中,同時也會在本地磁盤中保留一份副本。當用戶刷新頁面,若是緩存的資源沒有過時,那麼直接從內存中讀取並加載。當用戶關閉頁面後,當前頁面緩存在內存中的資源被清空。當用戶再一次訪問頁面時,若是資源文件的緩存沒有過時,那麼將從本地磁盤進行加載並再次緩存到內存之中。緩存

服務器能夠經過Response Headers使用 expirescache-control 設置一個有效的過時時間,當瀏覽器再次請求資源時會判斷本地緩存是否已過時:性能優化

  1. 若是沒有過時那麼直接從本地緩存讀取,不會產生http請求,此爲 強緩存
  2. 若是已過時,那麼瀏覽器將從新向服務器請求資源,這一過程每每伴隨着 緩存檢測

expires

這是HTTP1.0版本的產物,屬於 Response Headers,使用一個UTC格式的日期時間字符串表示資源的過時時間。服務器

使用 expires 設置的過時時間是以服務器時間爲準的,它可能跟瀏覽器時間不一致,不一樣時區也會存在影響。

cache-control

這是HTTP1.1版本的產物,屬於 Response Headers,提供更多詳細的緩存策略,能夠根據三種不一樣性質經過逗號進行組合使用:

  1. 是否不使用緩存: cache-control: no-store/no-cache/must-revalidate
  2. 是否爲私有緩存: cache-control:public/private
  3. 設置過時時間: cache-control: max-age/s-maxage

是否不使用緩存:

  1. must-revalidate : 當本地的資源緩存沒有過時前,使用本地緩存;當本地資源緩存已過時時,須要進行緩存檢測(默認值)。
  2. no-cache : 無論本地的資源緩存是否過時,都須要進行緩存檢測。
  3. no-store : 禁止瀏覽器緩存資源,每次請求資源都去服務器從新下載。

是否爲私有緩存:

  1. public : 公共緩存,表示瀏覽器和代理服務器均可以設置緩存(默認值)。
  2. private : 私有緩存,僅瀏覽器設置緩存。

設置過時時間:

  1. max-age:使用 cache-control: max-age=60 的形式表示本地緩存的資源將在xx秒以後過時,單位爲秒,會覆蓋 Expires 的設置。
  2. s-maxage : 使用方式同 max-age ,在public設置下有效,針對共享緩存(代理服務器)有效。

使用 max-age 的優勢在於設置的過時時間是一個相對於瀏覽器的時間,不受服務器和瀏覽器時間不一致的影響,也不會由於時區的不一樣而受到影響。

啓發式緩存

當資源文件的 Response Headers 中帶有 last-modified 字段,可是卻缺乏 expirescache-control 用來表示資源緩存的過時時間的字段,這個時候瀏覽器會使用啓發式緩存來確認該資源緩存的過時時間:

瀏覽器會根據 datelast-modified 之間的時間差值的10%來做爲資源緩存的過時時間。

緩存檢測

當瀏覽器從新向服務器請求資源時,若是原先的 Response Headers 中存在 last-modified 或者 etag 信息,那麼在 Request Headers 中會經過 if-modified-sinceif-none-match 將以前的信息帶給服務器進行檢測。若是服務器資源相對於本地的資源緩存沒有發生變動,那麼將會返回304狀態碼,表示資源未更新,讓瀏覽器使用本地的資源緩存,這就是 協商緩存

若是原先的 Response Headers 中沒有 last-modifiedetag 信息,那麼將從服務器從新下載資源文件。

last-modified 和 if-modified-since

這兩個字段都是HTTP1.0版本的產物。

  1. last-modified: 屬於 Response Headers,表示資源最後一次修改的時間。

  2. if-modified-since: 屬於 Request Headers,用來判斷服務器端資源是否在該傳遞的時間以後作了修改,若是沒有修改那麼服務器將返回304狀態碼,讓瀏覽器使用資源緩存。

etag 和 if-none-match

這是HTTP1.1版本的產物。

  1. etag: 屬於 Response Headers,表示資源的惟一標識符,由服務器端生成。

  2. if-none-match: 屬於 Request Headers,用來判斷服務器資源是否與該傳遞的標識符不一致,若是一致則表示資源文件沒有修改過,服務器將返回304狀態碼,讓瀏覽器使用資源緩存。會覆蓋 if-modified-since 的設置。

使用etag來判斷服務器端資源文件是否作了修改,主要有如下考慮:

  1. last-modified 只能精確到秒,而有些服務器資源可能在1秒內進行了屢次修改。
  2. 服務器資源文件,有些會定時自動生成,可是文件內容並無發生任何變動。

用戶行爲

瀏覽器的緩存策略還跟用戶的行爲有關:

  1. 當用戶從url地址欄回車訪問網頁時,強緩存和協商緩存都有效。
  2. 當用戶從頁面中點擊一個超連接訪問網頁時,強緩存和協商緩存都有效。
  3. 當用戶按F5刷新時,強緩存將無效,但會觸發協商緩存。不過在Firefox瀏覽器中,強緩存和協商緩存均無效。
  4. 當用戶按Ctrl+F5強制刷新時,強緩存和協商緩存都將無效,瀏覽器將向服務器從新並下載資源文件。

demo檢驗

爲了完全搞清楚瀏覽器的緩存策略,這裏提供了一個使用node http模塊構建的一個簡單服務器環境,經過自行設置Response Headers來預覽瀏覽器緩存的表現行爲。點擊下載資源包

下載資源包後,自行解壓,而後使用 npm install 命令安裝依賴,經過 node server 執行目錄下的server.js文件來啓動本地服務器,將會自動使用默認瀏覽器打開目錄下的 /pages/index/index.html 頁面。

以後能夠在cache.json配置文件的下圖所示的代碼中,對瀏覽器緩存涉及到的四個http字段進行編輯,修改完畢後保存並強制刷新瀏覽器頁面便可:

編輯說明:

  1. 設置相關字段爲false,則表示不設置相應的http字段;
  2. 對於Cache-Control字段的值,填寫其支持的策略組合便可;
  3. 對於Expires字段的值,按秒填寫數字便可;
  4. 對於Etag和Last-modified字段的值,設置爲true便可;

參考資源

  1. 完全理解瀏覽器緩存機制
  2. 透過瀏覽器看HTTP緩存
  3. 瀏覽器緩存機制剖析
  4. 完全弄懂 Http 緩存機制 - 基於緩存策略三要素分解法
  5. web性能優化之:no-cache與must-revalidate深刻探究
  6. 由memoryCache和diskCache產生的瀏覽器緩存機制的思考
相關文章
相關標籤/搜索