編按:本文綜合整理自 Cloudflare 官方部落格、Cloudflare Workers 定價頁 與 Astro 7 發布公告,並加入 Siami 編輯部觀點與分析。
Cloudflare 正式推出 Workers Cache:一個位於 Worker 前方的分層快取(tiered cache),只要在 wrangler.jsonc 加一行 "cache": { "enabled": true },就能用既有的 Cache-Control header 控制整個快取行為。這是 Workers 平台自 2017 年推出以來,在快取架構上最大的翻新。
一行設定就啟動的分層快取
過去 9 年,Cloudflare Workers 的架構是「Worker 站在快取前面、再站在 origin 前面」。這套設計適合做 header 改寫、URL 重寫、A/B 切換等請求前處理。
但世界變了。Astro、TanStack Start、Next.js、Remix、SvelteKit 這些主流框架都內建 Cloudflare adapter,整個 app 編譯成 Worker 部署,後面沒有 origin,Worker 自己就是 origin。這種情況下舊架構沒東西可快取 — 每個請求都跑程式碼,即使回應內容與一秒前一模一樣。
Workers Cache 把架構翻轉過來,Cloudflare 的快取現在站在 Worker 前面:
{
"name": "my-worker",
"main": "src/index.ts",
"compatibility_date": "2026-05-01",
"cache": {
"enabled": true
}
}
之後用熟悉的 Cache-Control header 控制:
return new Response(body, {
headers: {
"Cache-Control": "public, max-age=300, stale-while-revalidate=3600",
"Cache-Tag": "products,product:123",
},
});
要清快取也直接在 Worker 裡做:
await ctx.cache.purge({ tags: ["product:123"] });
整個 API 就這樣。沒有 zone 設定、沒有 rule engine、沒有第二個產品要登入。Worker 寫在哪裡、快取就跟到哪裡 — custom domain、workers.dev、service binding、preview URL、Workers for Platforms 租戶都適用。
為什麼伺服器渲染的 app 需要前面一層快取
當 Worker 就是 origin 的時候,每個頁面載入都等於一次 render。即使 Workers runtime 已經很快(每秒處理數千萬次請求都不是問題),「每次都 render」還是有延遲成本與 CPU 時間成本。
過去要選邊站:
- 靜態站點生成(SSG):頁面快,但每次改內容都要 rebuild。文件站幾千頁要 5-10 分鐘;大型電商網站更慘,動一個地方就要整個 rebuild。
- 每次請求都 render:內容永遠最新,但每個訪客都要付 render 成本與延遲。
Workers Cache 提供第三條路:按需 server-render、把 render 結果快取、依照設定的 TTL 重新整理。第一次請求某個新頁面時還是會 render,但之後直到快取過期前,都像靜態頁面一樣被送出來。
這不是框架特定機制(像 Next.js 的 ISR 那些),就是照 RFC 9110 / RFC 9111 設計的標準 HTTP 快取,運作在設計來當 origin 的程式碼前面。
stale-while-revalidate 讓 SSR 站點感覺像靜態
stale-while-revalidate 是 Workers Cache 真正讓網站「感覺是靜態」的關鍵。沒有它,快取過期後第一個請求要等 Worker 從頭 render,使用者會看到延遲。有了它,過期後第一個請求立刻拿到舊版(response header 會標 Cf-Cache-Status: UPDATING),Worker 在背景重新 render。每位使用者都拿到快取速度的回應,包含觸發 refresh 的那一位。
實務上的時程模型:
- Fresh window(
max-age內):命中快取,Worker 不跑。 - Stale window(
stale-while-revalidate內):命中快取,Worker 在背景 refresh,使用者零等待。 - 都過期:Worker 重新 render,使用者等待那一次 render。
商品目錄每幾分鐘更新:max-age=300, stale-while-revalidate=3600,訪客基本上不會等待。部落格文章幾乎不變:max-age=86400, stale-while-revalidate=2592000,每頁每天只跑 Worker 一次。
Vary 標頭支援:同一 URL、多種內容
實務上同一個 URL 可能要回 HTML 給瀏覽器、JSON 給 API client;同一張圖可能要 WebP 給支援的 client、JPEG 給不支援的;同一個首頁可能要英文、法文、日文。沒快取時 Worker 讀 request header 回對的就好,有快取時這通常會變醜 — 多數快取要嘛不快取這種 URL,要嘛只快取一種版本然後發給所有人。
Workers Cache 支援標準 HTTP Vary header:Worker 回 Vary: Accept-Encoding(或 Accept、Accept-Language)時,Cloudflare 對每種 header 組合分開存一份快取變體。瀏覽器送 Accept: image/webp,*/* 拿到 WebP;送 Accept: image/jpeg 拿到 JPEG。兩種都從快取來,第一次之後 Worker 完全不跑。
export default {
async fetch(request) {
const accept = request.headers.get("Accept") ?? "";
const wantsWebp = accept.includes("image/webp");
const body = wantsWebp ? await fetchWebpImage() : await fetchJpegImage();
return new Response(body, {
headers: {
"Content-Type": wantsWebp ? "image/webp" : "image/jpeg",
"Cache-Control": "public, max-age=3600",
Vary: "Accept",
},
});
},
};
沒有「允許 Vary 哪些 header」的白名單限制,照 RFC 9110 / RFC 9111 實作。
這是 Worker 的快取、不是 zone 的快取
這裡有個概念上的轉變要釐清:Cloudflare 一直都有 zone 等級的快取 — Cache Rules、Page Rules、cached-file-extensions list、Cache Reserve、Tiered Cache topology。全部都是 zone 設定,Worker 要嘛配合 zone 的設定、要嘛繞過。
Workers Cache 不一樣。它是 Worker 的快取、不是 zone 的快取,這個差別帶來幾個重要的結果:
- 沒有 zone 設定要管理。Cache Rules、cache level 設定、Page Rules 都不套用 Workers Cache。Worker 的
Cache-Controlheader 就是設定。 - 快取跟著 Worker 跑、不是跟著 hostname 跑。Worker 綁在
api.example.com、api.example.net、用 service binding 呼叫時,三個入口共用同一個快取。 - 連
workers.dev都有快取。Preview URL 每個有自己獨立快取(測試改動不會汙染正式環境)。Workers for Platforms 租戶的每個 user Worker 也有獨立快取。 - 清快取範圍是 Worker entrypoint。
ctx.cache.purge({ purgeEverything: true })只清特定 Worker,不會動到 zone 其他內容、不會影響別的 Worker。
兩層分層、每個 Worker 預設啟用
Workers Cache 預設是區域分層(regionally tiered):
- 下層:離使用者最近的 Cloudflare 機房,每個機房有自己的下層快取。
- 上層:橫跨整個網路的聚合層,數量較少,所有下層錯過時都會問它。
請求先打下層。命中就送出回應,沒事。沒命中下層去問上層;上層命中就回應、也順便存到下層。兩層都沒命中時 Worker 才真的跑,那次的回應會存到兩層。
這個設計重要的地方在於:世界上任何地方的第一個請求會填滿上層,之後任何機房來的請求都能從上層拿到,即使那個機房從沒見過這個請求。命中率比單層快取高非常多 — 這正是 Worker 當 origin 時最需要的。
而且這個 Tiered Cache 不用設定。沒有「幫某個 Worker 開 tiered cache」的對話框,開了 caching 的 Worker 都自動享有分層。
如果 Worker 用 Smart Placement 跟資料庫同邊執行,快取會跟它乾淨地組合:先查快取、兩層都沒命中才讓 Smart Placement 把執行路由到資料庫那邊。
🚨 為什麼這件事重要
Workers Cache 的發布對 Cloudflare 平台有三層意義,不只是「多一個快取開關」。
第一層:把 Cloudflare 從 CDN 升級成完整應用平台。 過去 9 年 Workers 一直被定位為「在 CDN 前面跑的程式」,但 Astro、Next.js 等 SSR 框架興起後,Worker 自己就是 origin 的場景越來越多。沒有快取在 Worker 前面,SSR 站點就只能在「貴、慢但即時」跟「便宜、快但要 rebuild」之間二選一。Workers Cache 把這個 false dilemma 消掉 — 對手 Vercel、Netlify 都靠 ISR 跟 edge functions 模擬類似效果,但都是框架綁定的 workaround;Cloudflare 用標準 HTTP header 做到同一件事,這是協議級的優勢。
第二層:解決多租戶 SaaS 的快取隔離痛點。 ctx.props 進 cache key 這個設計,讓認證後的 API 終於可以安全地快取 — 過去 CDN 要嘛用 user token 當 cache key(命中率慘)、要嘛每個請求都打回 origin 做授權(成本慘)。Workers Cache 讓多租戶 API 第一次之後走快取、又不會有 A 用戶看到 B 用戶資料的風險。目前市面上似乎沒有其他 CDN 內建提供這個模型,Workers for Platforms 的多租戶客戶會直接受惠。
第三層:把「近使用者」跟「近資料」兩個目標縫合起來。 Cloudflare 的網路覆蓋全球 95% 網路使用者 50ms 內,Smart Placement 讓 Worker 跑到資料庫那邊執行,但這兩塊過去很難在同一個 app 內組合。Workers Cache 透過 service binding 讓 Worker A 跑在邊緣、Worker B 跑在資料中心、A 呼叫 B 時先查 B 的快取,資料中心這一跳只在快取 miss 時付一次。這是架構上的新原語。
數據解讀:成本模型
根據 Cloudflare Workers 定價頁 與 Workers & Pages 方案:
| 項目 | Free | Paid($5/月起) |
|---|---|---|
| 月請求額度 | 10 萬次/天 | 1,000 萬次/月 |
| 額外請求 | — | $0.30 / 百萬次 |
| CPU 時間 | 包含 | 3,000 萬 ms/月,額外 $0.02 / 百萬 ms |
| Cache hit | 算請求、不耗 CPU | 同上 |
Workers Cache 命中只算請求、不算 CPU 時間。一個被快取命中的請求只付 $0.30 / 百萬次;render 一次可能要花數十到數百 ms CPU($0.02 / 百萬 ms)。對 SSR app 來說,每 1% 命中率提升就是直接成本下降。
實務估算:一個產品頁 50ms CPU、每秒 1000 請求、20% 命中率提升 → 每月省下約 $260 CPU 成本(簡化估算公式:$0.02 × 50ms × 1000rps × 30天 × 命中率提升)。對電商、文件站、API 服務這些高重複內容的場景,回本速度以小時計。
框架整合與下一步
Astro 7 已經內建整合 Workers Cache(Astro 7 發布公告)。Cloudflare 跟其他框架維護者合作,要把類似整合加進 TanStack Start、Next.js(透過 Vinext)。
Workers Cache 推出時所有付費方案都可用(Free plan 也有,但暫時套用 512 MB 快取大小限制,未來會依方案調整)。
Cloudflare 預告的下一步:
- 更大回應大小限制:目前全部方案都用 Free 的 512 MB 上限,等 rollout 完成後會依方案套標準快取大小限制。
- 框架整合擴展:TanStack Start、Next.js(Vinext)。
ctx.cache.invalidate()API:讓對應的快取回應表現得像過期,下一個請求還能用stale-while-revalidate拿到舊版、Worker 在背景重新填滿。purge是直接刪除;invalidate是標記過期但保留 — 給「想重新 render 但不要使用者等待」這個場景用。
上手方式
在 wrangler.jsonc 加上 "cache": { "enabled": true }、重新部署、開始設 Cache-Control header 就好。完整 Workers Cache 文件 涵蓋 quickstart、cache key、purging、composition patterns 跟除錯。
Workers 曾經只能站在快取前面。現在也能站在快取後面。看 app 需要哪一邊 — 或透過 service binding 兩邊都用。
官方公告全文:Cloudflare Blog: Your Worker can now have its own cache in front of it(Dan Lapid 與 Connor Harwood 撰寫,2026-07-06 發布)。
網友熱門留言 (5)