Browser / CDN Cache 怎麼運作?
HTTP Cache 會根據 Response Headers(主要是 Cache-Control),以及 HTTP 狀態碼等條件,決定回應是否可以儲存,以及能否直接重用。
常見 Cache-Control directives
- 未指定 Cache-Control:不代表不能快取。符合條件的回應仍可能使用 heuristic caching(啟發式快取)來決定 freshness。
- no-cache:允許儲存,但每次重用前必須重新驗證(revalidate),不能直接使用快取內容。
- no-store:禁止儲存這份回應。
- max-age=3600:回應在 3600 秒內可視為 fresh,通常可以直接重用。
- s-maxage=3600:共享快取(例如 CDN)的 freshness lifetime 為 3600 秒,會覆寫共享快取使用的 max-age。
- private:只允許私有快取儲存,禁止共享快取儲存。
- public:明確允許共享快取儲存回應(仍受其他快取規則限制)。
- immutable:表示資源在 fresh 期間內容不會改變,可以避免不必要的重新驗證。
快取類型
- Private Cache:通常是 Browser Cache,只供特定使用者使用,可以快取個人化內容。
- Shared Cache:例如 CDN、Proxy Cache,可以讓不同使用者共用快取內容。
Freshness
- Fresh:快取仍在有效期限內,通常可以直接重用。
- Stale:快取超過 freshness lifetime,通常需要重新驗證後才能重用。
- Revalidation:確認既有快取內容是否仍有效。若內容未變更,可回傳 304,避免重新傳輸完整內容。
Age 表示回應的估計年齡,可搭配 max-age 或 s-maxage 判斷快取是否仍然 fresh。
例如:
Cache-Control: public, max-age=0, s-maxage=3600
Age: 2400- Browser:
max-age=0,通常需要重新驗證。 - CDN:
s-maxage=3600,在此情境下仍可將回應視為 fresh。 Age: 2400:回應已有約 2400 秒的年齡,因此 CDN 約剩 1200 秒的 freshness。
no-cache 與 ETag 驗證流程
假設伺服器提供 ETag:
- 第一次請求,伺服器回傳
200 OK、完整內容,以及ETag: "v1"。 - 下次需要重新驗證時,瀏覽器可以送出
If-None-Match: "v1"。 - 如果內容沒有改變,伺服器回傳
304 Not Modified,瀏覽器可以重用快取內容。 - 如果內容改變,伺服器回傳
200 OK與新內容,並提供新的 ETag。
ETag 是資源表示內容的驗證識別碼,不一定等於應用程式版本。
重新驗證也可以使用 Last-Modified 與 If-Modified-Since。
注意:如果中間有 CDN,Browser 可能先向 CDN 驗證;由 CDN 決定是否需要進一步聯繫 origin。
s-maxage
s-maxage 只作用於 Shared Cache(例如 CDN),Private Cache 會忽略它。
例如:
Cache-Control: public, max-age=0, s-maxage=3600代表 Browser 通常每次都需要重新驗證,但 CDN 在回應仍 fresh 時,可以直接使用快取,不必重新聯繫 origin。
如何避免 SPA 部署後看到舊版?
核心策略:固定 URL 的入口 HTML 需要重新驗證;帶有 content hash 的靜態資源可以長期快取。
1. HTML:使用 no-cache
Cache-Control: no-cache適合 index.html 等 URL 固定、內容會隨部署更新的資源。
如果是使用者專屬的 HTML,可以考慮:
Cache-Control: private, no-cache如果內容高度敏感、不應儲存,則評估使用 no-store。
2. JS / CSS:使用 Cache Busting
Cache-Control: public, max-age=31536000, immutable例如:
app.a1b2c3.jsapp.d4e5f6.js
內容改變時,檔名中的 hash 也跟著改變,產生新的 URL。
因此舊版資源可以長期快取,而新版 HTML 會引用新的資源 URL。
3. CDN 快取與部署流程
即使 JS/CSS 使用 content hash,如果 CDN 持續提供舊版 index.html,使用者仍可能看到舊版本。
改善方向:
- 確認 HTML 的 Browser / CDN Cache-Control 設定。
- 部署時先確保新版 JS/CSS 已可被取得,再發布新版 HTML。
- 必要時使用 CDN Purge / Invalidation,讓舊版 HTML 快取失效。
- 透過 DevTools Network 檢查
Cache-Control、Age、ETag、304、CDN cache status 等資訊。
總結
no-cache:允許儲存,但重用前必須驗證。no-store:禁止儲存。max-age:控制 freshness lifetime。s-maxage:控制共享快取的 freshness lifetime。Age:回應的估計年齡。ETag / 304:減少重新驗證時的資料傳輸。Content Hash + immutable:適合長期快取的靜態資源。
參考資料
- MDN — HTTP Caching: https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Caching
- MDN — Cache-Control: https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Cache-Control
- RFC 9111 — HTTP Caching: https://www.rfc-editor.org/rfc/rfc9111.html