透過網路擷取資源既緩慢,又所費不貲:
- 大型回應需要在瀏覽器和伺服器之間來回多次轉換。
- 網頁要等到所有重要資源下載完成才會載入。
- 如果您網站上的使用者採用有限的行動數據方案,則每個不必要的網路要求都會浪費資金。
如何避免不必要的網路要求?瀏覽器的 HTTP 快取是第一道防線這不是最強大或最靈活的方法,您對於快取回應的生命週期擁有有限的掌控權,但這項功能也有效,所有瀏覽器都支援,而且不需要做太多工作。
本指南說明有效 HTTP 快取實作的基本概念。
瀏覽器相容性
HTTP 快取是所有瀏覽器支援的網路平台 API 集合的一般名稱:
Cache-Control
ETag
Last-Modified
HTTP 快取的運作方式
瀏覽器提出的所有 HTTP 要求會先轉送至瀏覽器快取,確認是否有可用於執行要求的有效快取回應。如果比對相符,就會從快取中讀取回應,避免網路延遲和傳輸的數據用量。
HTTP 快取的行為是由要求標頭和回應標頭的組合控制。在理想情況下,您可以控制網頁應用程式的程式碼,進而決定要求標頭,以及決定回應標頭的網路伺服器設定。
如需更深入的概念總覽,請參閱 MDN 的 HTTP 快取一文。
要求標頭:保留預設值 (通常)
有些重要標頭應納入網頁應用程式的傳出要求,但瀏覽器在發出要求時,幾乎一律會替您設定這些標頭。系統會根據瀏覽器對於 HTTP 快取中目前值的瞭解,顯示會影響檢查更新頻率的要求標頭 (例如 If-None-Match
和 If-Modified-Since
)。
好消息是,這表示您可以繼續在 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
。
如要回應含有「指紋」或版本資訊,且其內容永遠不會改變的要求,請在回應中加入 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 回應,相當於「Ok,繼續使用目前擁有的內容!」傳送這類回應時,因為僅需要轉移少量資料,因此通常比必須實際回傳實際資源副本要來得快。
摘要
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 |
回應可由瀏覽器和中介快取快取長達一天 (60 秒 x 60 分鐘 x 24 小時)。 |
private, max-age=600 |
回應可由瀏覽器快取,但中介快取作業最多為十分鐘 (60 秒 x 10 分鐘)。 |
public, max-age=31536000 |
回應可由任何快取儲存一年。 |
no-store |
無法快取回應,且每次要求時都必須完整擷取回應。 |