使用者第二次載入網站時會使用 HTTP 快取,因此請確保快取運作正常。
本文將隨附於 2020 年 Chrome 開發人員高峰會「延伸內容」的「愛你的快取」影片。請務必觀看這部影片:
使用者第二次載入網站時,瀏覽器會使用 HTTP 快取中的資源,加快載入速度。不過,網路快取標準可追溯至 1999 年,而且定義相當廣泛,因此要判斷 CSS 或圖片等檔案是否可從網路重新擷取,而非從快取中載入,這項判斷有點不準確。
在本文中,我將介紹合理且新穎的快取預設值,實際上「完全不快取」。但這只是預設值,當然比「關閉」更精細。快繼續往下閱讀吧!
目標
網站第 2 次載入時,您有兩個目標:
- 請確保使用者取得了最新版本;如果您變更了某些內容,應該很快就能得到更新。
- 執行 #1,同時盡量減少從網路擷取的資料
從廣義來說,您只想在客戶重新載入網站時,將最小的變更傳送給客戶。而且,要將網站架構得宜,確保能以最有效率的方式發布任何變更,這項挑戰相當艱鉅 (詳情請見下文和影片)。
不過,考量快取時,您也能使用其他調整鈕,例如決定讓使用者的瀏覽器 HTTP 快取長時間保留您的網站,這樣一來,就不需要任何網路要求就能提供網站。或是建構了服務工作處理程序,將網站完全離線,再檢查網站是否為最新版本。這是相當極端的選項,適用於許多類似離線優先的應用程式網頁體驗,但網站不必受限於僅快取的極限,甚至完全沒有網路。
背景
身為網頁開發人員,我們都習慣「快取過期」的概念。但我們幾乎本能地知道,有哪些工具可用來解決這個問題:執行「強制重新整理」或開啟無痕式視窗,或是使用瀏覽器開發人員工具的組合,清除網站資料。
網路上的一般使用者沒有如此奢華,因此,雖然我們有幾項核心目標,確保使用者在第 2 次載入時能獲得良好體驗,但確保使用者不會感到不悅或卡住,也非常重要。(如果您想聽聽我們近期讓 web.dev/live 網站停滯不前的原因,請觀看影片)
稍微說明一下背景資訊,「陳舊快取」的常見原因其實是 1999 年快取的預設值。這項技術仰賴 Last-Modified
標頭:
您載入的每個檔案都會保留目前壽命的 10%,以便瀏覽器查看。舉例來說,如果 index.html
是在一個月前建立,瀏覽器會將其快取約三天。
這在當時是個好主意,但考量到現今網站的緊密整合性,這個預設行為可能會導致使用者擁有為不同網站版本設計的檔案 (例如星期二版本的 JS 和星期五版本的 CSS),因為這些檔案並未在同一時間更新。
光線充足的路徑
現代快取的預設做法是完全不快取,並使用CDN 將內容提供給使用者。每當使用者載入您的網站時,都會前往網路查看網站是否為最新版本。這項要求會由地理位置上鄰近每位使用者的 CDN 提供,因此延遲時間較短。
您可以設定網站主機使用這個標頭回應網路要求:
Cache-Control: max-age=0,must-revalidate,public
這基本上表示檔案的有效期限為零,您必須透過網路驗證檔案,才能再次使用 (否則只是「建議」)。
就傳輸位元組而言,這個驗證程序的成本相對較低,如果大型圖片檔案未變更,瀏覽器會收到小型 304 回應,但這會產生延遲,因為使用者仍必須前往網路才能查看。這也是這種做法的主要缺點。對於在第一世界國家中使用快速連線,且所選 CDN 涵蓋範圍廣泛的使用者來說,這項功能非常實用,但對於使用較慢行動連線或基礎架構不佳的使用者來說,就沒有太大幫助。
無論如何,這都是一種現代做法,也是熱門 CDN Netlify 的預設做法,但幾乎所有 CDN 都可以設定這類做法。針對 Firebase 代管服務,您可以在 firebase.json 檔案的代管區段中加入這個標頭:
"headers": [
// Be sure to put this last, to not override other headers
{
"source": "**",
"headers": [ {
"key": "Cache-Control",
"value": "max-age=0,must-revalidate,public"
}
}
]
因此,雖然我仍建議採用這個做為合理的預設值,但這只是預設值!請繼續閱讀,瞭解如何介入並升級預設值。
加上指紋的網址
在網站上提供的素材資源、圖片等名稱中加入檔案內容的雜湊,即可確保這些檔案一律含有獨特的內容,例如檔案名稱為 sitecode.af12de.js
。當伺服器回應這些檔案的要求時,您可以使用這個標頭設定瀏覽器,安全地指示終端使用者瀏覽器將這些檔案快取一段長時間:
Cache-Control: max-age=31536000,immutable
這個值以秒為單位。根據規格,這實際上等同於「永久」。
重要的是,請勿手動產生這些雜湊,因為這需要太多人工作業!您可以使用 Webpack、Rollup 等工具來處理這個問題。請務必參閱工具報告,進一步瞭解這些指標。
請記住,它不僅可受益於加上指紋網址的 JavaScript,也可以像圖示、CSS 和其他不可變動的資料檔案等資產命名。(請務必觀看上方影片,進一步瞭解程式碼分割,這個做法可讓您在網站變更時減少傳送程式碼)。
無論您的網站使用快取方式為何,這類指紋檔案對於您要建立的任何網站都非常具有價值。大多數網站並不會在每次發布時變更。
當然,我們無法以這種方式重新命名「友善」的使用者介面網頁:將 index.html
檔案重新命名為 index.abcd12.html
,這麼做是不切實際的,因為您無法要求使用者每次載入網站時都前往新的網址!這些「友善」網址無法以這種方式重新命名及快取,這會讓我找到可能的折衷做法。
中間地帶
在快取方面,顯然有中庸之道。我提出了兩種極端的做法:永遠不快取或永遠快取。您可能會想將許多檔案暫時快取,例如我前面提到的「友善」網址。
如果您想快取這些「友善」網址及其 HTML,建議您考量這些網址包含哪些依附元件、這些網址如何快取,以及快取這些網址一段時間可能對您造成的影響。假設 HTML 網頁包含如下圖片:
<img src="/images/foo.jpeg" loading="lazy" />
如果您透過刪除或變更此延遲載入圖片來更新或變更網站,查看快取 HTML 版本的使用者可能會看到錯誤或缺少圖片,因為他們在重新造訪網站時,仍會快取原始 /images/foo.jpeg
。
只要你小心操作,這項政策可能不會對你造成影響。不過,請務必記住,當使用者快取網站時,網站就不再只存在於伺服器上。而是在使用者瀏覽器快取的「片段」中。
一般來說,大多數快取指南都會提到這類設定,例如您要快取一小時、數小時等等。如要設定這類快取,請使用類似以下的標頭 (快取時間為 3600 秒,即一小時):
Cache-Control: max-age=3600,immutable,public
最後一點是,如果您正在製作時效性內容,使用者通常只會存取一次 (例如新聞文章),我認為這些內容不應快取,您應使用上述合理的預設值。如果使用者希望隨時看到最新、最優質的內容,例如新聞報導或時事重大更新,我們經常會高估快取的價值。
非 HTML 選項
除了 HTML 以外,中間區域的檔案還有以下幾個選項:
一般來說,請找出不影響他人的素材資源
- 例如:避免使用 CSS,因為這會導致 HTML 呈現方式發生變更
用於時事文章的大型圖片
- 使用者可能不會多次造訪任何一篇文章,因此請勿永久快取相片或主圖片,以免浪費儲存空間
代表本身具有生命週期的資產
- 天氣相關的 JSON 資料可能每小時才發布一次,因此您可以將先前的結果快取一小時,因為在您指定的時間範圍內,這項資料不會變更
- 開放原始碼專案的建構作業可能會受到速率限制,因此請快取建構狀態圖片,直到狀態可能變更為止
摘要
如果使用者第二次載入網站,您就很有信心,吸引他們回來觀看更多產品或服務。此時,您不只要縮短載入時間,還可以使用多種選項,確保瀏覽器只執行必要作業,提供快速且即時的使用體驗。
快取並非網頁上的新概念,但可能需要合理的預設值。建議您在需要時使用預設值,並強烈選擇加入更完善的快取策略。感謝您閱讀本信!
另請參閱
如需 HTTP 快取的一般指南,請參閱「透過 HTTP 快取防止不必要的網路要求」。