[前端 · 面試 ]HTTP 總結(八)—— HTTP 強快取

程式設計三昧發表於2021-08-08

最近我在做前端面試題總結系列,感興趣的朋友可以新增關注,歡迎指正、交流。

爭取每個知識點能夠多總結一些,至少要做到在面試時,針對每個知識點都可以侃起來,不至於啞火。

HTTP 強快取和協商快取

前言

透過上一篇的總結,我們知道 HTTP 快取分為兩種:

  • 強快取
  • 協商快取

HTTP 快取分類

今天我們就先來了解一下強快取相關的內容。

強快取

特點

強快取中,當請求再次發出時,瀏覽器會判斷目標資源是否“命中”強快取,如果命中則直接從快取中獲取資源,不會再與服務端發生通訊。

在 Chrome 中,命中強快取的情況下, Network 中顯示的 HTTP 狀態碼是 200 ,比如:

image-20210808211159084

規則

強制快取的請求結果有兩種情況:

  • 命中快取
  • 未命中快取

命中快取

image-20210808212126564

未命中快取

image-20210808212546662

分類

在 Chrome 中,強快取又分為:

  • Disk Cache

    快取資源在硬碟中,瀏覽器(或頁面標籤)關閉後硬碟中的快取不會消失,下次進入頁面還能從硬碟中獲取。

  • Memory Cache

    快取資源在記憶體中,瀏覽器(或頁面標籤)關閉後記憶體中的快取就會被釋放,重新開啟頁面取不到該快取。

快取存放的位置是由瀏覽器控制的。

image-20210808210306482

如果不想從強快取中獲取資源,Windows 電腦可以透過 Ctrl + F5 重新整理頁面,Mac OS 可以透過 Shift + Command + R 重新整理頁面,重新整理後你可以看到資源不會出現 from disk(or memory) cache 了。

屬性

是否強快取由以下 3 個 Header 屬性共同來控制:

  • Expires
  • Cache-Control
  • Pragma

Expires

Expires 的值是一個 HTTP 日期,當伺服器返回響應時,在 Response Headers 中將過期時間寫入 Expires 欄位。

在瀏覽器發起請求時,會根據系統時間和 Expires 的值進行比較,如果系統時間超過了 Expires 的值,快取失效,會繼續從伺服器獲取資源,比如:

image-20210808211410000

Expires 的值是一個絕對時間,可以看到上圖中的時間點:2021 年 8 月 15 日 07:16:53,這代表:這個資源在這個時間點之前都可以直接從快取中獲取。

但是,使用 Expires 會存在一個問題:由於 Expires 的時間戳是伺服器定義的,而本地時間的取值來自客戶端,因此 Expires 的工作機制對於客戶端時間和伺服器時間的一致性要求極高,如果兩者的時間存在時差,會帶來意料之外的結果。

Expires 的優先順序在三個 Header 屬性中是最低的。

Expires 欄位是 HTTP 1.0 時代的產物,現在的瀏覽器用的全都是 HTTP 1.1 了,所以這個欄位的作用基本可以忽略 。

Cache-Control

是 HTTP 1.1 中新增的屬性,為了彌補 Expires 缺陷提出的,提供了更精確細緻的快取功能。Cache-Control 在請求頭和響應頭中都可以使用:

請求頭Cache-Control 欄位列表:

  • Cache-Control: max-age=
  • Cache-Control: max-stale[=]
  • Cache-Control: min-fresh=
  • 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=
  • Cache-control: s-maxage=

Cache-Control 常見欄位的含義:

  • public
    表明響應可以被任何物件(包括:傳送請求的客戶端,CDN 等代理伺服器,等等)快取,即使是通常不可快取的內容(例如,該響應沒有max-age指令或Expires訊息頭)。

  • private
    表明響應只能被單個使用者快取,不能作為共享快取(即代理伺服器不能快取它),私有快取可以快取響應內容。

  • no-cache
    可以在本地進行快取,但每次發請求時,都要向伺服器進行驗證,如果伺服器允許,才能使用本地快取(即:需要協商快取)。

  • no-store
    禁止快取客戶端請求或伺服器響應的內容,每次都須重新請求伺服器拿內容。

  • max-age
    設定快取儲存的最大週期,超過這個時間快取被視為過期 (單位:秒)。

  • must-revalidate

    在快取過期前可以使用,過期後必須向伺服器驗證。

image-20210808214220870

圖中 Cache-Control 僅指定了 Max-age,所以預設為 private,快取時間為 31536000 秒(365 天),也就是說,在 365 天內再次請求這條資料,都會直接獲取快取資料庫中的資料,直接使用。

在 HTTP 1.1 標準試圖將快取相關配置收斂進 Cache-Control 這樣的大背景下, Max-age 可以視作是對 Expires 能力的補位/替換。在當下的前端實踐裡,我們普遍會傾向於使用 Max-age。但如果你的應用對向下相容有強訴求,那麼 Expires 仍然是不可缺少的。

Pragma

Pragma 只有一個屬性值,就是 no-cache ,效果和 Cache-Control 中的 no-cache 一致,不使用強快取,需要與伺服器驗證快取是否新鮮,在 3 個頭部屬性中的優先順序最高。

總結

  • Expires 和 Pragma 是 HTTP 1.0的產物,Cache-Control是 HTTP 1.1 的產物。
  • 當 Expires 和 Cache-Control 同時存在時,只有 Cache-Control 生效。
  • 在某些不支援 HTTP 1.1 的環境下,Expires 就會發揮用處,現階段它的存在只是為了相容性
  • 大檔案,優先快取至 Disk,小檔案優先快取至 Memory
  • 當記憶體佔用率高的情況下,優先快取至 Disk

~

~本文完,感謝閱讀!

~

學習有趣的知識,結識有趣的朋友,塑造有趣的靈魂!

大家好,我是〖程式設計三昧〗的作者 隱逸王,我的公眾號是『程式設計三昧』,歡迎關注,希望大家多多指教!

你來,懷揣期望,我有墨香相迎! 你歸,無論得失,唯以餘韻相贈!

知識與技能並重,內力和外功兼修,理論和實踐兩手都要抓、兩手都要硬!

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章