瀏覽器快取機制(詳)

GaoYanbing發表於2024-10-15

參考:

https://blog.csdn.net/qq_40147756/article/details/135110801

1,快取的分類
1.1,按快取位置
1,Service Worker

MDN參考

它是執行在瀏覽器後臺的獨立執行緒,可以將它理解為是一個代理伺服器。可以攔截所有的網路請求,也可以快取資料。主要是為了建立有效的離線體驗,比如後臺同步,離線渲染,推送通知等。

它的快取機制也比較特殊,可以自由的控制:快取內容,匹配規則,讀取規則,有效期等。

實現快取的大致步驟:

註冊 Service Worker。
監聽 install 事件提前快取資源。
監聽 fetch 事件,攔截網路請求並返回已快取的資源。

在這裡插入圖片描述
2,Memory Cache

它是記憶體中的快取,主要快取當前頁面中已經抓取到的資源,例如已經下載的樣式、指令碼、圖片等,儲存一份資源的引用,以備下次使用。

注意,Memory Cache 是瀏覽器為了加快讀取快取速度而進行的自身的最佳化行為,不受開發者控制,也不受 HTTP Header 的約束,算是一個黑盒。

訪問頁面後,再次重新整理,可以看到很多資料來自記憶體快取:
在這裡插入圖片描述

特點:讀取速度快,但時效性很短,會隨著程序結束而釋放。比如關閉標籤頁,記憶體中的快取就被釋放了。

而因為計算機可使用的記憶體一般都比較小,作業系統對記憶體的使用會更精細化,所以可供瀏覽器使用的並不會很多。

作用:該快取機制保證了一個頁面有2個以上相同的資源請求時,實際最多隻會被請求一次,如上圖所示。
3,Disk Cache

重點

它是儲存在硬碟中的快取,是覆蓋面最大的快取機制,會根據 HTTP Header 中的欄位(Cache-Control等)來判斷:

哪些資源需要快取
哪些資源可以不請求直接使用
哪些資源已經過期需要重新請求

並且在跨站點的情況下,相同地址的資源一旦被硬碟快取下來,就不會再去請求資料。一般來說,絕大部分快取都來自 Disk Cache。

特點:讀取速度較慢,但時效性很好(可設定)。

因為時效性的原因,Disk Cache 也算是永續性儲存,所以也會面對容量增長的問題。

而瀏覽器解決這個問題,是透過特殊的演算法把 “最老的” 和 “最有可能過時” 的資源一個一個的刪除。
4,Push Cache

稱為推送快取或啟發式快取,是HTTP2 新增的內容。

上面3種快取都沒有命中時,它才會被使用,並且時效性很短,只在 session 會話中存在,會話結束就被釋放了。

這個我瞭解的不多,網上也沒有找到合適的文章,就不多做介紹了。

1.2,按快取型別

其實是對 Disk Cache 進行的分類。
強快取

當瀏覽器請求資源後,會優先訪問強快取。存在則返回,否則請求伺服器,響應後再次寫入強快取。

作用:直接減少請求數量,是提升最大的快取策略。透過快取最佳化網頁效能時是應該首先被考慮的。

實現:透過 HTTP Header 中的欄位:Expires 和 Cache-control。
Expires

是 HTTP 1.0 的欄位,表示快取到期的時間,是一個絕對時間(當前時間+快取時間)

Expires: Wed, 20 Dec 2023 23:09:07 GMT

1

在響應頭中設定該欄位,告訴瀏覽器在過期之前不要再次請求。

注意格林威治時間和本地時間的區別:

new Date() // Wed Dec 20 2023 23:09:07 GMT+0800 (中國標準時間)
new Date().toGMTString() // Wed, 20 Dec 2023 15:09:07 GMT

1
2

該欄位的缺點:

由於是絕對時間,使用者可以修改本地時間,導致瀏覽器判斷快取失效而重新請求資源。即便不考慮本地修改的問題,時間誤差等因素也會導致瀏覽器和伺服器之間的時間不一致,導致快取失效。
Cache-control

在已知 Expires 的缺點後,在 HTTP 1.1 中增加該欄位,是一個相對時間,表示資源快取的最大有效時間,該時間內不需要再次向伺服器傳送請求。

Cache-Control: max-age=3600

1

下面列舉一些 Cache-control 的常用值,更多的欄位參考 MDN

max-age,最大有效時間

must-revalidate(響應頭資訊),如果超過了 max-age 的時間,瀏覽器必須向伺服器傳送請求,驗證資源是有效性。

no-cache,客戶端會快取資源,但每次都得傳送請求驗證有效性,等價於 max-age=0 must-revalidate。

no-store,真正意義上的“不要快取”。所有內容都不走快取,包括強快取和協商快取。

private(預設值),所有的內容只有客戶端才可以快取,代理伺服器不能快取。

這些值可以混合使用,優先順序如下:(網圖,我翻譯了一下)
在這裡插入圖片描述

其他一些注意點:

在 HTTP 1.1 之前,如果想使用 no-cache,通常設定 Pragma: no-cache(這也是 Pragma 欄位唯一的取值)。但這個欄位只是瀏覽器約定俗成的實現,缺乏可靠性,只是作為相容欄位出現。
自 HTTP 1.1 開始,Expires 逐漸被 Cache-control 取代。而為了相容 HTTP 1.0 和 HTTP 1.1 ,實際上這2個欄位都會配置。

協商快取

當強快取超時失效後,就需要使用協商快取,有伺服器來決定快取資源是否失效(也就是強快取中的有效性判斷。)

伺服器資源為更新時,驗證請求返回 304,大致流程如下圖示:

而如果資源更新了,驗證請求返回 200

特點:協商快取並不會減少請求的數量。但如果是304,請求只會返回一個狀態碼,沒有實際的資源內容,所以會減少響應體體積,來縮短網路傳輸時間。

協商快取作為強快取失效的後備解決方案,一般會和強快取一起使用。透過2組欄位來實現:

Last-Modified & If-Modified-Since
Etag & If-None-Match

Last-Modified & If-Modified-Since

Last-Modified 是響應頭,If-Modified-Since 是請求頭。

首先,伺服器透過 Last-Modified 欄位告知瀏覽器,資源最後一次被修改的時間。

Last-Modified: Thu, 21 Dec 2023 00:28:00 GMT

1

瀏覽器將資源和這個欄位的值保留在快取中。
再次請求相同資源時,瀏覽器從自己的快取中找出 “不確定是否過期的” 快取(也就是強快取失效,已經命中協商快取了)。並在請求頭的 If-Modified-Since 欄位中寫入儲存的 Last-Modified 的值。
伺服器會將接收到的 If-Modified-Since 的值與服務端的 Last-Modified 欄位進行對比。相等則表示未修改,響應 304;反之,則表示修改了,響應 200 狀態碼,並返回資料。

缺點:因為它的時間單位是秒,所以如果資源的更新速度是秒以下的單位,則無法使用該快取。
Etag & If-None-Match

為了解決上面的問題,所以在出現了這組新的欄位。

ETag 是響應頭,If-None-Match 是請求頭。

ETag 是資源的識別符號,一般為一個 hash 值,在伺服器儲存。

整體流程和 Last-Modified & If-Modified-Since 類似,只是做了替換 Last-Modified --> ETag ;If-Modified-Since --> If-None-Match。

流程如下圖示:

二者對比:

精度:Etag > Last-Modified,因為 Etag 是一個 hash 值,每次都會改變從而確保精度。
效能:Last-Modified > Etag,因為 Etag 需要伺服器透過演算法來計算 Hash 值。而 Last-Modified 只需要記錄時間。
優先順序:伺服器校驗優先考慮 Etag。

Disk Cache 整體流程圖:
2,快取讀取規則

當瀏覽器要請求資源時:

從 Service Worker 中獲取內容(如果設定了 Service Worker)。

檢視 Memory Cache。

檢視 Disk Cache。細分為:

如果有強制快取且未失效,則使用強制快取,不請求伺服器。這時的狀態碼全都是 200。

如果有強制快取但已失效,使用協商快取,比較後確定 304 還是 200。

傳送網路請求,等待網路響應。

把響應內容存入 Disk Cache(如果 HTTP 響應頭資訊有相應配置的話)。

把響應內容的引用存入 Memory Cache(無視 HTTP 頭資訊的配置)。

把響應內容存入 Service Worker 的 Cache Storage(如果設定了 Service Worker)。

3,瀏覽器的一些行為

使用者對瀏覽器的不同操作,會觸發不同的快取讀取策略。

常見的有3種:

在位址列輸入地址訪問時,瀏覽器會查詢 Disk Cache 中是否有匹配。有則使用,沒有傳送則傳送網路請求。
普通重新整理(F5),因為標籤頁沒有關閉,所以 Memory Cache 是可用的,會優先使用它。其次才是 Disk Cache。
強制重新整理(Ctrl / Shift + F5),瀏覽器不使用快取,因此在 請求頭 Request Headers 中會自動新增 Cache-Control: no-cache(為了相容還會有Pragma: no-cache),伺服器直接返回200和最新內容。

4,快取最佳實踐
頻繁變動的資源

Cache-Control: no-cache

1

或(二者等效)

Cache-Control: max-age=0, must-revalidate

1

表示瀏覽器可以快取資源,但每次使用快取資源前都必須重新驗證其有效性(透過 ETag 或者 Last-Modified)。

這樣雖然每次都會發起 HTTP 請求,但當快取內容仍然有效時可以跳過 HTTP 響應體的下載,來減少響應資料的大小。
不常變化的資源

Cache-Control: max-age=31536000

1

這類資源,可以設定一個很大的有效時間 31536000(一年)。這樣瀏覽器之後請求相同 url 時會命中強制快取。

由此帶來的更新問題,可以在檔名後新增 hash,版本號等字元,從而達到更改資源 url 的目的。

注意之前的強制快取並未失效,只是不再使用了而已。
————————————————

版權宣告:本文為博主原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處連結和本宣告。

原文連結:https://blog.csdn.net/qq_40147756/article/details/135110801

相關文章