框架整合:把 Next.js、React、Astro 部署到 Workers | Cloudflare 完整教學

2026/09/14
框架整合:把 Next.js、React、Astro 部署到 Workers | Cloudflare 完整教學

這一篇要教你把主流前端框架部署到 Cloudflare Workers。上一篇我們把 Workers Static Assetsassets 設定一行一行拆開來實作;這一篇就把這些設定套用到真實框架上——從 create-cloudflare(C3)起手,逐一看 Next.js(@opennextjs/cloudflare)、React/Vite、Astro、Remix、Hono 各自的整合方式與適配器(adapter),說清楚 SSR 與靜態的差別,以及用錯 adapter、Node API 相容、edge runtime 這些常見坑。本篇也為整個 Pages 段落作收尾。

前言

上一篇《Workers Static Assets 靜態託管》,我們把 wrangler.jsonc 裡的 assets 設定攤開來,一行一行講清楚:directory 指向建置輸出、not_found_handling 決定找不到檔案怎麼辦、run_worker_first 控制哪些路由先進 Worker、main 補上後端邏輯。那一篇教的是「手工設定」;但實際開發時,你不會手刻這些檔案——你會用一個框架(React、Next.js、Astro……),讓它的官方適配器幫你自動產生這些設定

先給一句話定義:

框架整合(Framework Integration)指的是:透過各框架的官方 Cloudflare 適配器(adapter)或建置設定,把框架的建置產物(靜態檔案 + 伺服器端程式碼)自動對應到 Workers 的 assets.directorymain 入口,讓你用熟悉的框架語法開發,卻部署在 Cloudflare 的全球邊緣網路上。

打個比方會更好懂。上一篇的 assets 設定,就像一台通用的引擎與底盤;而框架適配器,就是為不同車型(Next.js、Astro、Remix)量身打造的變速箱——它把框架這具「引擎」的輸出,精準地接到 Workers 這副「底盤」上。React/Vite 這種純靜態產物,引擎輸出的是「已經做好的成品」(靜態 HTML/JS),幾乎不用變速箱,直接放上底盤就能跑;而 Next.js、Astro SSR 這種要「每次請求即時產生 HTML」的,就得靠對應的適配器把伺服器端邏輯翻譯成 Workers 看得懂的 main 入口。選對變速箱(adapter),車才跑得順;選錯(例如用了給 Pages 的舊 adapter),就會格格不入。

讀完這篇你會掌握:

  • C3 起手式——用 npm create cloudflare@latest 一鍵建立各框架的 Workers 專案骨架。
  • 靜態 vs SSR 的判斷——哪些框架/模式是純靜態(不用 adapter)、哪些是 SSR(需要 adapter 產生 main)。
  • 五大框架的整合方式——Next.js(@opennextjs/cloudflare)、React/Vite、Astro、Remix、Hono 各自怎麼接。
  • 常見坑——用錯 adapter、Node API 相容(nodejs_compat)、SSR 與 edge runtime 的取捨。

核心概念

一、一切的分水嶺:純靜態 vs 需要伺服器

在談任何框架之前,先建立最重要的一條判斷線:這個框架的產物,是「純靜態」還是「需要伺服器端執行」? 這條線決定了你需不需要 adapter、wrangler.jsonc 要不要寫 main

  • 純靜態(SSG / SPA):建置時就把所有 HTML(或一個 SPA 的 index.html)產好,執行期不需要跑任何框架程式碼。只需要 assets.directory,不需要 adapter、不需要 main 例如 React/Vite 的 SPA、Astro 的 output: 'static'、Hugo/Jekyll。
  • SSR(伺服器端渲染):每次請求都要在伺服器端執行框架程式碼、即時產生 HTML。需要一個 Cloudflare adapter 把框架的 server 產物翻譯成 Workers 的 main 入口。 例如 Next.js 的 SSR、Astro 的 output: 'server'、Remix。

一句話總結這張對照:adapter 的本質,就是「幫框架產生 Workers 的 main 入口」的工具。純靜態框架不需要 main,自然也不需要 adapter;有 SSR 才需要。

這條分水嶺為什麼這麼重要?因為它直接決定了你的部署成本與複雜度。純靜態站的每個請求都由邊緣直接提供、不計入 Worker 調用次數(這正是上一篇強調的「靜態請求免費」),而且沒有伺服器端程式碼,幾乎不可能出現執行期錯誤。SSR 則相反:每次請求都要跑框架程式碼,會計入調用、也可能因為 Node API 相容或資料庫查詢而出錯。因此在動手整合任何框架前,先問自己一個問題:這個網站的內容,是「建置時就固定好」,還是「每次請求都可能不同」? 部落格、文件、行銷頁多半屬於前者(純靜態);而需要登入、個人化、即時資料的應用則屬於後者(SSR)。判斷清楚了,後面選 adapter、寫設定才不會走冤枉路。

二、各框架整合方式對照表

下表把主流框架在 Workers 上的整合方式整理成一覽(套件名稱與版本細節請以各框架官方文件為準):

框架整合方式是否需要 adapter對應 wrangler.jsonc
React + Vite(SPA)assets + 選用 @cloudflare/vite-plugin否(純靜態)只設 assets.directory + not_found_handling
Next.js@opennextjs/cloudflare 適配器main 指向 .open-next/worker.js
Astro(SSR)@astrojs/cloudflare 適配器main 指向 dist/server/entry.mjs
Astro(靜態)無 adapter,output: 'static'只設 assets.directory
RemixWorkers 適配器(C3 產生)main 指向 server 產物
Hono原生執行,無需 adapter否(直接跑)main 指向你的 Hono app
SvelteKit@sveltejs/adapter-cloudflareadapter 自動產生
NuxtNitro preset: 'cloudflare-module'是(Nitro 內建)preset 自動產生

幾個關鍵術語先講清楚:

  • adapter(適配器):框架與部署平台之間的翻譯層,負責把框架的 build 產物轉成目標平台(這裡是 Workers)的格式。
  • @opennextjs/cloudflare:部署 Next.js 到 Workers 的官方適配器。注意它與舊版 @cloudflare/next-on-pages(部署到 Pages)不同,新專案用前者。
  • bindings:Workers 的資源綁定(D1、KV、R2、AI……)。各框架都提供了在 server 端(如 Server Components、loader、API route)存取 env 的方式,語法各有不同。

三、bindings 在各框架裡怎麼拿

框架整合不只是「跑起來」,還要能在框架的伺服器端程式碼裡存取 Cloudflare 的 bindings。各框架的取用入口不同,先有個印象:

  • Next.js:import { getCloudflareContext } from '@opennextjs/cloudflare',再 const { env } = await getCloudflareContext()
  • Astro:Astro.locals.runtime.env
  • Remix:loader 的 context.cloudflare.env
  • SvelteKit:platform.env(在 +page.server.ts 等 server load 裡)。
  • Hono:handler 的 c.env

實作範例

理論看完,我們用「由簡到繁」的順序,把各框架的最小整合實際寫出來。

1. C3 起手式:一鍵建立框架專案

不論你要用哪個框架,最省事的起點都是 create-cloudflare(C3)——它會幫你選框架、裝依賴、產生 wrangler.jsonc 與正確的 adapter 設定:

# 互動式:會問你要哪個框架、要不要部署
npm create cloudflare@latest my-app

# 直接指定框架(範例:Next.js、React、Astro、Remix)
npm create cloudflare@latest my-next-app -- --framework=next
npm create cloudflare@latest my-react-app -- --framework=react
npm create cloudflare@latest my-astro-app -- --framework=astro
npm create cloudflare@latest my-remix-app -- --framework=remix

C3 產生的專案已經幫你把 assetsmain、adapter、compatibility_flags 都設好了。如果你是全新專案,強烈建議直接用 C3,而不是自己從零手刻設定。(可用的 --framework 選項與其預設會隨版本調整,請以 C3 當下的互動選單或官方文件為準。)

為什麼建議用 C3 而不是手工設定?因為每個框架的建置產物路徑、需要的 compatibility_flags、adapter 版本搭配都有各自的細節,手動抄設定很容易漏掉一兩處(最常見的就是漏開 nodejs_compat,或把 main 指錯目錄)。C3 會依你選的框架自動裝上正確的 adapter、產生對應的 wrangler.jsoncpackage.json 指令,還會問你要不要順便部署。換句話說,C3 把上一篇我們手工拆解的那些 assetsmain 設定「自動化」了——你只需要專注在寫應用程式,不用記每個框架的設定慣例。等專案跑起來後,你仍然可以打開 wrangler.jsonc 微調(例如加上 D1、KV、R2 綁定),但起點交給 C3 最省事、也最不容易出錯。

2. React + Vite:純靜態,不需要 adapter

React/Vite 的預設產物是 SPA(單頁應用),是最單純的情況——不需要任何 adapter,只要把建置輸出設成 assets.directory、開啟 SPA fallback 即可:

// wrangler.jsonc — React/Vite SPA,零 Worker 程式碼
{
  "name": "my-react-app",
  "compatibility_date": "2026-01-01",
  "assets": {
    "directory": "./dist",
    "not_found_handling": "single-page-application"  // 前端路由的必要設定
  }
}
npm run build      # Vite 建置,輸出到 ./dist
npx wrangler deploy

如果想要更順的本地開發體驗(在 vite dev 裡就能存取 bindings),可以加上官方的 @cloudflare/vite-plugin:

// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { cloudflare } from '@cloudflare/vite-plugin';

export default defineConfig({
  plugins: [
    react(),
    cloudflare()   // 讓 vite dev 模擬 Workers 執行環境與 bindings
  ]
});

這個 plugin 屬於「錦上添花」——沒有它,純靜態 React 一樣能部署;有了它,開發時能就近測試 env.DBenv.KV 等綁定。

3. Next.js:@opennextjs/cloudflare 適配器

Next.js 是最需要 adapter 的框架,因為它有 SSR、Server Components、Route Handlers、ISR 等大量伺服器端功能。官方適配器是 @opennextjs/cloudflare(部署到 Workers);舊版 @cloudflare/next-on-pages(部署到 Pages)已不建議用於新專案。

新專案最快的路是用 C3;現有專案則用適配器提供的遷移指令:

# 新專案(C3 會裝好 @opennextjs/cloudflare)
npm create cloudflare@latest my-next-app -- --framework=next

# 現有 Next.js 專案遷移(指令與旗標請以官方文件為準)
npx @opennextjs/cloudflare migrate

wrangler.jsonc 的重點是 main 指向 open-next 的產物、assets 指向它產出的靜態目錄,並開啟 nodejs_compat:

// wrangler.jsonc — Next.js on Workers(欄位以官方文件為準)
{
  "name": "my-next-app",
  "main": ".open-next/worker.js",       // adapter 產生的 Worker 入口
  "compatibility_date": "2026-08-01",
  "compatibility_flags": ["nodejs_compat"],
  "assets": {
    "directory": ".open-next/assets",   // adapter 產生的靜態資源
    "binding": "ASSETS"
  },
  // ISR 快取(選用):需要一個 R2 bucket
  "r2_buckets": [
    { "binding": "NEXT_INC_CACHE_R2_BUCKET", "bucket_name": "next-cache" }
  ]
}

在 Server Components 或 Route Handler 裡存取 bindings,透過 getCloudflareContext():

// app/api/users/route.ts — 在 Next.js 伺服器端存取 D1
import { getCloudflareContext } from '@opennextjs/cloudflare';

export async function GET() {
  const { env } = await getCloudflareContext();
  const { results } = await env.DB.prepare('SELECT * FROM users').all();
  return Response.json(results);
}

@opennextjs/cloudflare 已支援 App Router 與 Pages Router、React Server Components、Route Handlers、Server Actions,以及 SSG / SSR / ISR。要特別記住:它不支援把路由標成 export const runtime = 'edge'(Edge Runtime)——這點下一節會展開。

4. Astro:內建 Cloudflare 適配器

Astro 很有彈性:純內容站可用 output: 'static'(純靜態,不用 adapter);要 SSR 或混合模式,就加上 @astrojs/cloudflare:

npm create cloudflare@latest my-astro-app -- --framework=astro
# 或在現有 Astro 專案中加上適配器
npx astro add cloudflare
// astro.config.mjs — Astro SSR on Workers
import { defineConfig } from 'astro/config';
import cloudflare from '@astrojs/cloudflare';

export default defineConfig({
  output: 'server',   // 'static' 純靜態 / 'server' SSR
  adapter: cloudflare({
    platformProxy: { enabled: true }  // 本地開發模擬 Workers 環境
  })
});

在 Astro 頁面/元件裡,透過 Astro.locals.runtime.env 存取 bindings:

---
// src/pages/index.astro — 伺服器端查詢 D1
const { DB } = Astro.locals.runtime.env;
const { results: products } = await DB.prepare(
  'SELECT * FROM products ORDER BY created_at DESC LIMIT 10'
).all();
---
<ul>
  {products.map((p) => <li>{p.name} — ${p.price}</li>)}
</ul>

SSR 模式下,wrangler.jsoncmain 指向 Astro 產出的 server 入口、assets 指向 client 目錄:

// wrangler.jsonc — Astro SSR
{
  "name": "my-astro-app",
  "main": "dist/server/entry.mjs",
  "compatibility_date": "2026-01-01",
  "compatibility_flags": ["nodejs_compat"],
  "assets": { "directory": "dist/client" },
  "d1_databases": [{ "binding": "DB", "database_id": "your-db-id" }]
}

若你的 Astro 站是純內容(部落格、文件),用 output: 'static' 建置後,連 main 都不用寫,回到上一篇的「純靜態站」型態即可。

5. Hono:原生跑在 Workers,無需 adapter

Hono 是為 Web 標準與邊緣環境設計的輕量框架,可以直接原生跑在 Workers 上,不需要任何 adapter——你的 Worker 入口本身就是一個 Hono app:

// src/index.ts — Hono 直接當作 Worker 入口
import { Hono } from 'hono';

interface Env {
  DB: D1Database;
  ASSETS: Fetcher;
}

const app = new Hono<{ Bindings: Env }>();

// API 路由,c.env 直接拿到 bindings
app.get('/api/users', async (c) => {
  const { results } = await c.env.DB.prepare('SELECT * FROM users').all();
  return c.json(results);
});

export default app;   // 不需要 adapter,直接 export
// wrangler.jsonc — Hono + 前端靜態資源
{
  "name": "my-hono-app",
  "main": "src/index.ts",
  "compatibility_date": "2026-01-01",
  "assets": {
    "directory": "./dist",
    "run_worker_first": ["/api/*"]   // 只有 API 先進 Hono,其餘走免費靜態
  }
}

這裡把上一篇的 run_worker_first: ["/api/*"] 派上用場:Hono 只處理 /api/*,其餘前端靜態檔案由邊緣直送、不計費。這種「Hono 寫後端 API + 前端框架靜態產物」的組合,是 Workers 上很常見的輕量全端模式。

6. Remix:透過 C3 產生 Workers 適配器

Remix 同樣是 SSR 框架,舊的 @remix-run/cloudflare-pages(Pages 版)已棄用,改用 C3 產生的 Workers 版設定:

npm create cloudflare@latest my-remix-app -- --framework=remix

在 loader 裡透過 context.cloudflare.env 存取 bindings:

// app/routes/_index.tsx — Remix loader 存取 D1
import type { LoaderFunctionArgs } from '@remix-run/cloudflare';
import { json } from '@remix-run/cloudflare';

export async function loader({ context }: LoaderFunctionArgs) {
  const { cloudflare } = context;
  const { results } = await cloudflare.env.DB.prepare(
    'SELECT * FROM products LIMIT 10'
  ).all();
  return json({ products: results });
}

wrangler.jsoncmain 指向 Remix 的 server build、assets 指向 client build,型態與 Astro SSR 幾乎一致(C3 會幫你產生,不用手刻)。

常見錯誤與最佳實踐

框架整合的坑,大多集中在「用錯適配器」「Node API 相容」「SSR 與 edge runtime 搞混」這三類。以下是最高頻的幾個。

坑一:Next.js 用了給 Pages 的舊 adapter(@cloudflare/next-on-pages)。

這是最常見的誤會。@cloudflare/next-on-pages 是部署到 Pages 的舊適配器,而現在官方主推的是部署到 Workers@opennextjs/cloudflare。用錯了不只是設定不同,還會少掉 Workers 才有的能力(Durable Objects、Cron、更完整的 observability)。正確做法:新專案一律用 @opennextjs/cloudflare;既有的 next-on-pages 專案考慮遷移。(套件名稱與遷移路徑以官方文件為準。)

坑二:忘了開 nodejs_compat,SSR 框架跑不起來。

Next.js、Astro SSR、Remix 這類框架的伺服器端程式碼,常會用到 Node.js 的 API(如 Bufferprocess、部分內建模組)。Workers 預設不提供完整 Node 環境,若沒設定就會在執行期報錯。正確做法:SSR 框架的 wrangler.jsonc 記得在 compatibility_flags 加上 "nodejs_compat"(C3 產生的專案通常已幫你加好;手動遷移時最容易漏)。

坑三:在 @opennextjs/cloudflare 上硬用 export const runtime = 'edge'

有些 Next.js 教學會叫你把 API route 或頁面標成 Edge Runtime(export const runtime = 'edge'),但 @opennextjs/cloudflare 不支援這個標記。原因是:在 Workers 上你「本來就跑在邊緣」,不需要 Next.js 那套 Edge Runtime 抽象。正確做法:移除 runtime = 'edge' 標記,使用預設(Node.js 相容)執行環境即可——功能不會少,反而更完整。

坑四:把純靜態專案硬套 adapter,徒增複雜度。

反過來的錯誤:一個明明是 React SPA 或 Astro 純內容站的專案,卻去裝 SSR adapter、寫一堆 main正確做法:先判斷「這個專案需不需要伺服器端渲染」。純靜態(SSG/SPA)就只設 assets.directory + not_found_handling,不碰 adapter;確定有 SSR 需求(即時資料、個人化頁面)才引入對應框架的 Cloudflare adapter。

坑五:分不清該讓框架處理路由,還是用 run_worker_first

框架自己有一套路由(Next.js 的 App Router、Remix 的 file routes),而 Workers 也有 run_worker_first。兩者混用時容易打架。正確做法:用「官方 adapter 產生的 main」的框架(Next.js/Astro/Remix),路由交給框架、wrangler.jsonc 照 adapter 產生的設定走,不要自己亂加 run_worker_first;只有在「自己手寫 Worker(如 Hono)+ 前端靜態產物」的組合裡,才用 run_worker_first: ["/api/*"] 劃清 API 與靜態的界線。

最佳實踐小結:

  • 新專案用 C3 起手——npm create cloudflare@latest 幫你把 adapter、mainassetscompatibility_flags 一次設好。
  • 先判斷靜態 vs SSR——純靜態只設 assets;SSR 才用對應框架的 Cloudflare adapter。
  • Next.js 認 @opennextjs/cloudflare——不用舊的 next-on-pages,不用 runtime = 'edge'
  • SSR 框架記得 nodejs_compat——避免 Node API 相容性報錯。
  • Hono 直接跑——輕量 API/全端首選,搭配 run_worker_first 與前端靜態產物。

小結

上一篇《Workers Static Assets 靜態託管》,我們把 assets 的每個選項拆開來實作,學會了手工設定靜態託管。這一篇《框架整合》,我們把這些設定套用到真實框架上:

  • 分水嶺——純靜態(SSG/SPA)只需 assets、不用 adapter;SSR 需要 adapter 產生 main 入口。
  • 五大框架——React/Vite(純靜態,選用 @cloudflare/vite-plugin)、Next.js(@opennextjs/cloudflare)、Astro(@astrojs/cloudflare)、Remix(C3 產生)、Hono(原生跑,無需 adapter)。
  • C3 起手——npm create cloudflare@latest 一鍵建立各框架骨架,自動設好 adapter 與設定。
  • 常見坑——用錯 Pages 舊 adapter、漏開 nodejs_compat、誤用 runtime = 'edge'、純靜態硬套 adapter。

到這裡,我們從《Pages 與 Static Assets 總覽》的選型,到《Workers Static Assets 靜態託管》的手工實作,再到這一篇的框架整合,完整走完了 Cloudflare 前端與全端託管的 Pages 段落。你現在應該能自信地判斷:任何一個前端專案,該用純靜態還是 SSR、該不該用 adapter、wrangler.jsonc 該怎麼寫。

掌握了「怎麼把應用部署上去」,下一步就是「怎麼把應用設計得好」。下一篇《架構模式與反模式》,我們會拉高視角,談 Workers 應用常見的架構模式(以及那些看似方便、實則會踩雷的反模式)——如何組織 Worker、bindings、資料流,讓你的應用不只跑得起來,還跑得穩、擴得動。我們下一篇見。

想查閱各框架整合的官方最新指南與適配器套件細節,可以參考 Cloudflare Workers 框架指南官方文件(各框架適配器名稱、版本與支援矩陣以當下官方文件為準)。

BenZ Software Developer

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

本週主打

AI 自動化入門包

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

看看這個產品 →