瀏覽器HTTP緩存機制

介紹HTTP緩存之前先簡單說一下Web緩存

Web緩存是一種保存Web資源副本並在下次請求時直接使用該副本的技術。

       Web緩存可以分爲這幾種:瀏覽器緩存、CDN緩存、服務器緩存、數據庫數據緩存 。因爲可能會直接使用副本免於重新發送請求或者僅僅確認資源沒變無需重新傳輸資源實體,Web緩存可以減少延遲加快網頁打開速度、重複利用資源減少網絡帶寬消耗、降低請求次數或者減少傳輸內容從而減輕服務器壓力。

       這篇文章主要討論和前端密切相關的瀏覽器HTTP緩存機制。瀏覽器HTTP緩存可以分爲強緩存協商緩存強緩存協商緩存最大也是最根本的區別是:強緩存命中的話不會發請求到服務器(比如chrome中的200 from memory cache),協商緩存一定會發請求到服務器,通過資源的請求首部字段驗證資源是否命中協商緩存,如果協商緩存命中,服務器會將這個請求返回,但是不會返回這個資源的實體,而是通知客戶端可以從緩存中加載這個資源(304 not modified)。
強緩存與協商緩存

瀏覽器HTTP緩存由HTTP報文的首部字段決定

報文結構

控制強緩存的字段按優先級介紹

1.Pragma
       Pragma是HTTP/1.1之前版本遺留的通用首部字段,僅作爲於HTTP/1.0的向後兼容而使用。雖然它是一個通用首部,但是它在響應報文中時的行爲沒有規範,依賴於瀏覽器的實現。RFC中該字段只有no-cache一個可選值,會通知瀏覽器不直接使用緩存,要求向服務器發請求校驗新鮮度。因爲它優先級最高,當存在時一定不會命中強緩存。

2.Cache-Control
       Cache-Control是一個通用首部字段,也是HTTP/1.1控制瀏覽器緩存的主流字段。和瀏覽器緩存相關的是如下幾個響應指令:

指令 參數 說明
private 表明響應只能被單個用戶緩存,不能作爲共享緩存(即代理服務器不能緩存它)
public 可省略 表明響應可以被任何對象(包括:發送請求的客戶端,代理服務器,等等)緩存
no-cache 可省略 緩存前必需確認其有效性
no-store 不緩存請求或響應的任何內容
max-age=[s] 必需 響應的最大值

- max-age(單位爲s)設置緩存的存在時間,相對於發送請求的時間。只有響應報文首部設置Cache-Control爲非0的max-age或者設置了大於請求日期的Expires(下文會講)纔有可能命中強緩存。當滿足這個條件,同時響應報文首部中Cache-Control不存在no-cacheno-store且請求報文首部不存在Pragma字段,纔會真正命中強緩存。以下所有圖片均爲刷新(command+R)的截圖。

響應報文首部no-cache和max-age同時存在
響應報文首部no-store和max-age同時存在
請求報文首部Pragma,響應報文首部max-age

  • no-cache 表示請求必須先與服務器確認緩存的有效性,如果有效才能使用緩存(協商緩存),無論是響應報文首部還是請求報文首部出現這個字段均一定不會命中強緩存。Chrome硬性重新加載(Command+shift+R)會在請求的首部加上Pragma:no-cacheCache-Control:no-cache
  • no-store 表示禁止瀏覽器以及所有中間緩存存儲任何版本的返回響應,一定不會出現強緩存和協商緩存,適合個人隱私數據或者經濟類數據。
  • public 表明響應可以被瀏覽器、CDN等等緩存。
  • private 響應只作爲私有的緩存,不能被CDN等緩存。如果要求HTTP認證,響應會自動設置爲private

3.Expires
       Expires是一個響應首部字段,它指定了一個日期/時間,在這個時間/日期之前,HTTP緩存被認爲是有效的。無效的日期比如0,表示這個資源已經過期了。如果同時設置了Cache-Control響應首部字段的max-age,則Expires會被忽略。它也是HTTP/1.1之前版本遺留的通用首部字段,僅作爲於HTTP/1.0的向後兼容而使用。

控制協商緩存的字段

1.Last-Modified/If-Modified-Since
       If-Modified-Since是一個請求首部字段,並且只能用在GET或者HEAD請求中。Last-Modified是一個響應首部字段,包含服務器認定的資源作出修改的日期及時間。當帶着If-Modified-Since頭訪問服務器請求資源時,服務器會檢查Last-Modified,如果Last-Modified的時間早於或等於If-Modified-Since則會返回一個不帶主體的304響應,否則將重新返回資源。

If-Modified-Since: , :: GMT
Last-Modified: , :: GMT

2.ETag/If-None-Match
       ETag是一個響應首部字段,它是根據實體內容生成的一段hash字符串,標識資源的狀態,由服務端產生。If-None-Match是一個條件式的請求首部。如果請求資源時在請求首部加上這個字段,值爲之前服務器端返回的資源上的ETag,則當且僅當服務器上沒有任何資源的ETag屬性值與這個首部中列出的時候,服務器纔會返回帶有所請求資源實體的200響應,否則服務器會返回不帶實體的304響應。ETag優先級比Last-Modified高,同時存在時會以ETag爲準。

If-None-Match:
If-None-Match: , , …
If-None-Match: *

ETag與If-None-Match

ETag屬性之間的比較採用的是弱比較算法,即兩個文件除了每個比特都相同外,內容一致也可以認爲是相同的。例如,如果兩個頁面僅僅在頁腳的生成時間有所不同,就可以認爲二者是相同的。

因爲ETag的特性,所以相較於Last-Modified有一些優勢:

    1.  某些情況下服務器無法獲取資源的最後修改時間
    2.  資源的最後修改時間變了但是內容沒變,使用ETag可以正確緩存
    3.  如果資源修改非常頻繁,在秒以下的時間進行修改,Last-Modified只能精確到秒

整體流程

整體流程

求贊,歡迎訪問我的博客

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章