瀏覽器快取和 Cloudflare 快取不是一回事:Cache-Control、Edge TTL 與發布刷新

從瀏覽器快取和 Cloudflare 邊緣快取的差異出發,解釋 Cache-Control、max-age、s-maxage、Edge TTL、Browser TTL、purge all 之間的關係,以及靜態部落格該如何配置快取。

配置 Cloudflare 快取時,最容易混淆的是兩件事:

  • Cloudflare 邊緣節點快取多久。
  • 使用者瀏覽器本地快取多久。

這兩層都和快取有關,但控制對象不同,風險也不同。

對靜態部落格來說,一個比較穩的思路是:Cloudflare 邊緣快取可以激進一點,瀏覽器快取要保守一點。因為 Cloudflare 的快取可以透過後台或 API 清掉,而使用者瀏覽器本地快取無法由站長直接清掉。

先分清三層位置

一次訪問大致經過三層:

1
2
3
4
5
瀏覽器
Cloudflare 邊緣節點
VPS / Nginx / Hugo 靜態檔案

對應的快取也有兩類重點:

  • Browser cache:瀏覽器存在使用者本機的快取。
  • Edge cache:Cloudflare 存在邊緣節點上的快取。

源站 Nginx 返回的 Cache-Control 會影響瀏覽器,也可能影響 CDN。Cloudflare 的 Cache Rules 又可以單獨設定 Edge TTL 和 Browser TTL。再加上 Response Header Transform Rules 還能改最終返回給瀏覽器的響應頭,所以如果不分層,很容易以為「設定了快取」就解決了一切。

Cache-Control 控制的是誰

Cloudflare 學習中心對 Cache-Control 的解釋很直接:它是一個 HTTP 響應頭,用來告訴瀏覽器和中間快取如何處理資源。

常見指令有幾個:

1
Cache-Control: public, max-age=300

含義是:這個響應可以被快取,瀏覽器最多快取 300 秒。

1
Cache-Control: private

含義是:只適合瀏覽器這類私有快取保存,不應該被 CDN 這類共享快取保存。

1
Cache-Control: no-store

含義是:不要快取,適合非常敏感的資料。

1
Cache-Control: no-cache

這個名字容易誤導。它不是完全不快取,而是使用快取前必須先向伺服器確認資源有沒有更新。通常會配合 ETagLast-Modified

1
Cache-Control: s-maxage=86400

s-maxage 面向共享快取,例如 CDN。它可以讓 CDN 快取更久,而瀏覽器仍按 max-age 或其他規則處理。

所以,Cache-Control 不是只給瀏覽器看的,也不是只給 CDN 看的。它是一組快取規則,具體誰採用、誰覆蓋,要看中間層怎麼配置。

Cloudflare Edge TTL 和 Browser TTL 的區別

Cloudflare 裡的兩個 TTL 要分開看。

Edge TTL 決定 Cloudflare 邊緣節點快取多久。

例如:

1
Cloudflare Edge TTL = 1 day

意思是 Cloudflare 可以把頁面、圖片、CSS、JS 等內容存在邊緣節點 1 天。訪客再次請求同一個 URL 時,如果快取命中,Cloudflare 直接返回,不回源到 VPS。

Browser TTL 決定瀏覽器快取多久。

例如:

1
Browser TTL = 5 minutes

意思是瀏覽器收到資源後,本地最多把它當作新鮮資源保存 5 分鐘。5 分鐘內使用者再次訪問,瀏覽器可能直接使用本地快取;超過 5 分鐘後,需要重新驗證或重新請求。

兩者最大的差別是:

  • Edge cache 可以由站長 purge
  • Browser cache 在使用者電腦裡,站長沒法直接清。

因此,HTML 頁面不建議給瀏覽器很長 TTL。否則文章更新後,即使 Cloudflare 已經清快取,使用者瀏覽器仍可能繼續用本地舊頁面。

靜態部落格為什麼適合快取 HTML

動態網站通常不敢隨便快取 HTML,因為頁面可能包含登入狀態、使用者資料、購物車、推薦內容、權限資訊。

靜態部落格不一樣。Hugo 生成的頁面通常是純靜態檔案:

  • 首頁。
  • 文章頁。
  • 分類頁。
  • 標籤頁。
  • 多語言頁面。
  • RSS。
  • sitemap。

這些內容對所有訪客基本一樣,所以可以讓 Cloudflare 快取 HTML。這樣做能減少回源請求,也能讓海外訪問更快。

但這裡的關鍵是:

1
2
Cloudflare Edge 可以長一點
瀏覽器 Browser 要短一點

例如:

1
2
Cloudflare Edge TTL = 1 day
Browser TTL = 5 minutes

這表示 Cloudflare 可以快取 1 天,但使用者瀏覽器只快取 5 分鐘。

每次發布都 purge all 時,Edge TTL 可以更長

如果發布腳本每次都會呼叫 Cloudflare purge everything,那麼 Edge TTL 可以設得更長。

邏輯是:

1
2
3
平時:Cloudflare 快取 1 天,減少回源
發布:上傳新 public 後 purge all
發布後:Cloudflare 重新回源拿新內容

這種模式適合靜態部落格。因為站點內容不是即時變化,更新動作也集中在部署時。

Edge TTL 設 1 天和 1 個月都可以,差別主要是風險偏好:

  • 1 day:如果某次 purge 失敗,舊內容最多自然保留 1 天。
  • 1 month:快取命中率更高,但 purge 失敗時舊內容可能留更久。

普通個人部落格先用 1 day 更穩。

為什麼不建議瀏覽器也長快取

瀏覽器快取越長,重複訪問越快,但更新越難控制。

比如 HTML 設定:

1
Cache-Control: public, max-age=31536000

使用者訪問一次文章頁後,瀏覽器可能把頁面當作一年內都新鮮。你後面修改錯字、更新連結、修正內容,Cloudflare purge 了也不一定影響這個使用者的本地快取。

靜態資源可以長快取,是因為它們通常帶指紋檔名:

1
2
/scss/style.min.5e5f1f8f7ce389becd0a48fe3eff3e1c79b2750a903584200a3a6fc54ae1e664.css
/ts/main.9acdcb7a78e911f2c617b8cd4af2eab573c04169dddc51c052977dde63210ced.js

內容變了,檔名也變,舊快取不會影響新頁面引用的新檔案。

但 HTML URL 通常不變:

1
/2026/06/13/browser-cache-vs-cloudflare-edge-cache/

所以 HTML 更適合短瀏覽器 TTL。

一種簡單配置

如果希望簡單,不想按檔案類型細分,可以用一套統一策略:

1
2
3
Cloudflare Edge TTL = 1 day
Browser TTL = 5 minutes
每次發布 purge everything

Cloudflare Cache Rule 負責邊緣快取:

1
(http.host in {"knightli.com" "www.knightli.com"} and not starts_with(http.request.uri.path, "/cdn-cgi/"))

動作:

1
2
3
4
Eligible for cache
Edge TTL: 1 day
Browser TTL: 5 minutes
Query string: ignore

如果源站 Nginx 對 CSS/JS/圖片設定了更長的 Cache-Control,而你又希望所有返回給瀏覽器的資源都統一為 5 分鐘,可以在 Cloudflare 再加一條 Response Header Transform Rule:

1
2
3
4
5
Set:
Cache-Control: public, max-age=300

Remove:
Expires

這樣就能做到:

  • Edge 快取由 Cloudflare Cache Rule 控制。
  • Browser 快取由 Cloudflare 響應頭規則統一控制。
  • Nginx 不需要為了瀏覽器 TTL 做統一改動。

什麼時候需要分層快取

如果追求更高性能,可以做分層:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
HTML:
  Edge TTL: 1 day
  Browser TTL: 5 minutes

CSS / JS / 圖片 / 字型:
  Edge TTL: 1 month
  Browser TTL: 1 month 或 1 year

RSS / sitemap:
  Edge TTL: 1 hour
  Browser TTL: 5 minutes

這種配置更細,但維護成本也更高。個人部落格一開始可以不用這麼複雜。

當你確認所有靜態資源都帶 hash 檔名,再把 CSS/JS/圖片的 Browser TTL 拉長,會更穩。

如何驗證是否生效

可以用 curl -I 連續請求同一個 URL:

1
2
curl.exe -I https://knightli.com/
curl.exe -I https://knightli.com/

重點看兩個頭:

1
2
cf-cache-status: HIT
cache-control: public, max-age=300

cf-cache-status: HIT 說明 Cloudflare 邊緣快取命中。

cache-control: public, max-age=300 說明瀏覽器端最多快取 300 秒。

如果看到:

1
cf-cache-status: MISS

可能是第一次訪問、剛 purge 過、規則還沒生效,或者這個資源不符合快取條件。再請求一次通常能看到 HIT

如果 CSS/JS 仍顯示:

1
cache-control: public, max-age=31536000, immutable

說明瀏覽器快取頭仍由源站或某條更高優先級規則控制。要麼接受靜態資源長快取,要麼用 Cloudflare Response Header Transform Rule 覆蓋。

小結

瀏覽器快取和 Cloudflare 快取不是一回事。

最實用的判斷是:

  • Cloudflare Edge 快取可以激進,因為站長能 purge。
  • 瀏覽器快取要謹慎,因為站長不能清使用者本地快取。
  • HTML 頁面適合短 Browser TTL。
  • 帶 hash 的靜態資源可以長 Browser TTL。
  • 靜態部落格如果每次發布都 purge all,Edge TTL 設 1 天是一個穩妥起點。

對 Hugo 靜態部落格來說,先用:

1
2
3
Cloudflare Edge TTL = 1 day
Browser TTL = 5 minutes
每次發布 purge everything

就已經能獲得大部分 CDN 加速收益,同時避免文章更新後長期顯示舊頁面。

參考連結

记录并分享
使用 Hugo 建立
主題 StackJimmy 設計