一文總結HTTP緩存

緩存是一個很大的話題,本文只是講述HTTP緩存。

HTTP

瀏覽器緩存機制

HTTP 頭信息控制緩存
大致分爲兩種:強緩存和協商緩存。強緩存如果命中緩存不需要和服務器端發生交互,而協商緩存不管是否命中都要和服務器端發生交互,強制緩存的優先級高於協商緩存。

兩類緩存規則的不同,強制緩存如果生效,不需要再和服務器發生交互,而對比緩存不管是否生效,都需要與服務端發生交互。

匹配流程:
在這裏插入圖片描述

強緩存

可以理解爲無須驗證的緩存策略。響應頭包括兩種字段 HTTP/1.0 Expires和HTTP/1.1 Cache-Control。Cache-Control 比 Expires 優先級更高。

Expires

Expires 指緩存過期的時間。Expires 存在於 。到期時間是由服務端生成的,客戶端時間可能跟服務端時間有誤差,會導致緩存命中的誤差。

Cache-Control

Cache-Control 可以由多個字段組合而成,多個指令以逗號分隔。分客戶端和服務端
客戶端可以在HTTP請求中使用的標準 Cache-Control 指令。

Cache-control: max-age=<seconds>
Cache-control: max-stale[=<seconds>]
Cache-control: min-fresh=<seconds>
Cache-control: no-cache 
Cache-control: no-store
Cache-control: no-transform
Cache-control: only-if-cached

服務器可以在響應中使用的標準 Cache-Control 指令。

Cache-control: must-revalidate
Cache-control: no-cache
Cache-control: no-store
Cache-control: no-transform
Cache-control: public
Cache-control: private
Cache-control: proxy-revalidate
Cache-control: max-age=<seconds>
Cache-control: s-maxage=<seconds>

cache-control參數講解

  • max-age 指定一個緩存有效時間長度,單位s。後續需要使用這個資源,瀏覽器不會發出 HTTP 請求,而是直接使用本地緩存的文件
  • s-maxage 同 max-age,覆蓋 max-age、Expires,但僅適用於共享緩存,在私有緩存中被忽略
  • public 響應可以被任何對象(客戶端、代理服務器等)緩存
  • private 默認值,響應只能被單個用戶緩存,非共享,不能被代理服務器緩存
  • no-cache 需要使用對比緩存來驗證緩存數據
  • no-store 禁止緩存,每次請求都要向服務器重新獲取數據。強制緩存,對比緩存都將失效
  • must-revalidate
  • proxy-revalidate
  • no-transform

注:
拓展緩存指令不是核心HTTP緩存標準文檔的一部分,使用前請注意檢查兼容性!

Cache-control: immutable 
Cache-control: stale-while-revalidate=<seconds>
Cache-control: stale-if-error=<seconds>

怎樣決定一個資源的Cache-Control策略呢?參考定義最佳 Cache-Control 策略
在這裏插入圖片描述

Pragma

存在於HTTP/1.0版本中,只有一種值Pragema:no-cache, 防止頁面被緩存,等價於HTTP/1.1中Cache-Control:no-cache

協商緩存

對比緩存,服務端下發的緩存時間到期,並不意味着資源內容發生改變,如果本地資源和服務器上的資源沒有差異,實際上沒有必要再次請求。客戶端和服務器端通過某種驗證機制驗證當前請求資源是否可以使用緩存。
瀏覽器第一次請求數據之後會將數據和響應頭部的緩存標識存儲起來。再次請求時會帶上存儲的頭部字段,服務器端驗證是否可用。返回 304 Not Modified,代表資源沒有發生改變可以使用緩存的數據,獲取新的過期時間。返回 200 則需要重新請求一遍資源並替換舊資源。

Last-modified/If-Modified-Since

Last-modified: 服務器端資源的最後修改時間,響應頭部會帶上這個標識。第一次請求之後,瀏覽器記錄這個時間,再次請求時,請求頭部帶上 If-Modified-Since 即爲之前記錄下的時間。服務器端收到帶 If-Modified-Since 的請求後會去和資源的最後修改時間對比。若修改過就返回最新資源,狀態碼 200,若沒有修改過則返回 304。
注意:如果響應頭中有 Last-modified 而沒有 Expire 或 Cache-Control 時,瀏覽器會有自己的算法來推算出一個時間緩存該文件多久,不同瀏覽器得出的時間不一樣,所以 Last-modified 要配合 Expires/Cache-Control 使用。

Etag/If-None-Match

Etag,即Entity Tag,由服務器端上生成的一段 hash 字符串,生成規則由服務器決定(比如根據資源的索引節(INode),大小(Size)和最後修改時間(MTime)進行Hash),對應着唯一資源。第一次請求時響應頭帶上 ETag,隨後的請求帶上 If-None-Match,服務器檢查 ETag,返回 304 或 200。優先級高於Last-modified/If-Modified-Since

last-modified 和 Etag 區別:

  1. 某些服務器不能精確得到資源的最後修改時間,這樣就無法通過最後修改時間判斷資源是否更新。
  2. Last-modified 只能精確到秒。
  3. 資源的最後修改時間改變,但內容不一定改變,使用 Last-modified 看不出內容沒有改變。
  4. Etag 的精度比 Last-modified 高,屬於強驗證,要求資源字節級別的一致,優先級高。如果服務器端有提供 ETag 的話,必須先對 ETag 進行 Conditional Request。

瀏覽器刷新

以Chrome爲例,有兩類(只需要看加載頁面時的第一個請求):

  1. 正常重新加載
    按下刷新按鈕(F5)或Ctrl + R會觸發瀏覽器的正常重新加載normal reload,瀏覽器會直接認爲緩存已經過期(可能緩存還沒有過期),帶如下請求頭:Cache-Control:max-age=0,此時瀏覽器會執行一次 Conditional GET。
  2. 強制重新加載
    強制刷新頁面(Ctrl+F5)或Ctrl+Shift+R快捷鍵觸發強制重新加載(Hard Reload),此時包括頁面本身在內的所有資源都不會使用緩存。在請求中加上字段:Cache-Control:no-cache或(和)Pragma:no-cache
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章