两种部署形态
Pages(Dashboard Git 集成)
连 GitHub/GitLab,push 自动构建部署。每个 PR 有 Preview 环境。
Workers + Static Assets
2024 新模式:Worker 本身可以托管静态资源,wrangler deploy 一步到位。这是两者合并后的统一路径。
2026 起 Cloudflare 推荐走 Workers + Static Assets——但大量现存项目还在 Pages 上,两种都要懂。
Next.js on Cloudflare
官方推荐 @opennextjs/cloudflare,把 Next.js 构建产物适配到 Workers。
npm create cloudflare@latest my-app -- --framework=next cd my-app npm run preview # 本地用 wrangler 跑,看到 Workers 实际行为 npm run deploy
# wrangler.jsonc 示例 { "name": "my-next-app", "main": ".open-next/worker.js", "compatibility_date": "2026-05-01", "compatibility_flags": ["nodejs_compat"], "assets": { "directory": ".open-next/assets", "binding": "ASSETS" }, "d1_databases": [{ "binding": "DB", "database_name": "prod", "database_id": "..." }], "r2_buckets": [{ "binding": "ASSETS_BUCKET", "bucket_name": "..." }] }
// app/api/users/route.ts — Next.js Route Handler 里直接用 bindings import { getRequestContext } from '@opennextjs/cloudflare'; export async function GET() { const { env } = getRequestContext(); const { results } = await env.DB.prepare('SELECT * FROM users LIMIT 10').all(); return Response.json(results); }
SvelteKit on Cloudflare
// svelte.config.js import adapter from '@sveltejs/adapter-cloudflare'; export default { kit: { adapter: adapter() }, };
// src/routes/api/users/+server.ts export async function GET({ platform }) { const r = await platform.env.DB.prepare('SELECT * FROM users').all(); return new Response(JSON.stringify(r.results)); }
Remix / Astro
官方 @remix-run/cloudflare 和 @astrojs/cloudflare adapter,流程一致:
npm create cloudflare -- --framework=remix或astro- 本地
npm run dev(Vite 模式)或npm run preview(wrangler 模式) npm run deploy→ 几十秒后全球上线
Functions(老 Pages 模式)
老 Pages 项目里 functions/ 目录,文件系统路由:
functions/ ├── api/ │ ├── users/ │ │ └── [id].ts ← GET /api/users/42 │ └── index.ts ← GET /api/ └── _middleware.ts ← 所有路由前置中间件
// functions/api/users/[id].ts interface Env { DB: D1Database } export const onRequestGet: PagesFunction<Env> = async (ctx) => { const id = ctx.params.id; const r = await ctx.env.DB.prepare('SELECT * FROM users WHERE id=?').bind(id).first(); return r ? Response.json(r) : new Response('404', { status: 404 }); };
Preview 环境
每次 PR 自动部署一个独立 URL <pr-id>.my-app.pages.dev,和生产完全隔离但共享 Bindings 配置。设计/产品 review 直接点链接看效果。
Preview 用独立 D1?
Pages 的 Preview 环境可以绑不同的 D1 / R2 / KV——wrangler.toml 配两套即可。这样 PR 随便改数据不影响生产。
Pages 的 Preview 环境可以绑不同的 D1 / R2 / KV——wrangler.toml 配两套即可。这样 PR 随便改数据不影响生产。
自定义域名与 SSL
- Pages Dashboard → Custom Domains → 添加
www.example.com - 域名需要在 Cloudflare 托管,DNS 自动配置
- SSL 证书自动签发,强制 HTTPS
构建配置
| 框架 | Build command | Output directory |
|---|---|---|
| Next.js | npx opennextjs-cloudflare build | .open-next/worker.js |
| SvelteKit | npm run build | .svelte-kit/cloudflare |
| Remix | npm run build | build/client |
| Astro | npm run build | dist |
| Vite SPA | npm run build | dist |
从 Vercel / Netlify 迁移
Edge Runtime 已兼容
Vercel Edge Functions / Middleware 基于 Web 标准,大部分代码能直接跑在 Workers。Node-only API(
fs、path)要换成 nodejs_compat 或重写。ISR 替代
Next.js ISR 用 Cache API + KV 实现(
@opennextjs/cloudflare 已内置)。Image Optimization
Cloudflare Images 服务或 Image Resizing,替代 Next/image loader。
陷阱与诊断
- 🙅
process.env.X在 Next.js Route Handler 里是 undefined——用getRequestContext().env - 🙅 Server Components 里做 Node fs 操作——Edge 运行时没有,改成 D1/R2 调用
- 🙅 某些 npm 包依赖 Node 原生(sharp、puppeteer)——走
nodejs_compat或换边缘替代(Browser Rendering) - 🙅 SSR 里同步读取大 bundle——超 CPU 限额,分流或 lazy load
本章小结
- Pages + Workers 统一到"Workers + Static Assets",新项目直接用新模式
- 主流框架(Next/Svelte/Remix/Astro)都有官方 adapter,一行命令脚手架
- Bindings 在框架的 env / platform 里透传,写 API 直通 D1/R2/KV
- Preview 环境每 PR 一个,可绑独立资源隔离生产
- 从 Vercel 迁移:Edge Runtime 代码基本兼容,ISR/图片优化有替代方案