Cache-Control
Cache-Control HTTP 頭欄位包含用於控制瀏覽器和共享快取(例如代理、CDN)中快取的指令(說明)——在請求和響應中。
| 頭型別 | 請求頭,響應頭 |
|---|---|
| 禁止的頭名稱 | 否 |
| CORS 安全列表響應頭 | 是 |
語法
快取指令遵循以下規則
- 快取指令不區分大小寫。但是,建議使用小寫,因為某些實現不識別大寫指令。
- 允許多個指令,並且必須用逗號分隔(例如,
Cache-control: max-age=180, public)。 - 某些指令具有可選引數。提供引數時,它與指令名稱之間用等號 (
=) 分隔。通常,指令的引數是整數,因此不包含在引號字元中(例如,Cache-control: max-age=12)。
快取指令
下表列出了標準的 Cache-Control 指令
| 請求 | 響應 |
|---|---|
max-age |
max-age |
max-stale |
- |
min-fresh |
- |
| - | s-maxage |
no-cache |
no-cache |
no-store |
no-store |
no-transform |
no-transform |
only-if-cached |
- |
| - | must-revalidate |
| - | proxy-revalidate |
| - | must-understand |
| - | private |
| - | public |
| - | immutable |
| - | stale-while-revalidate |
stale-if-error |
stale-if-error |
注意:請檢視相容性表格以瞭解其支援情況;不支援它們的 User Agent 應忽略它們。
詞彙
本節定義了本文件中使用的術語,其中一些術語來自規範。
- (HTTP) 快取
-
儲存請求和響應以供後續請求重用的實現。它可以是共享快取或私有快取。
-
存在於源伺服器和客戶端之間(例如代理、CDN)的快取。它儲存單個響應並將其重用於多個使用者——因此開發人員應避免將個性化內容儲存在共享快取中。
- 私有快取
-
存在於客戶端中的快取。它也稱為本地快取或瀏覽器快取。它可以儲存和重用單個使用者的個性化內容。
- 儲存響應
-
當響應可快取時,將其儲存在快取中。但是,快取的響應並不總是按原樣重用。(通常,“快取”表示儲存響應。)
- 重用響應
-
重用快取的響應以供後續請求使用。
- 重新驗證響應
-
詢問源伺服器儲存的響應是否仍然新鮮。通常,重新驗證是透過條件請求完成的。
- 新鮮響應
-
表示響應新鮮。這通常意味著響應可以重用於後續請求,具體取決於請求指令。
- 陳舊響應
-
表示響應為陳舊響應。這通常意味著響應不能按原樣重用。快取儲存不需要立即刪除陳舊響應,因為重新驗證可以將響應從陳舊更改為新鮮。
- Age
-
自生成響應以來的時間。它是響應是否新鮮或陳舊的標準。
指令
本節列出了影響快取的指令——響應指令和請求指令。
響應指令
max-age
max-age=N 響應指令指示響應保持新鮮,直到生成響應後N秒。
Cache-Control: max-age=604800
指示快取可以儲存此響應並在其新鮮期間將其重用於後續請求。
請注意,max-age 不是自接收響應以來的經過時間;它是自源伺服器上生成響應以來的經過時間。因此,如果網路路由中其他快取儲存響應 100 秒(使用 Age 響應頭欄位指示),則瀏覽器快取會從其新鮮生命週期中減去 100 秒。
如果 max-age 值為負數(例如,-1)或不是整數(例如,3599.99),則快取行為未指定。鼓勵快取將該值視為 0(這在 HTTP 規範的計算新鮮生命週期部分中有所說明)。
Cache-Control: max-age=604800
Age: 100
s-maxage
s-maxage 響應指令指示響應在共享快取中保持新鮮多長時間。私有快取會忽略 s-maxage 指令,並且如果存在,則會覆蓋共享快取中由 max-age 指令或 Expires 標頭指定的值。
Cache-Control: s-maxage=604800
no-cache
no-cache 響應指令指示響應可以儲存在快取中,但每次重用之前都必須使用源伺服器驗證響應,即使快取與源伺服器斷開連線也是如此。
Cache-Control: no-cache
如果希望快取在重用儲存的內容時始終檢查內容更新,則應使用 no-cache 指令。它透過要求快取使用源伺服器重新驗證每個請求來實現此目的。
請注意,no-cache 不表示“不要快取”。no-cache 允許快取儲存響應,但要求它們在重用之前重新驗證它。如果所需的“不要快取”的含義實際上是“不要儲存”,則應使用 no-store 指令。
must-revalidate
must-revalidate 響應指令指示響應可以儲存在快取中,並且可以在新鮮時重用。如果響應變得陳舊,則必須在重用之前使用源伺服器對其進行驗證。
通常,must-revalidate 與 max-age 一起使用。
Cache-Control: max-age=604800, must-revalidate
HTTP 允許快取在與源伺服器斷開連線時重用陳舊響應。must-revalidate 是一種防止這種情況發生的方法——要麼儲存的響應使用源伺服器重新驗證,要麼生成 504(閘道器超時)響應。
proxy-revalidate
proxy-revalidate 響應指令等效於 must-revalidate,但僅針對共享快取。
no-store
no-store 響應指令指示任何型別的快取(私有或共享)都不應儲存此響應。
Cache-Control: no-store
private
private 響應指令指示響應只能儲存在私有快取中(例如瀏覽器中的本地快取)。
Cache-Control: private
您應該為使用者個性化內容新增 private 指令,特別是對於登入後收到的響應以及透過 cookie 管理的會話。
如果您忘記向包含個性化內容的響應新增 private,則該響應可能會儲存在共享快取中並最終被多個使用者重用,這可能導致個人資訊洩露。
public
public 響應指令指示響應可以儲存在共享快取中。具有 Authorization 標頭欄位的請求的響應不得儲存在共享快取中;但是,public 指令會導致此類響應儲存在共享快取中。
Cache-Control: public
通常,當頁面處於基本身份驗證或摘要身份驗證下時,瀏覽器會發送帶有 Authorization 標頭的請求。這意味著響應對於受限使用者(擁有帳戶的使用者)是訪問受控的,並且從根本上來說不可共享快取,即使它具有 max-age 也是如此。
您可以使用 public 指令來解除該限制。
Cache-Control: public, max-age=604800
請注意,s-maxage 或 must-revalidate 也會解除該限制。
如果請求沒有 Authorization 標頭,或者您已經在響應中使用了 s-maxage 或 must-revalidate,則無需使用 public。
must-understand
must-understand 響應指令指示快取僅當它理解基於狀態碼的快取要求時才應儲存響應。
must-understand 應與 no-store 結合使用以實現回退行為。
Cache-Control: must-understand, no-store
如果快取不支援 must-understand,則會將其忽略。如果也存在 no-store,則不會儲存響應。
如果快取支援 must-understand,則會根據其狀態碼儲存並理解快取要求的響應。
no-transform
出於各種原因,某些中間體轉換內容。例如,有些會轉換影像以減小傳輸大小。在某些情況下,這對於內容提供者來說是不可取的。
no-transform 指示任何中間體(無論它是否實現快取)都不應轉換響應內容。
immutable
immutable 響應指令指示響應在其新鮮期間不會更新。
Cache-Control: public, max-age=604800, immutable
靜態資源的現代最佳實踐是在其 URL 中包含版本/雜湊值,同時永遠不修改資源——而是,在必要時,更新具有新版本號/雜湊值的較新版本資源,以便它們的 URL 不同。這稱為快取清除模式。
<script src="https://example.com/react.0.0.0.js"></script>
當用戶重新載入瀏覽器時,瀏覽器會發送條件請求以驗證源伺服器。但是,即使使用者重新載入瀏覽器,也不需要重新驗證這些型別的靜態資源,因為它們從未修改過。immutable 告訴快取響應在其新鮮期間是不可變的,並避免了對伺服器進行此類不必要的條件請求。
當您對資源使用快取失效模式並應用較長的max-age時,還可以新增immutable以避免重新驗證。
stale-while-revalidate
stale-while-revalidate響應指令指示快取可以在重新驗證到快取時重用過期的響應。
Cache-Control: max-age=604800, stale-while-revalidate=86400
在上面的示例中,響應在7天(604800秒)內是新鮮的。7天后,它變為陳舊的,但快取允許在接下來的1天(86400秒)內重用它,前提是在後臺重新驗證響應。
重新驗證將使快取再次變為新鮮的,因此在客戶端看來,它在該期間始終是新鮮的——有效地隱藏了重新驗證的延遲開銷。
如果在此期間沒有發生請求,則快取變為陳舊的,並且下一個請求將正常重新驗證。
stale-if-error
stale-if-error響應指令指示快取可以在上游伺服器生成錯誤或本地生成錯誤時重用陳舊的響應。在此,錯誤被認為是任何狀態程式碼為500、502、503或504的響應。
Cache-Control: max-age=604800, stale-if-error=86400
在上面的示例中,響應在7天(604800秒)內是新鮮的。之後,它變為陳舊的,但在遇到錯誤時可以額外使用1天(86400秒)。
在stale-if-error期限過後,客戶端將收到任何生成的錯誤。
請求指令
no-cache
no-cache請求指令要求快取在重用之前使用源伺服器驗證響應。
Cache-Control: no-cache
即使快取有新鮮的響應,no-cache也允許客戶端請求最新的響應。
當用戶**強制重新載入**頁面時,瀏覽器通常會將no-cache新增到請求中。
no-store
no-store請求指令允許客戶端請求快取不要儲存請求和相應的響應——即使源伺服器的響應可以儲存。
Cache-Control: no-store
max-age
max-age=N請求指令指示客戶端允許儲存在源伺服器上生成的響應,該響應在N秒內生成——其中N可以是任何非負整數(包括0)。
Cache-Control: max-age=10800
在上述情況下,如果帶有Cache-Control: max-age=10800的響應是在3小時前(根據max-age和Age標頭計算)生成的,則快取無法重用該響應。
許多瀏覽器將此指令用於**重新載入**,如下所述。
Cache-Control: max-age=0
max-age=0是no-cache的解決方法,因為許多舊的(HTTP/1.0)快取實現不支援no-cache。最近,瀏覽器仍在“重新載入”中使用max-age=0——為了向後相容——並選擇性地使用no-cache來導致“強制重新載入”。
如果max-age值為負數(例如,-1)或不是整數(例如,3599.99),則快取行為未指定。鼓勵快取將該值視為0。
max-stale
max-stale=N請求指令指示客戶端允許儲存在N秒內陳舊的響應。如果沒有指定N值,則客戶端將接受任何年齡的陳舊響應。
Cache-Control: max-stale=3600
例如,帶有上述標頭的請求指示瀏覽器將接受來自快取的陳舊響應,該響應在過去一小時內已過期。
當源伺服器宕機或速度過慢時,客戶端可以使用此標頭,並且即使快取響應有點舊,也可以接受來自快取的快取響應。
請注意,主流瀏覽器不支援帶有max-stale的請求。
min-fresh
min-fresh=N請求指令指示客戶端允許儲存至少N秒內新鮮的響應。
Cache-Control: min-fresh=600
在上述情況下,如果帶有Cache-Control: max-age=3600的響應是在51分鐘前儲存在快取中的,則快取無法重用該響應。
當用戶不僅需要響應新鮮,而且還需要它在一段時間內不會更新時,客戶端可以使用此標頭。
請注意,主流瀏覽器不支援帶有min-fresh的請求。
no-transform
與響應的no-transform含義相同,但用於請求。
only-if-cached
客戶端指示應返回已快取的響應。如果快取有儲存的響應,即使是陳舊的響應,也會返回。如果沒有可用的快取響應,將返回504閘道器超時響應。
用例
防止儲存
如果您不希望響應儲存在快取中,請使用no-store指令。
Cache-Control: no-store
請注意,no-cache表示“可以儲存,但在驗證之前不要重用”——因此它不是為了防止響應被儲存。
Cache-Control: no-cache
理論上,如果指令發生衝突,則應遵循最嚴格的指令。因此,下面的示例基本上毫無意義,因為private、no-cache、max-age=0和must-revalidate與no-store衝突。
# conflicted
Cache-Control: private, no-cache, no-store, max-age=0, must-revalidate
# equivalent to
Cache-Control: no-store
使用“快取失效”快取靜態資源
當您使用版本控制/雜湊機制構建靜態資源時,在檔名或查詢字串中新增版本/雜湊是管理快取的好方法。
例如
<!-- index.html -->
<script src="/assets/react.min.js"></script>
<img src="/assets/hero.png" width="900" height="400" />
當您更新庫時,React庫版本將發生變化,並且當您編輯圖片時,hero.png也將發生變化。因此,很難使用max-age將它們儲存在快取中。
在這種情況下,您可以透過使用庫的特定編號版本並在其URL中包含圖片的雜湊來解決快取需求。
<!-- index.html -->
<script src="/assets/react.0.0.0min.js"></script>
<img src="/assets/hero.png?hash=deadbeef" width="900" height="400" />
您可以新增較長的max-age值和immutable,因為內容永遠不會更改。
# /assets/*
Cache-Control: max-age=31536000, immutable
當您更新庫或編輯圖片時,新內容應具有新的URL,並且不會重用快取。這稱為“快取失效”模式。
使用no-cache確保HTML響應本身不會被快取。no-cache可能會導致重新驗證,並且客戶端將正確接收HTML響應和靜態資源的新版本。
# /index.html
Cache-Control: no-cache
注意:如果index.html受基本身份驗證或摘要身份驗證控制,則/assets下的檔案不會儲存在共享快取中。如果/assets/檔案適合儲存在共享快取中,則還需要public、s-maxage或must-revalidate之一。
始終獲取最新的內容
對於動態生成的內容或靜態但經常更新的內容,您希望使用者始終接收最新版本。
如果您不新增Cache-Control標頭,因為響應並非旨在快取,則可能會導致意外結果。快取儲存允許啟發式地快取它——因此,如果您對快取有任何要求,則應始終在Cache-Control標頭中明確指示它們。
向響應中新增no-cache會導致重新驗證伺服器,因此您可以每次都提供新鮮的響應——或者如果客戶端已經有了新的響應,則只需響應304 未修改。
Cache-Control: no-cache
大多數HTTP/1.0快取不支援no-cache指令,因此歷史上使用max-age=0作為解決方法。但是,只有max-age=0才能導致在快取與源伺服器斷開連線時重用陳舊的響應。must-revalidate解決了這個問題。這就是下面示例等效於no-cache的原因。
Cache-Control: max-age=0, must-revalidate
但現在,您可以簡單地使用no-cache。
清除已儲存的快取
不幸的是,沒有用於清除快取中已儲存響應的快取指令。
假設客戶端/快取儲存了路徑的新鮮的響應,而沒有向伺服器傳送請求。伺服器對此路徑無能為力。
或者,Clear-Site-Data可以清除瀏覽器的站點快取。但請注意:這將清除站點的所有儲存的響應——並且僅在瀏覽器中,而不是在共享快取中。
規範
| 規範 |
|---|
| HTTP快取 # field.cache-control |
| HTTP不可變響應 # the-immutable-cache-control-extension |
瀏覽器相容性
BCD表格僅在啟用JavaScript的瀏覽器中載入。