Pages 與 Static Assets 總覽:全端託管選型 | Cloudflare 完整教學

2026/09/12
Pages 與 Static Assets 總覽:全端託管選型 | Cloudflare 完整教學

這一篇要幫你把 Cloudflare 的「前端與全端託管」講清楚。你可能聽過 Cloudflare Pages,也聽過比較新的 Workers Static Assets——它們都能把你的網站放上 Cloudflare 全球網路,但定位不同、官方態度也不同。這篇不鑽細節,而是先建立一張「地圖」:兩者各是什麼、差在哪、官方為何主推 Workers、Pages Functions 與一般 Worker 的分別,以及你該怎麼選、既有專案怎麼遷移。這是 CF-6 全端與周邊系列的開場總覽,細節留給接下來的文章。

前言

上一篇《Agents SDK:即時 WebSocket 與 React》,我們讓 Agent「活了起來」——做出一個逐字浮現的即時聊天前端,還把 React 打包後的靜態資源用 assets 綁定放上線。那時我們其實已經偷偷用到了本篇的主角:Workers Static Assets。這一篇,就把「靜態託管」這件事攤開來好好講。

先說一個很多人會踩到的困惑:我要把一個 React、Vue、Astro 或純 HTML 的網站放上 Cloudflare,到底該用什麼?搜尋一下你會看到兩個名字——Cloudflare PagesWorkers Static Assets。它們看起來都在做同一件事(託管前端),但你如果隨便選一個,可能會走進一條「官方已經不再積極維護」的路,或是把簡單的事搞複雜。所以在動手之前,先弄懂這張地圖非常值得。

先給一句話定義:

Cloudflare Pages 是較早推出的 JAMstack 靜態網站託管平台,主打 Git 自動部署與預覽環境;Workers Static Assets 則是後來讓 Cloudflare Worker「同時托管靜態資源與動態邏輯」的能力。2025 年後 Cloudflare 官方明確表態:Pages 進入維護模式(持續支援但不再積極開發新功能),所有新的投資都放在 Workers,新專案一律建議使用 Workers Static Assets。

這裡有幾個關鍵詞先埋下伏筆。JAMstack——JavaScript、API、Markup 的縮寫,指的是「前端建置成靜態檔案 + 透過 API 取得動態資料」的架構風格,這是 Pages 誕生時的定位。Static Assets——就是你的網站建置後產出的那一堆靜態檔案(HTML、CSS、JS、圖片)。維護模式——不是「淘汰下線」,而是「還會養、但不再長新功能」。

打個比方會更好懂。你可以把 Cloudflare Pages 想成一台「專門烤吐司的烤麵包機」:插電、放吐司、按下去,簡單好用,做靜態網站這件事它做得很順。而 Workers Static Assets 則像一台「多功能烤箱」:它一樣能烤吐司(純靜態託管),但你需要的時候還能烤雞、燉菜、做甜點(動態 API、WebSocket、排程、資料庫)。過去 Cloudflare 賣兩台機器,現在他們決定:未來只認真升級那台多功能烤箱,烤麵包機還能用,但不會再出新型號了。所以新廚房該買哪一台,答案很清楚。

讀完這篇你會掌握:

  • Cloudflare Pages 是什麼——它的核心特色(Git 部署、預覽環境、Pages Functions)與適用場景。
  • Workers Static Assets 是什麼——它怎麼用一個 Worker 同時扛靜態與動態,以及 assets 綁定的角色。
  • 官方方向與選型——為什麼 Pages 進入維護模式、新專案該選什麼、既有專案要不要遷移。
  • Pages Functions vs 一般 Worker——兩者的路由模型與能力差異,別再搞混。

核心概念

一、Cloudflare Pages:JAMstack 靜態託管平台

Cloudflare Pages 是 Cloudflare 推出較早的前端託管平台,主打「連上 Git、推程式碼就自動部署」的體驗。它最受歡迎的幾個特色是:

  • Git 整合(Git Integration)——連接 GitHub 或 GitLab,每次 push 自動觸發建置與部署,不用手動上傳。
  • 預覽部署(Preview Deployments)——每個 branch 或 Pull Request 自動產生唯一的預覽 URL(格式 <branch>.<project>.pages.dev),讓你在合併前先看效果。
  • Pages Functions——在 Workers 執行環境上跑的 serverless 函式,讓靜態網站也能有後端 API,支援 KV、D1、R2 等綁定(bindings)。
  • 即時回滾(Instant Rollback)——一鍵還原到任意歷史版本。
  • 全球 CDN——靜態資源自動分發到 Cloudflare 全球 300 多個資料中心。

這些能力讓 Pages 一度是 Cloudflare 上做前端的首選。它把「靜態網站 + 少量後端」這條路走得很順。

二、Workers Static Assets:一個 Worker 扛全部

Workers Static Assets 是後來 Cloudflare 幫 Worker 加上的能力:讓一個 Worker 同時托管靜態資源與動態邏輯。過去你需要 Pages 才能做到的「靜態網站託管」,現在直接寫在 Worker 的設定裡就有了。

它的運作原理是這樣的:

  1. 你把建置好的靜態資源(HTML、CSS、JS、圖片)透過 wrangler.jsonc 裡的 assets.directory 指定目錄,部署時一起上傳到 Cloudflare 的資源儲存系統。
  2. Cloudflare 自動快取這些資源,並在全球邊緣節點提供(自動壓縮、附 ETag)。
  3. 你的 Worker 程式碼可以透過 env.ASSETS 這個綁定去存取這些資源。
  4. 透過 run_worker_first 設定,你可以決定哪些路由「先進 Worker 處理」、哪些「直接回靜態檔案」。

一張圖看懂請求怎麼走:

Request 進入
     ↓
是否符合 run_worker_first 設定?
├─ 是 → 執行 Worker → Worker 可呼叫 env.ASSETS.fetch() 取得靜態資源
└─ 否 → 直接查找靜態資源
         ├─ 找到 → 回傳靜態資源(自動壓縮、快取)
         └─ 找不到 → 依 not_found_handling 設定處理(SPA 回 index.html / 404 頁 / 直接 404)

關鍵是:如果你不需要後端,連 Worker 程式碼都不用寫——只設定 assets.directory 就是一個純靜態網站。而當你需要 API 時,補上一個 Worker 入口就升級成全端應用,不用換平台。

三、Pages vs Workers Static Assets 對照表

這是本篇最該記住的一張表。除了功能差異,最上面兩列「維護狀態」與「建議用途」是官方態度的核心:

面向Cloudflare PagesWorkers Static Assets
維護狀態持續支援,但不再積極開發新功能主要投資方向
建議用途既有 Pages 專案所有新專案
Git 整合部署原生支援Workers Builds
預覽部署 URL支援Workers Builds
靜態資源托管支援支援
Serverless 函式Pages Functions原生 Worker
Durable Objects不支援支援
Cron Triggers不支援支援
Queue Consumers不支援支援
WebSocket僅限 Advanced Mode原生支援
Gradual Deployments不支援支援
進階 Observability有限完整

看出重點了嗎?凡是「綁在 Worker 上的進階能力」(Durable Objects、Cron、Queue、原生 WebSocket),Pages 幾乎都沒有,而 Workers Static Assets 全都有。 這正是官方把資源集中到 Workers 的原因——與其維護兩套,不如讓 Workers 一套通吃。

四、官方方向:為什麼 Pages 進入維護模式

2025 年初,Cloudflare 官方部落格說了一句很關鍵的話:

“Cloudflare Pages will continue to be supported, but, going forward, all of our investment, optimizations, and feature work will be dedicated to improving Workers.”

翻成白話:Pages 會繼續支援,但往後所有的投資、優化與新功能開發,都會投注在改進 Workers 上。 這句話拆開來理解:

  • Pages 不會下線,現有專案不受影響,照常運作、照常部署。
  • 新功能、效能優化、框架整合的重心已全部轉移到 Workers Static Assets
  • 過去 Pages 獨有的優勢(靜態託管、SSR、Git 部署、預覽環境)Workers 現在都有了——差異化消失,自然收斂到一套。
  • 官方明確建議:新專案一律優先考慮 Workers,而非 Pages

五、Pages Functions vs 一般 Worker:別再搞混

這是最多人混淆的一點。兩者都跑在 Workers 執行環境上,但寫法與能力不同:

面向Pages Functions一般 Worker(Workers Static Assets)
路由模型基於檔案(functions/ 目錄對應 URL)單一入口(export default { fetch }),路由自己分派
Handler 寫法onRequestGet / onRequestPost一個 fetch(request, env, ctx) 統包
中介層_middleware.ts自己在 fetch 內組合
進階能力受限(WebSocket 需 Advanced Mode)完整(DO、Cron、Queue、WebSocket 原生)
靜態資源存取自動回退透過 env.ASSETS 綁定

一句話總結:Pages Functions 是「Pages 平台幫你包裝好的 Worker」,用檔案路由、方便但受限;一般 Worker 是「完整體」,單一入口、自己掌控路由、能力最全。 官方主推的 Workers Static Assets 用的就是後者。

實作範例

光看表格不夠實感,我們用「同一個目標:把一個 React SPA + 一個 /api 後端放上線」來對照兩種做法的最小設定。你會直接感受到差別。

1. 純靜態:Workers Static Assets 最簡設定

先看最單純的:一個沒有後端的純靜態網站。這是新專案最該優先掌握的起手式——連 Worker 程式碼都不用寫:

// wrangler.jsonc — 純靜態,零 Worker 程式碼
{
  "name": "my-static-site",
  "compatibility_date": "2026-01-01",
  "assets": {
    "directory": "./dist"   // 指向建置輸出目錄即可
  }
}
# 建置你的前端(以 Vite 為例),然後部署
npm run build
npx wrangler deploy
# ↑ 上線後所有請求直接由邊緣節點提供靜態檔案,不計入 Worker 調用次數

就這樣。沒有 main 入口、沒有 Worker 程式碼,Cloudflare 自動幫你壓縮、快取、附 ETag。

2. 全端:Workers Static Assets + Worker 後端

現在加上一個 /api 後端。只要補上 main 入口與 run_worker_first,同一個專案就升級成全端應用:

// wrangler.jsonc — SPA + API 全端設定
{
  "name": "my-app",
  "main": "src/index.ts",              // 補上 Worker 入口
  "compatibility_date": "2026-01-01",
  "assets": {
    "directory": "./dist",
    "not_found_handling": "single-page-application", // 找不到就回 index.html(SPA)
    "run_worker_first": ["/api/*"]     // 只有 /api/* 先進 Worker,其餘直接回靜態
  },
  "d1_databases": [
    { "binding": "DB", "database_id": "your-db-id" }
  ]
}
// src/index.ts — Worker 入口:API 自己處理,其餘交給 ASSETS
interface Env {
  ASSETS: Fetcher;
  DB: D1Database;
}

export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    const url = new URL(request.url);

    // API 路由由 Worker 處理
    if (url.pathname.startsWith("/api/")) {
      const { results } = await env.DB.prepare("SELECT * FROM users").all();
      return Response.json(results);
    }

    // 其餘路由交給靜態資源(SPA 模式下找不到會回 index.html)
    return env.ASSETS.fetch(request);
  },
};

注意 run_worker_first: ["/api/*"] 這個設定的巧妙:只有 /api/* 的請求會先進 Worker(產生調用計費),其他所有靜態檔案的請求直接由邊緣提供、不進 Worker——這對成本控制很重要。

3. 對照:Pages 的做法(既有專案的樣子)

同樣的目標,如果是在 Pages 上,設定與程式碼組織會長這樣——放這裡是為了讓你認得既有 Pages 專案的樣貌:

// wrangler.jsonc — Pages 專用:注意 pages_build_output_dir
{
  "name": "my-pages-project",
  "pages_build_output_dir": "./dist",   // Pages 專屬欄位(不是 assets)
  "compatibility_date": "2026-01-01"
}
// functions/api/users.ts — Pages Functions:檔名即路由,對應 /api/users
import type { PagesFunction } from "@cloudflare/workers-types";

interface Env {
  DB: D1Database;
}

// 檔案路由 + onRequestGet handler,這是 Pages Functions 的招牌寫法
export const onRequestGet: PagesFunction<Env> = async ({ env }) => {
  const { results } = await env.DB.prepare("SELECT * FROM users").all();
  return Response.json(results);
};

對照著看差別就很清楚:Pages 用 pages_build_output_dir 而非 assets、用 functions/ 檔案路由而非單一 fetch 入口。這也是遷移的核心:把 pages_build_output_dir 換成 assets.directory、把 functions/ 目錄的邏輯改寫進 Worker 的 fetch 遷移的完整步驟,我們留到後面幾篇細講。

4. not_found_handling:三種模式一次看

上面用到的 not_found_handling 決定「找不到靜態資源時怎麼辦」,這是靜態託管最常用的設定:

模式行為適用場景
"single-page-application"所有非資源路徑回 /index.html(HTTP 200)React / Vue / Angular SPA
"404-page"若有 /404.html 就回它,否則 404靜態網站(SSG,有自訂錯誤頁)
"none"直接回 404API 優先、完全自訂路由

SPA 一定要用 single-page-application,不然重新整理子路由(例如 /dashboard)就會 404;純靜態部落格(Hugo、Astro SSG)則用 404-page

常見錯誤與最佳實踐

託管選型的坑,大多不在「部署失敗」,而在「一開始選錯路」或「把兩個概念搞混」。以下是最高頻的幾個。

坑一:新專案還在預設選 Pages。

很多教學、範本還停在「用 Pages 做前端」的舊思維,於是新專案一開就選了進入維護模式的平台。正確做法:2025 年後的所有新專案,一律從 Workers Static Assets 起手。 就算你現在只做純靜態網站(用不到 DO、Cron),也該選 Workers——因為它純靜態一樣簡單(三行設定),而且哪天需要長出後端 API 時,補個 main 入口就能無痛升級,不必搬家換平台。一句話:新專案沒有理由選 Pages。

坑二:把 Pages Functions 當成「一般 Worker」,期待它有 Worker 的全部能力。

有人在 Pages Functions 裡想用 Durable Objects、Cron Triggers、原生 WebSocket,結果發現做不到(或得繞 Advanced Mode 的 _worker.js)。正確做法:認清 Pages Functions 是「受平台約束的 Worker」——檔案路由方便,但進階能力受限。 需要那些能力,就直接用 Workers Static Assets 的「一般 Worker」模型。別在 Pages 上硬湊。

坑三:所有請求都設 run_worker_first: true,白白燒 Worker 調用次數。

有人為了省事,把 run_worker_first 設成布林 true,結果連載入圖片、CSS、JS 都先進 Worker,每個靜態請求都算一次 Worker 調用,成本暴增、延遲也上升。正確做法:用陣列模式,只讓真正需要後端的路由先進 Worker(例如 ["/api/*", "/auth/*"]),其餘靜態資源直接由邊緣提供、不計入調用次數。需要排除某些子路徑時,用 ! 前綴(例如 "!/api/docs/*")。

坑四:既有 Pages 專案急著全部遷移。

聽到「Pages 進入維護模式」就恐慌,把運作良好的舊專案全部連夜搬到 Workers——這既沒必要、又容易出錯。正確做法:Pages 不會下線,現有專案照常維護即可,不急於遷移。 真正該遷移的時機是:(1) 你要開新專案;(2) 你的 Pages 專案「撞到能力天花板」(需要 DO、Cron、Queue、原生 WebSocket)。時機到了再遷,而且要按部就班測試。

選型建議小結(一句話決策):

  • 開新專案 → 一律 Workers Static Assets(純靜態就只設 assets.directory,要後端再加 main)。
  • 現有 Pages 專案運作正常留著別動,繼續維護。
  • 現有 Pages 撞到能力天花板 → 規劃遷移到 Workers(pages_build_output_dirassets.directory,functions/ → Worker)。
  • 搞不清 Pages Functions 還是 Worker → 新專案直接用一般 Worker,能力最完整、最不綁死。

小結

上一篇《Agents SDK:即時 WebSocket 與 React》,我們做出了逐字浮現的即時聊天前端,並用 assets 綁定把 React 前端放上線——那其實已經在用本篇的主角。這一篇《Pages 與 Static Assets 總覽》,我們把 Cloudflare 的前端與全端託管地圖攤開來看:

  • Cloudflare Pages——較早的 JAMstack 靜態託管平台,主打 Git 部署、預覽環境、Pages Functions;現已進入維護模式(持續支援但不再積極開發新功能)。
  • Workers Static Assets——讓一個 Worker 同時扛靜態與動態;純靜態只需設 assets.directory,要後端補上 mainrun_worker_first 即可無痛升級,是官方主推、所有新專案的預設選擇
  • Pages Functions vs 一般 Worker——前者是「平台包裝好的 Worker」(檔案路由、能力受限),後者是「完整體」(單一入口、能力全);Workers Static Assets 用的是後者。
  • 選型與遷移——新專案一律 Workers;既有 Pages 專案不急遷移,撞到能力天花板再搬(pages_build_output_dirassets.directory)。

這也是 CF-6 全端與周邊系列的開場——我們把視角從單一功能(AI、儲存、運算)拉高到「怎麼把一個完整的前端與全端應用漂亮地放上 Cloudflare」。下一篇《Workers Static Assets 靜態託管》,我們就把今天總覽帶過的 Workers Static Assets 拆開來實作:assets 的完整選項、html_handling 的 URL 斜線行為、.assetsignore 排除檔、Vite Plugin 整合,一步步把一個靜態網站(以及它未來可能長出的後端)紮實地部署上線。我們下一篇見。

想查閱 Cloudflare 官方對 Pages 與 Workers Static Assets 定位的完整說明與最新設定選項,可以參考 Cloudflare Workers Static Assets 官方文件(設定欄位與官方建議以當下官方文件為準)。

BenZ Software Developer

熱愛技術的軟體開發者,在這裡分享程式開發經驗與學習筆記。

本週主打

AI 自動化入門包

你每天手動在做的那些煩事,其實 AI 可以自己跑。這份給你 10 個照著做就會的自動化工作流 + 50 個複製即用的提示詞,不用會寫程式。

看看這個產品 →