透過網路擷取資源既緩慢又昂貴:
- 大型回應需要在瀏覽器和伺服器之間進行多次往返作業。
- 所有重要資源都下載完畢後,您的網頁才會載入。
- 如果有人透過有限的行動數據方案存取您的網站,則每個不必要的網路要求都會浪費資金。
如何避免不必要的網路要求?瀏覽器的 HTTP 快取是您的第一道防線。這不一定是最強大或彈性的方法,而且您對於快取回應的生命週期有限,但這樣做效果有效,並且適用於所有瀏覽器,而且不需要太多作業。
本指南說明有效 HTTP 快取實作的基本概念。
瀏覽器相容性
實際上,沒有任何一個稱為 HTTP 快取的 API。是一組網路平台 API 的通用名稱。所有瀏覽器均支援這些 API:
HTTP 快取的運作方式
瀏覽器發出的所有 HTTP 要求都會先轉送至瀏覽器快取,以檢查是否具備可用於執行要求的有效快取回應。如果比對內容相符,系統就會從快取讀取回應,這能省去網路延遲時間和移轉作業產生的資料費用。
HTTP 快取的行為由要求標頭和回應標頭組合而成。在理想情況下,您可以控管網頁應用程式的程式碼 (這會影響要求標頭),以及網路伺服器的設定 (這會決定回應標頭)。
如需深入瞭解概念總覽,請參閱 MDN 的「HTTP 快取」一文。
要求標頭:與預設值一起 (通常)
雖然在網頁應用程式的傳出要求中包含多個重要標頭,但瀏覽器在發出要求時,幾乎一律會代您設定這些標頭。而會影響檢查更新間隔的要求標頭 (例如 If-None-Match
和 If-Modified-Since
),只會根據瀏覽器對 HTTP 快取中目前值的瞭解顯示。
好消息是,您可以在 HTML 中繼續加入 <img
src="my-image.png">
這類標記,瀏覽器會自動為您處理 HTTP 快取作業,不必額外費心。
回應標頭:設定您的網路伺服器
HTTP 快取設定最重要的部分是網路伺服器新增至每個傳出回應的標頭。下列標頭全都會列入有效的快取行為:
Cache-Control
。伺服器可能會傳回Cache-Control
指令,指定瀏覽器和其他中繼快取應如何快取個別回應,以及快取這些快取的時間長度。ETag
。當瀏覽器找到過期的快取回應時,可能會將小型權杖 (通常是檔案內容的雜湊) 傳送至伺服器,檢查檔案是否已變更。如果伺服器傳回相同的權杖,就代表檔案是一樣的,也不需要重新下載。Last-Modified
。此標頭與ETag
的用途相同,但使用以時間為準的策略來判斷資源是否已變更,而不是使用ETag
的內容型策略。
部分網路伺服器提供預設可設定這些標頭的內建支援,而有些伺服器則不需要明確設定標頭,否則將完全排除標頭。設定標頭的具體細節會因使用的網路伺服器而異,建議您參閱伺服器的說明文件,以取得最準確的詳細資訊。
為了節省搜尋時間,以下提供設定一些熱門網路伺服器的操作說明:
留下 Cache-Control
回應標頭並不會停用 HTTP 快取!
相反地,瀏覽器會有效推測哪種快取行為對特定類型的內容最有幫助。您或許需要比這些方案更多的控制,因此不妨花點時間設定回應標頭。
請問你該使用哪種回應標頭值?
設定網路伺服器回應標頭時,需要涵蓋兩個重要情境。
適用於版本化網址的長期快取
假設您的伺服器指示瀏覽器快取 CSS 檔案長達 1 年 (Cache-Control: max-age=31536000
),但設計人員剛執行了需要立即推出的緊急更新作業。如何通知瀏覽器更新「過時」檔案的快取副本?
您必須變更資源的網址,才能進行這項操作。瀏覽器快取回應後,就會使用快取版本,直到快取版本不再更新 (由 max-age
或 expires
決定),或是因其他原因 (例如使用者清除瀏覽器快取) 從快取中移除為止。因此,不同使用者可能會在建構網頁時使用不同的檔案版本:僅擷取資源的使用者會使用新版本,而先前快取過舊 (但仍然有效) 副本的使用者則會使用舊版回應。那麼,您如何充分運用用戶端快取和快速更新功能?您可以變更資源的網址,並強制使用者在每次內容變更時下載新的回應。通常,您可以在檔案名稱 (例如 style.x234dff.css
) 中嵌入檔案的指紋或版本號碼。
回應包含「fingerprint」(指紋) 或版本資訊,且內容絕不會變更的要求時,請在回應中加入 Cache-Control: max-age=31536000
。
設定這個值會告訴瀏覽器在未來一年內隨時需要載入同一個網址 (31,536,000 秒;支援的值上限) 可立即使用 HTTP 快取中的值,而不必向網路伺服器發出網路要求。太棒了,您已立即提升規避網路帶來的可靠性和速度!
Webpack 等建構工具可以自動執行將雜湊指紋指派給資產網址的程序。
針對未版本的網址重新驗證伺服器
很抱歉,您載入的不是部分網址的版本。您可能無法在部署網頁應用程式之前加入建構步驟,而無法在素材資源網址中加入雜湊。而且每個網頁應用程式都需要 HTML 檔案,這些檔案就幾乎都不需要包含版本資訊,因為如果確定造訪的網址是 https://example.com/index.34def12.html
,就沒有人可以使用您的網頁應用程式。那麼,您可以針對這些網址該怎麼做?
在這個案例中,您必須堅持擊敗。單憑 HTTP 快取功能還不足以避免網路完全避免網路運作。(請放心,您很快就會瞭解服務工作站,這些工作人員會提供您揮灑大戰所需的支援)。不過,您可以採取幾個步驟,確保網路要求能以最快的速度和效率完成。
下列 Cache-Control
值可協助您微調未版本網址的快取位置和方式:
no-cache
:指示瀏覽器在每次使用網址的快取版本之前,必須重新向伺服器進行驗證。no-store
:這會指示瀏覽器和其他中繼快取 (例如 CDN) 一律不儲存任何版本的檔案。private
。瀏覽器可以快取檔案,但中繼快取則無法。public
。回應可由任何快取儲存。
請參閱附錄:Cache-Control
流程圖以視覺化方式呈現決定使用哪個 Cache-Control
值的程序。另請注意,Cache-Control
接受以半形逗號分隔的指令清單。請參閱附錄:Cache-Control
範例。
除此之外,設定其他兩個回應標頭中的任一個也有助於:ETag
或 Last-Modified
。如回應標頭中所述,ETag
和 Last-Modified
的用途相同:判斷瀏覽器是否需要重新下載已過期的快取檔案。建議您使用 ETag
,因為其準確度較高。
假設自初始擷取以來,120 秒已過,且瀏覽器已針對同一個資源發出新的要求。首先,瀏覽器會檢查 HTTP 快取,並找出先前的回應。很抱歉,由於回應已過期,瀏覽器無法使用先前的回應。此時,瀏覽器可以分派新的要求,並擷取新的完整回應。不過,由於資源並未變更,所以效率較低,所以沒有理由下載快取中現有的相同資訊!這就是驗證權杖 (如 ETag
標頭所指定) 旨在解決的問題。伺服器會產生並傳回任意權杖,通常是檔案內容的雜湊或其他指紋。瀏覽器不必知道指紋的產生方式,只需在下次要求時將指紋傳送至伺服器。如果指紋維持不變,表示資源並未變更,瀏覽器可以略過下載程序。
設定 ETag
或 Last-Modified
可讓您更有效率地提出重新驗證要求。而會觸發要求標頭中提及的 If-Modified-Since
或 If-None-Match
要求標頭。
當正確設定的網頁伺服器偵測到傳入的要求標頭時,可以確認瀏覽器的 HTTP 快取中既有的資源版本是否與網路伺服器的最新版本相符。如果比對相符,伺服器就會回應 304 Not Modified
HTTP 回應,這相當於「Hey,繼續使用您已擁有的項目!」傳送這類回應時要傳輸的資料很少,因此通常比實際傳回實際要求資源副本的速度要快上許多。

/file
,並附上 If-None-Match
標頭,指示伺服器只在伺服器上檔案的 ETag
與瀏覽器的 If-None-Match
值不符時,才傳回完整檔案。在這種情況下,這兩個值相符,因此伺服器會傳回 304 Not Modified
回應,其中包含應快取檔案多長時間的指示 (Cache-Control: max-age=120
)。
摘要
HTTP 快取可減少不必要的網路要求,因此能有效提高載入效能。適用於所有瀏覽器,且不太容易設定。
不妨先使用下列 Cache-Control
設定:
Cache-Control: no-cache
用於在每次使用前應透過伺服器重新驗證的資源。Cache-Control: no-store
表示一律不應快取的資源。Cache-Control: max-age=31536000
適用於版本化資源。
此外,ETag
或 Last-Modified
標頭也能讓您更有效率地重新驗證過期的快取資源。
瞭解詳情
如果您想進一步瞭解使用 Cache-Control
標頭的基本知識,請參閱 Jake Archibald 的快取最佳做法和 max-age 檢查指南。
請參閱「放置快取」一文,瞭解如何針對回訪訪客最佳化快取使用方式。
附錄:其他訣竅
如需更多時間,以下提供其他方法,讓 HTTP 快取的使用達到最佳狀態:
- 使用一致的網址。如果您在不同的網址上提供相同的內容,系統會多次擷取及儲存該項內容。
- 盡量減少流失。如果某項資源的部分資源 (例如 CSS 檔案) 經常更新,而其餘檔案並未 (例如程式庫程式碼),請考慮將經常更新的程式碼分割成不同檔案,並針對經常更新的程式碼使用較短的持續時間快取策略,並針對不會經常變更的程式碼使用較長的快取持續時間策略。
- 如果
Cache-Control
政策可以接受某些過時程度,請參閱新的stale-while-revalidate
指令。
附錄:Cache-Control
流程圖
附錄:Cache-Control
個範例
Cache-Control 值 |
說明 |
---|---|
max-age=86400 |
瀏覽器和中介快取可快取回應,最長可達 1 天 (60 秒 x 60 分鐘 x 24 小時)。 |
private, max-age=600 |
瀏覽器可快取回應,但不得快取中繼快取,最長可達 10 分鐘 (60 秒 x 10 分鐘)。 |
public, max-age=31536000 |
回應可以儲存在任何快取中 1 年。 |
no-store |
系統不允許快取回應,因此必須在每次要求時完整擷取回應。 |