從前端角度理解快取

薄荷前端發表於2019-01-17

快取的概念分很多種,本次討論的主要就是前端快取中的Http快取。

快取是怎麼回事

前端傳送請求主要經歷以下三個過程,請求->處理->響應。 如果有多次請求就需要重複執行這個過程。

重複請求的過程

以下是一個重複請求的流程圖:

重複請求

從以上的流程圖可以看書,如果使用者重複請求同一資源的話,會對伺服器資源造成浪費,伺服器重複讀取資源,傳送給瀏覽器後瀏覽器重複下載,造成不必要的等待與消耗。

快取讀取的過程

快取讀取就是瀏覽器在向伺服器請求資源之前,先查詢一下本地快取中是否存在需要的資源,如果存在,那便優先從快取中讀取。當快取不存在或者過期,再向伺服器傳送請求。

快取讀取

如何開啟Http快取並對快取進行設定,是本次討論的關鍵。

快取的型別

瀏覽器有如下常見的幾個欄位:

  1. expires: 設定快取過期的時間
  2. private: 客戶端可以快取
  3. public: 客戶端和代理伺服器都可快取
  4. max-age=xxx: 快取的內容將在 xxx 秒後失效
  5. no-cache: 需要使用對比快取來驗證快取資料
  6. no-store: 所有內容都不會快取,強制快取,對比快取都不會觸發
  7. last-modified: 內容上次被修改的時間
  8. Etag: 檔案的特殊標識

強制快取和協商快取

快取方法可以分為強制快取與協商快取。

從字面理解,強制快取的方式簡單粗暴,給cache設定了過期時間,超過這個時間之後cache過期需要重新請求。上述欄位中的expirescache-control中的max-age都屬於強制快取。

協商快取根據一系列條件來判斷是否可以使用快取。

強制快取優先順序高於協商快取

強制快取

expires

expires給瀏覽器設定了一個絕對時間,當瀏覽器時間超過這個絕對時間之後,重新向伺服器傳送請求。

Expires: Fri, 04 Jan 2019 12:00:00 GMT

這個方法簡單直接,直接設定一個絕對的時間 (當前時間+快取時間)。但是也存在隱患,例如瀏覽器當前時間是可以進行更改的,更改之後expires設定的絕對時間相對不準確,cache可能會出現長久不過期或者很快就過期的情況。

cache-control: max-age

為了解決expires存在的問題,Http1.1版本中提出了cache-control: max-age,該欄位與expires的快取思路相同,都是設定了一個過期時間,不同的是max-age設定的是相對快取時間開始往後多久,因此不存在受日期不準確情況的影響。

但是強制快取存在一個問題,該快取方式優先順序高,如果在過期時間內快取的資源在伺服器上更新了,客服端不能及時獲取最新的資源。

協商快取

協商快取解決了無法及時獲取更新資源的問題。以下兩組欄位,都可以對資源做標識,由伺服器做分析,如果未進行更新,那返回304狀態碼,從快取中讀取資源,否則重新請求資源。

last-modify

last-modify告知了客戶端上次修改該資源的時間,

Last-Modified: Wed, 02 Jan 2019 03:06:03 GMT

瀏覽器將這個值記錄在if-modify-since中(瀏覽器自動記錄了該欄位資訊),下一次請求相同資源時,與伺服器返回的last-modify進行比對,如果相等,則表示未修改,響應 304;反之,則表示修改了,響應 200 狀態碼,並返回資料。

last-modify以秒為單位進行更新,如果小於該單位高頻進行更新的話,不適合採用該方法。

ETag

ETag是對資源的特殊標識

Etag: W/"e563df87b65299122770e0a84ada084f"

請求該資源成功之後,將返回的ETag存入if-none-match欄位中(瀏覽器自動記錄了該欄位資訊),同樣在請求資源時傳遞給伺服器,伺服器查詢該編碼對應的資源有無更新,無更新返回304狀態,更新返回200並重新請求。

以下有個小例子,查詢書籍更新:

當書籍資訊查詢之後,再次查詢,伺服器根據資源的ETag查詢得知該資源沒有進行更新,返回304狀態碼。

書籍資訊(舊)

更新返回的資料資訊,再次查詢,返回200狀態碼,重新進行請求:

書籍資訊(新)

從返回的Request Headers可以看出,再次請求時,瀏覽器自動傳送了If-Modified-SinceIf-None-Match兩個欄位,瀏覽器根據這兩個欄位中(If-None-Match 優先順序大於 If-Modified-Since)來判斷是否修改了資源。

image

ETag如何計算

ETag是針對某個檔案的特殊標識,伺服器預設採用SHA256演算法生成。也可以採用其他方式,保證編碼的唯一性即可。

快取的優先順序

根據上文優缺點的比對,可以得出以下的優先順序順序:

Cache-Control > Expires > ETag > Last-Modified

如果資源需要用到強制快取,Cache-Control相對更加安全,協商快取中利用ETag查詢更新更加全面。

快取的判斷流程

圖片來源:瀏覽器快取機制詳解

快取儲存在哪

disk cache

disk cache為儲存在硬碟中的快取,儲存在硬碟中的資源相對穩定,不會隨著tab或瀏覽器的關閉而消失,可以用來儲存大型的,需長久使用的資源。

當硬碟中的資源被載入時,記憶體中也儲存了該資源,當下次改資源被呼叫時,會優先從memory cache中讀取,加快資源的獲取。

memory cache

memory cache即儲存在記憶體中的快取,記憶體中的內容會隨著tab的關閉而釋放。

當介面狀態返回304時,資源預設儲存在memory cache中,當頁面關閉後,重新開啟需要再次請求。

這兩種儲存方式的區別可以參考該回答

When you visit a URL in Chrome, the HTML and the other assets(like images) on the page are stored locally in a memory and a disk cache. Chrome will use the memory cache first because it is much faster, but it will also store the page in a disk cache in case you quit your browser or it crashes, because the disk cache is persistent.

當您訪問chrome中的URL時,頁面上的HTML和其他資產(如影象)將本地儲存在記憶體和磁碟快取中。Chrome將首先使用記憶體快取,因為它的速度快得多,但它也會將頁面儲存在磁碟快取中,以防您退出瀏覽器或它崩潰,因為磁碟快取是持久的。

為什麼有的資源一會from disk cache,一會from memory cache

三級快取原理

  1. 先去記憶體看,如果有,直接載入
  2. 如果記憶體沒有,擇取硬碟獲取,如果有直接載入
  3. 如果硬碟也沒有,那麼就進行網路請求
  4. 載入到的資源快取到硬碟和記憶體,下次請求可以快速從記憶體中獲取到

為什麼有的請求狀態碼返回200,有的返回304

200 from memory cache

不訪問伺服器,直接讀快取,從記憶體中讀取快取。此時的資料時快取到記憶體中的,當關閉程式後,也就是瀏覽器關閉以後,資料將不存在。

但是這種方式只能快取派生資源。

200 from disk cache

不訪問伺服器,直接讀快取,從磁碟中讀取快取,當關閉程式時,資料還是存在。

這種方式也只能快取派生資源

304 Not Modified

訪問伺服器,發現資料沒有 更新,伺服器返回此狀態碼。然後從快取中讀取資料。

薄荷應用

舉一個簡單的小?,以薄荷的減肥群頁面為討論物件,檢視一下資源載入的情況:

薄荷圖片快取

這些圖片都是從硬碟中讀取,因為沒有在記憶體中獲取到響應的資源,當我們重新整理頁面時,這個資源因為從硬碟中讀取時,也儲存到了記憶體中,再次獲取就是從記憶體中獲取了:

薄荷圖片快取2

當我們沒有關閉頁面時,記憶體中的資源始終存在,重新開啟則記憶體釋放。

CDN快取

CDN邊緣節點快取策略因服務商不同而不同,但一般都會遵循http標準協議,通過http響應頭中的Cache-control: max-age的欄位來設定CDN邊緣節點資料快取時間。

當客戶端向CDN節點請求資料時,CDN節點會判斷快取資料是否過期,若快取資料並沒有過期,則直接將快取資料返回給客戶端;否則,CDN節點就會向源站發出回源請求,從源站拉取最新資料,更新本地快取,並將最新資料返回給客戶端。

如何合理應用快取

強制快取優先順序最高,並且資源的改動在快取有效期內都不會對快取產生影響,因此該方法適用於大型且不易修改的的資原始檔,例如第三方CSS、JS檔案或圖片資源,檔案後可以加上hash進行版本的區分。建議將此類大型資源存入disk cache,因為存在硬碟中的檔案資源不易丟失。

協商快取靈活性高,適用於資料的快取,根據上述方法的對比,採用Etag標識進行對比靈活度最高,並考慮將資料存入記憶體中,因為記憶體載入速最快,並且資料體積小,不會佔用大量記憶體資源。

廣而告之

本文釋出於薄荷前端週刊,歡迎Watch & Star ★,轉載請註明出處。

歡迎討論,點個贊再走吧 。◕‿◕。 ~

相關文章