http 快取 筆記
http 快取,有時後靜態資源沒更新的情況下,不需要每次都去伺服器獲取,減少資源的請求。
Http 報文中與快取相關的首部欄位
1. 通用首部欄位(就是請求報文和響應報文都能用上的欄位)
2. 請求首部欄位
3. 響應首部欄位
4. 實體首部欄位
廢棄欄位
http 1.0 版本有 pragma 和 expires 欄位。現在欄位被拋棄了,但是為了向下相容,還是有很多網站有帶上這兩個欄位。
pragma
pragma 只有no-cache 一個屬性值,和 Cache-Contorl 中的 no-cache 一致。
強快取
Expires:的值對應一個GMT(格林尼治時間),比如“Fri, 27 May 2022 12:02:01 GMT”來告訴瀏覽器資源快取過期的絕對時間,如果還沒過該時間點則不發請求。響應報文中Expires定義的快取時間是相對伺服器上的時間而言的,客戶端上的時間跟伺服器上的時間不一致(特別是使用者修改了自己電腦的系統時間)
Cache-Control: 是http/1.1中新增的屬性,在請求頭和響應頭中都可以使用。其中 max-age 值為相對時間,例 Cache-Control:max-age=700, 是相對響應報文中的 Date 欄位 700秒,這樣就算客戶端跟伺服器的時間不一致,也沒什麼問題了。以下都是 Cache-Control 欄位值
Date 欄位是伺服器傳送該資源響應報文的時間(GMT格式),連續F5刷新發現 Date 的值都沒變化,則說明你當前請求是命中了代理伺服器的快取。
Cache-Control 允許自由組合可選值 Cache-Control: max-age=3600, must-revalidate
組合的方式也會有些限制,比如 no-cache 就不能和 max-age、min-fresh、max-stale 一起搭配使用。
組合的形式還能做一些瀏覽器行為不一致的相容處理。例如在IE我們可以使用 no-cache 來防止點選“後退”按鈕時頁面資源從快取載入,但在 Firefox 中,需要使用 no-store 才能防止歷史回退時瀏覽器不從快取中去讀取資料,故我們在響應報頭加上如下組合值即可做相容處理:Cache-Control: no-cache, no-store
可快取性
public
表明響應可以被任何物件(包括:傳送請求的客戶端,代理伺服器,等等)快取。private
表明響應只能被單個使用者快取,不能作為共享快取(即代理伺服器不能快取它)no-cache
不使用強快取,需要與伺服器驗協商快取驗證。no-store
快取不應儲存有關客戶端請求或伺服器響應的任何內容,即不使用任何快取。
過期
max-age=<seconds>
快取儲存的最大週期,超過這個週期被認為過期。s-maxage=<seconds>
設定共享快取。會覆蓋max-age
和expires
,私有快取會忽略它max-stale[=<seconds>]
客戶端願意接收一個已經過期的資源,可以設定一個可選的秒數,表示響應不能已經過時超過該給定的時間。min-fresh=<seconds>
客戶端希望在指定的時間內獲取最新的響應
重新驗證和重新載入
must-revalidate
如頁面過期,則去伺服器進行獲取。proxy-revalidate
與must-revalidate
作用相同,但是用於共享快取。
其他
only-if-cached
不進行網路請求,完全只使用快取。no-transform
不得對資源進行轉換和轉變。例如,不得對影象格式進行轉換。
若報文中同時出現了 Pragma、Expires 和 Cache-Control, 優先順序為 Expires < Pragma < Cache-Control 。
協商快取
強緩會存在這樣的問題:
1、快取時間到了,但是其實伺服器資源並未更新,再次請求一次,如果檔案大的話會浪費頻寬和時間
2、快取時間未到,伺服器資源更新了,客戶端未請求最新資源
所以Http1.1 新增以下幾個欄位
Last-Modified / If-Modified-Since
- 在伺服器在響應請求時,會通過
Last-Modified
告訴瀏覽器資源的最後修改時間。 - 瀏覽器再次請求伺服器的時候,請求頭會包含 if
-Modified-Since
欄位,後面跟著在伺服器傳過來的 Last-Modified 的最後修改時間。 - 服務端收到此請求頭髮現有
if-Modified-Since
,則與被請求資源的最後修改時間進行對比,如果一致則返回 304 和響應報文頭,瀏覽器只需要從快取中獲取資訊即可。如果已經修改,那麼開始傳輸響應一個整體,伺服器返回:200 OK;
Last-Modified 時間精度為1秒,如果1秒內更新,伺服器資源更新了,導致資源不準確,或伺服器資源更新了,但是資源的內容其實沒改變,這時候就又發生了沒必要的請求,所以出現了 ETag
ETag / If-None-Match
1、伺服器會通過某種演算法,給資源計算得出一個唯一標誌符(比如md5標誌,雜湊值)
,資源內容變化都會導致 ETag 變化,跟最後修改時間沒有關係,ETag
可以保證每一個資源是唯一的。
2、在瀏覽器發起請求,瀏覽器的請求報文頭會包含 If-None-Match
欄位,其值為上次返回的Etag
傳送給伺服器,
3、伺服器接收到次報文後發現 If-None-Match
則與被請求資源的唯一標識進行對比。如果相同說明資源內容沒有修改,則響應返 304,瀏覽器直接從快取中獲取資料資訊。如果不同則
說明資源被改動過,則響應整個資源內容,返回狀態碼 200。
需要注意的是,如果資源是走分散式伺服器(比如CDN)儲存的情況,需要這些伺服器上計算ETag唯一值的演算法保持一致,才不會導致明明同一個檔案,在伺服器A和伺服器B上生成的ETag卻不一樣。
如果 Last-Modified 和 ETag 同時被使用,則要求它們的驗證都必須通過才會返回304;
如果 Expires 和 Cache-Control:max-age 都過期了,或 Cache-Contorl 為 no-cache,就會進入協商快取;
大多數瀏覽器在點選重新整理按鈕或按F5時會自行加上“Cache-Control:max-age=0”請求欄位,也就是跳過強快取;選中url位址列並按回車鍵(這樣不會被強行加上Cache-Control)。ctrl+F5 這是跳過強快取和協商快取,直接請求最新資源。
參考連結
https://www.cnblogs.com/vajoy/p/5341664.html https://juejin.cn/post/7060876277376352293