workers-frameworks
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseWorkers Frameworks Integration
Workers 框架集成
Build full-stack applications on Cloudflare Workers using modern frameworks.
使用现代框架在 Cloudflare Workers 上构建全栈应用。
Quick Start: Choose Your Framework
快速开始:选择你的框架
| Framework | Best For | SSR | Static | Workers Native |
|---|---|---|---|---|
| Hono | APIs, lightweight apps | ✅ | ✅ | ✅ Native |
| Remix | Full-stack apps | ✅ | ✅ | ✅ Adapter |
| Next.js | React apps | ✅ | ✅ | ⚠️ OpenNext |
| Astro | Content sites | ✅ | ✅ | ✅ Adapter |
| SvelteKit | Svelte apps | ✅ | ✅ | ✅ Adapter |
| Qwik | Resumable apps | ✅ | ✅ | ✅ Adapter |
| Nuxt | Vue apps | ✅ | ✅ | ✅ Nitro |
| 框架 | 适用场景 | SSR | Static | Workers 原生支持 |
|---|---|---|---|---|
| Hono | API、轻量级应用 | ✅ | ✅ | ✅ 原生支持 |
| Remix | 全栈应用 | ✅ | ✅ | ✅ 适配器支持 |
| Next.js | React 应用 | ✅ | ✅ | ⚠️ 通过 OpenNext |
| Astro | 内容型站点 | ✅ | ✅ | ✅ 适配器支持 |
| SvelteKit | Svelte 应用 | ✅ | ✅ | ✅ 适配器支持 |
| Qwik | 可恢复式应用 | ✅ | ✅ | ✅ 适配器支持 |
| Nuxt | Vue 应用 | ✅ | ✅ | ✅ 通过 Nitro |
Framework Decision Tree
框架选择决策树
Need an API only?
└─ Yes → Hono (fastest, smallest)
└─ No → Building a full app?
└─ React → Next.js (OpenNext) or Remix
└─ Vue → Nuxt
└─ Svelte → SvelteKit
└─ Content-heavy → Astro
└─ Max performance → Qwik仅需要 API?
└─ 是 → Hono(最快、体积最小)
└─ 否 → 构建全栈应用?
└─ React 技术栈 → Next.js(通过 OpenNext)或 Remix
└─ Vue 技术栈 → Nuxt
└─ Svelte 技术栈 → SvelteKit
└─ 内容密集型站点 → Astro
└─ 追求极致性能 → QwikTop 10 Framework Errors
十大常见框架错误
| Error | Framework | Cause | Solution |
|---|---|---|---|
| All | Wrong export format | Use |
| Next.js | Heavy SSR | Use ISR, reduce bundle size |
| Remix | Missing context | Pass |
| All | Node.js globals | Use |
| All | CJS in ESM | Convert to ESM imports |
| All | Body already read | Clone response before reading |
| All | Missing wrangler config | Add bindings to wrangler.jsonc |
| All | Wrong assets config | Configure |
| React/Vue | Server/client differ | Ensure consistent rendering |
| All | Circular imports | Refactor module structure |
| 错误信息 | 框架 | 原因 | 解决方案 |
|---|---|---|---|
| 所有框架 | 导出格式错误 | 使用 |
| Next.js | SSR 计算量过大 | 使用 ISR、减小包体积 |
| Remix | 缺少上下文 | 将 |
| 所有框架 | 使用了 Node.js 全局变量 | 启用 |
| 所有框架 | ESM 中使用了 CJS 语法 | 转换为 ESM 导入方式 |
| 所有框架 | 响应体已被读取 | 读取前克隆响应对象 |
| 所有框架 | 缺少 wrangler 配置 | 在 wrangler.jsonc 中添加绑定配置 |
| 所有框架 | 静态资源配置错误 | 在 wrangler.jsonc 中配置 |
| React/Vue | 服务端与客户端渲染不一致 | 确保渲染逻辑一致 |
| 所有框架 | 存在循环导入 | 重构模块结构 |
Hono Quick Start (Recommended)
Hono 快速开始(推荐)
typescript
// src/index.ts
import { Hono } from 'hono';
import { cors } from 'hono/cors';
import { logger } from 'hono/logger';
interface Env {
DB: D1Database;
KV: KVNamespace;
}
const app = new Hono<{ Bindings: Env }>();
// Middleware
app.use('*', logger());
app.use('/api/*', cors());
// Routes
app.get('/', (c) => c.text('Hello Workers!'));
app.get('/api/users', async (c) => {
const { results } = await c.env.DB.prepare('SELECT * FROM users').all();
return c.json(results);
});
app.post('/api/users', async (c) => {
const { name, email } = await c.req.json();
await c.env.DB.prepare('INSERT INTO users (name, email) VALUES (?, ?)')
.bind(name, email)
.run();
return c.json({ success: true }, 201);
});
export default app;jsonc
// wrangler.jsonc
{
"name": "my-app",
"main": "src/index.ts",
"compatibility_date": "2024-12-01",
"compatibility_flags": ["nodejs_compat"],
"d1_databases": [
{ "binding": "DB", "database_name": "my-db", "database_id": "xxx" }
]
}typescript
// src/index.ts
import { Hono } from 'hono';
import { cors } from 'hono/cors';
import { logger } from 'hono/logger';
interface Env {
DB: D1Database;
KV: KVNamespace;
}
const app = new Hono<{ Bindings: Env }>();
// 中间件
app.use('*', logger());
app.use('/api/*', cors());
// 路由
app.get('/', (c) => c.text('Hello Workers!'));
app.get('/api/users', async (c) => {
const { results } = await c.env.DB.prepare('SELECT * FROM users').all();
return c.json(results);
});
app.post('/api/users', async (c) => {
const { name, email } = await c.req.json();
await c.env.DB.prepare('INSERT INTO users (name, email) VALUES (?, ?)')
.bind(name, email)
.run();
return c.json({ success: true }, 201);
});
export default app;jsonc
// wrangler.jsonc
{
"name": "my-app",
"main": "src/index.ts",
"compatibility_date": "2024-12-01",
"compatibility_flags": ["nodejs_compat"],
"d1_databases": [
{ "binding": "DB", "database_name": "my-db", "database_id": "xxx" }
]
}Static Assets Configuration
静态资源配置
jsonc
// wrangler.jsonc - Serving static files
{
"name": "my-app",
"main": "src/index.ts",
"assets": {
"directory": "./public",
"binding": "ASSETS"
}
}typescript
// Serve static with fallback to app
import { Hono } from 'hono';
const app = new Hono<{ Bindings: { ASSETS: Fetcher } }>();
// API routes
app.get('/api/*', apiHandler);
// Static assets fallback
app.get('*', async (c) => {
return c.env.ASSETS.fetch(c.req.raw);
});
export default app;jsonc
// wrangler.jsonc - 托管静态文件
{
"name": "my-app",
"main": "src/index.ts",
"assets": {
"directory": "./public",
"binding": "ASSETS"
}
}typescript
// 托管静态资源,未匹配时回退到应用
import { Hono } from 'hono';
const app = new Hono<{ Bindings: { ASSETS: Fetcher } }>();
// API 路由
app.get('/api/*', apiHandler);
// 静态资源回退
app.get('*', async (c) => {
return c.env.ASSETS.fetch(c.req.raw);
});
export default app;When to Load References
何时加载参考文档
Load the specific framework reference when user:
| Reference | Load When |
|---|---|
| Building APIs, microservices, or lightweight apps |
| Full-stack React with loaders/actions |
| Next.js App Router on Workers via OpenNext |
| Content sites, blogs, docs, marketing pages |
| Svelte applications on Workers |
| Resumable apps, instant loading |
| Vue 3 applications with Nitro |
在以下场景加载对应框架的参考文档:
| 参考文档 | 加载场景 |
|---|---|
| 构建 API、微服务或轻量级应用时 |
| 开发带 loaders/actions 的全栈 React 应用时 |
| 通过 OpenNext 在 Workers 上部署 Next.js App Router 时 |
| 开发内容站点、博客、文档、营销页面时 |
| 在 Workers 上开发 Svelte 应用时 |
| 开发可恢复式应用、实现即时加载时 |
| 通过 Nitro 开发 Vue 3 应用时 |
Common Patterns Across Frameworks
各框架通用模式
Environment Bindings Access
环境绑定访问
typescript
// Hono
app.get('/', (c) => c.env.DB.prepare('...'));
// Remix
export async function loader({ context }) {
return context.cloudflare.env.DB.prepare('...');
}
// Astro
const db = Astro.locals.runtime.env.DB;
// SvelteKit
export async function load({ platform }) {
return platform.env.DB.prepare('...');
}
// Nuxt
const { cloudflare } = useRuntimeConfig();
// Or via nitro: event.context.cloudflare.env.DBtypescript
// Hono
app.get('/', (c) => c.env.DB.prepare('...'));
// Remix
export async function loader({ context }) {
return context.cloudflare.env.DB.prepare('...');
}
// Astro
const db = Astro.locals.runtime.env.DB;
// SvelteKit
export async function load({ platform }) {
return platform.env.DB.prepare('...');
}
// Nuxt
const { cloudflare } = useRuntimeConfig();
// 或通过 nitro: event.context.cloudflare.env.DBError Handling Pattern
错误处理模式
typescript
// Universal error boundary pattern
app.onError((err, c) => {
console.error(`[${c.req.path}] ${err.message}`);
if (err instanceof HTTPException) {
return err.getResponse();
}
return c.json(
{ error: 'Internal Server Error' },
500
);
});typescript
// 通用错误边界模式
app.onError((err, c) => {
console.error(`[${c.req.path}] ${err.message}`);
if (err instanceof HTTPException) {
return err.getResponse();
}
return c.json(
{ error: 'Internal Server Error' },
500
);
});Performance Tips
性能优化建议
- Bundle Size: Keep under 1MB compressed
- Cold Starts: Minimize top-level code
- Streaming: Use streaming SSR when available
- Caching: Leverage Cache API and CDN
- Code Splitting: Dynamic imports for routes
- 包体积:压缩后保持在 1MB 以内
- 冷启动优化:减少顶层代码执行逻辑
- 流式渲染:尽可能使用流式 SSR
- 缓存策略:充分利用 Cache API 和 CDN
- 代码分割:对路由使用动态导入
See Also
另请参阅
- - Optimization techniques
workers-performance - - Workers APIs reference
workers-runtime-apis - - Basic Workers setup
cloudflare-worker-base
- - 性能优化技巧
workers-performance - - Workers API 参考
workers-runtime-apis - - Workers 基础配置
cloudflare-worker-base