cloudflare-nextjs

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Cloudflare Next.js Deployment Skill

Cloudflare Next.js 部署技能指南

Deploy Next.js applications to Cloudflare Workers using the OpenNext Cloudflare adapter for production-ready serverless Next.js hosting.
使用OpenNext Cloudflare适配器将Next.js应用部署到Cloudflare Workers,实现生产就绪的无服务器Next.js托管。

Use This Skill When

适用场景

  • Deploying Next.js applications (App Router or Pages Router) to Cloudflare Workers
  • Need server-side rendering (SSR), static site generation (SSG), or incremental static regeneration (ISR) on Cloudflare
  • Migrating existing Next.js apps from Vercel, AWS, or other platforms to Cloudflare
  • Building full-stack Next.js applications with Cloudflare services (D1, R2, KV, Workers AI)
  • Need React Server Components, Server Actions, or Next.js middleware on Workers
  • Want global edge deployment with Cloudflare's network
  • 将Next.js应用(App Router或Pages Router)部署到Cloudflare Workers
  • 需要在Cloudflare上实现服务端渲染(SSR)、静态站点生成(SSG)或增量静态再生(ISR)
  • 将现有Next.js应用从Vercel、AWS或其他平台迁移到Cloudflare
  • 构建集成Cloudflare服务(D1、R2、KV、Workers AI)的全栈Next.js应用
  • 需要在Workers上使用React Server Components、Server Actions或Next.js中间件
  • 希望借助Cloudflare网络实现全球边缘部署

Key Concepts

核心概念

OpenNext Adapter Architecture

OpenNext适配器架构

The OpenNext Cloudflare adapter (
@opennextjs/cloudflare
) transforms Next.js build output into Cloudflare Worker-compatible format. This is fundamentally different from standard Next.js deployments:
  • Node.js Runtime Required: Uses Node.js runtime in Workers (NOT Edge runtime)
  • Dual Development Workflow: Test in both Next.js dev server AND workerd runtime
  • Custom Build Pipeline:
    next build
    → OpenNext transformation → Worker deployment
  • Cloudflare-Specific Configuration: Requires wrangler.jsonc and open-next.config.ts
OpenNext Cloudflare适配器
@opennextjs/cloudflare
)可将Next.js构建输出转换为Cloudflare Worker兼容格式。这与标准Next.js部署存在本质区别:
  • 需要Node.js运行时:在Workers中使用Node.js运行时(而非Edge运行时)
  • 双开发工作流:同时在Next.js开发服务器和workerd运行时中测试
  • 自定义构建流水线
    next build
    → OpenNext转换 → Worker部署
  • Cloudflare专属配置:需要wrangler.jsonc和open-next.config.ts文件

Critical Differences from Standard Next.js

与标准Next.js的关键差异

AspectStandard Next.jsCloudflare Workers
RuntimeNode.js or EdgeNode.js (via nodejs_compat)
Dev Server
next dev
next dev
+
opennextjs-cloudflare preview
DeploymentPlatform-specific
opennextjs-cloudflare deploy
Worker SizeNo limit3 MiB (free) / 10 MiB (paid)
Database ConnectionsGlobal clients OKMust be request-scoped
Image OptimizationBuilt-inVia Cloudflare Images
CachingNext.js cacheOpenNext config + Workers cache
维度标准Next.jsCloudflare Workers
运行时Node.js或EdgeNode.js(通过nodejs_compat)
开发服务器
next dev
next dev
+
opennextjs-cloudflare preview
部署方式平台专属
opennextjs-cloudflare deploy
Worker大小无限制3 MiB(免费版)/ 10 MiB(付费版)
数据库连接全局客户端可用必须为请求作用域
图片优化内置支持通过Cloudflare Images实现
缓存机制Next.js缓存OpenNext配置 + Workers缓存

Setup Patterns

配置模式

New Project Setup

新项目配置

Use Cloudflare's
create-cloudflare
(C3) CLI to scaffold a new Next.js project pre-configured for Workers:
bash
npm create cloudflare@latest -- my-next-app --framework=next
What this does:
  1. Runs Next.js official setup tool (
    create-next-app
    )
  2. Installs
    @opennextjs/cloudflare
    adapter
  3. Creates
    wrangler.jsonc
    with correct configuration
  4. Creates
    open-next.config.ts
    for caching configuration
  5. Adds deployment scripts to
    package.json
  6. Optionally deploys immediately to Cloudflare
Development workflow:
bash
npm run dev      # Next.js dev server (fast reloads)
npm run preview  # Test in workerd runtime (production-like)
npm run deploy   # Build and deploy to Cloudflare
使用Cloudflare的
create-cloudflare
(C3)CLI工具快速搭建预配置Workers的Next.js项目:
bash
npm create cloudflare@latest -- my-next-app --framework=next
该命令完成的操作
  1. 运行Next.js官方初始化工具(
    create-next-app
  2. 安装
    @opennextjs/cloudflare
    适配器
  3. 创建配置正确的
    wrangler.jsonc
    文件
  4. 创建用于缓存配置的
    open-next.config.ts
    文件
  5. package.json
    中添加部署脚本
  6. 可选:立即部署到Cloudflare
开发工作流
bash
npm run dev      # Next.js开发服务器(快速热重载)
npm run preview  # 在workerd运行时中测试(生产环境模拟)
npm run deploy   # 构建并部署到Cloudflare

Existing Project Migration

现有项目迁移

To add the OpenNext adapter to an existing Next.js application:
为现有Next.js应用添加OpenNext适配器的步骤:

1. Install the adapter

1. 安装适配器

bash
npm install --save-dev @opennextjs/cloudflare
bash
npm install --save-dev @opennextjs/cloudflare

2. Create wrangler.jsonc

2. 创建wrangler.jsonc

jsonc
{
  "name": "my-next-app",
  "compatibility_date": "2025-05-05",
  "compatibility_flags": ["nodejs_compat"]
}
Critical configuration:
  • compatibility_date
    : Minimum
    2025-05-05
    (for FinalizationRegistry support)
  • compatibility_flags
    : Must include
    nodejs_compat
    (for Node.js runtime)
jsonc
{
  "name": "my-next-app",
  "compatibility_date": "2025-05-05",
  "compatibility_flags": ["nodejs_compat"]
}
关键配置
  • compatibility_date
    最低要求
    2025-05-05
    (支持FinalizationRegistry)
  • compatibility_flags
    必须包含
    nodejs_compat
    (用于Node.js运行时)

3. Create open-next.config.ts

3. 创建open-next.config.ts

typescript
import { defineCloudflareConfig } from "@opennextjs/cloudflare";

export default defineCloudflareConfig({
  // Caching configuration (optional)
  // See: https://opennext.js.org/cloudflare/caching
});
typescript
import { defineCloudflareConfig } from "@opennextjs/cloudflare";

export default defineCloudflareConfig({
  // 缓存配置(可选)
  // 参考:https://opennext.js.org/cloudflare/caching
});

4. Update package.json scripts

4. 更新package.json脚本

json
{
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "preview": "opennextjs-cloudflare build && opennextjs-cloudflare preview",
    "deploy": "opennextjs-cloudflare build && opennextjs-cloudflare deploy",
    "cf-typegen": "wrangler types --env-interface CloudflareEnv cloudflare-env.d.ts"
  }
}
Script purposes:
  • dev
    : Next.js development server (fast iteration)
  • preview
    : Build + run in workerd runtime (test before deploy)
  • deploy
    : Build + deploy to Cloudflare
  • cf-typegen
    : Generate TypeScript types for Cloudflare bindings
json
{
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "preview": "opennextjs-cloudflare build && opennextjs-cloudflare preview",
    "deploy": "opennextjs-cloudflare build && opennextjs-cloudflare deploy",
    "cf-typegen": "wrangler types --env-interface CloudflareEnv cloudflare-env.d.ts"
  }
}
脚本用途
  • dev
    :Next.js开发服务器(快速迭代)
  • preview
    :构建并在workerd运行时中运行(部署前测试)
  • deploy
    :构建并部署到Cloudflare
  • cf-typegen
    :为Cloudflare绑定生成TypeScript类型

5. Ensure Node.js runtime (not Edge)

5. 确保使用Node.js运行时(而非Edge)

Remove Edge runtime exports from your app:
typescript
// ❌ REMOVE THIS (Edge runtime not supported)
export const runtime = "edge";

// ✅ Use Node.js runtime (default)
// No export needed - Node.js is default
移除应用中的Edge运行时导出:
typescript
// ❌ 移除该代码(不支持Edge运行时)
export const runtime = "edge";

// ✅ 使用Node.js运行时(默认)
// 无需额外导出 - Node.js为默认选项

Development Workflow

开发工作流

Dual Testing Strategy

双测试策略

Always test in BOTH environments:
  1. Next.js Dev Server (
    npm run dev
    )
    • Fast hot reloading
    • Best developer experience
    • Runs in Node.js (not production runtime)
    • Use for rapid iteration
  2. Workerd Runtime (
    npm run preview
    )
    • Runs in production-like environment
    • Catches runtime-specific issues
    • Slower rebuild times
    • Required before deployment
务必在两种环境中都进行测试
  1. Next.js开发服务器
    npm run dev
    • 快速热重载
    • 最佳开发体验
    • 在Node.js中运行(非生产运行时)
    • 用于快速迭代开发
  2. Workerd运行时
    npm run preview
    • 在类生产环境中运行
    • 捕获运行时专属问题
    • 重建速度较慢
    • 部署前必须执行

When to Use Each

适用场景区分

bash
undefined
bash
undefined

Iterating on UI/logic → Use Next.js dev server

迭代UI/逻辑 → 使用Next.js开发服务器

npm run dev
npm run dev

Testing integrations (D1, R2, KV) → Use preview

测试集成(D1、R2、KV)→ 使用preview

npm run preview
npm run preview

Before deploying → ALWAYS test preview

部署前 → 务必测试preview

npm run preview
npm run preview

Deploy to production

部署到生产环境

npm run deploy
undefined
npm run deploy
undefined

Configuration Requirements

配置要求

Wrangler Configuration

Wrangler配置

Minimum requirements in
wrangler.jsonc
:
jsonc
{
  "name": "your-app-name",
  "compatibility_date": "2025-05-05",  // Minimum for FinalizationRegistry
  "compatibility_flags": ["nodejs_compat"]  // Required for Node.js runtime
}
wrangler.jsonc
中的最低要求
jsonc
{
  "name": "your-app-name",
  "compatibility_date": "2025-05-05",  // 支持FinalizationRegistry的最低版本
  "compatibility_flags": ["nodejs_compat"]  // Node.js运行时必需
}

Environment Variables for Package Exports

包导出的环境变量

If using npm packages with multiple export conditions, create
.env
:
env
WRANGLER_BUILD_CONDITIONS=""
WRANGLER_BUILD_PLATFORM="node"
This ensures Wrangler prioritizes the
node
export when available.
如果使用包含多个导出条件的npm包,创建
.env
文件:
env
WRANGLER_BUILD_CONDITIONS=""
WRANGLER_BUILD_PLATFORM="node"
这将确保Wrangler在可用时优先选择
node
导出。

Cloudflare Bindings Integration

Cloudflare绑定集成

Add bindings in
wrangler.jsonc
:
jsonc
{
  "name": "your-app-name",
  "compatibility_date": "2025-05-05",
  "compatibility_flags": ["nodejs_compat"],

  // D1 Database
  "d1_databases": [
    {
      "binding": "DB",
      "database_name": "production-db",
      "database_id": "your-database-id"
    }
  ],

  // R2 Storage
  "r2_buckets": [
    {
      "binding": "BUCKET",
      "bucket_name": "your-bucket"
    }
  ],

  // KV Storage
  "kv_namespaces": [
    {
      "binding": "KV",
      "id": "your-kv-id"
    }
  ],

  // Workers AI
  "ai": {
    "binding": "AI"
  }
}
Access bindings in Next.js via
process.env
:
typescript
// app/api/route.ts
import type { NextRequest } from 'next/server';

export async function GET(request: NextRequest) {
  // Access Cloudflare bindings
  const env = process.env as any;

  // D1 Database query
  const result = await env.DB.prepare('SELECT * FROM users').all();

  // R2 Storage access
  const file = await env.BUCKET.get('file.txt');

  // KV Storage access
  const value = await env.KV.get('key');

  // Workers AI inference
  const response = await env.AI.run('@cf/meta/llama-3-8b-instruct', {
    prompt: 'Hello AI'
  });

  return Response.json({ result });
}
wrangler.jsonc
中添加绑定:
jsonc
{
  "name": "your-app-name",
  "compatibility_date": "2025-05-05",
  "compatibility_flags": ["nodejs_compat"],

  // D1数据库
  "d1_databases": [
    {
      "binding": "DB",
      "database_name": "production-db",
      "database_id": "your-database-id"
    }
  ],

  // R2存储
  "r2_buckets": [
    {
      "binding": "BUCKET",
      "bucket_name": "your-bucket"
    }
  ],

  // KV存储
  "kv_namespaces": [
    {
      "binding": "KV",
      "id": "your-kv-id"
    }
  ],

  // Workers AI
  "ai": {
    "binding": "AI"
  }
}
通过
process.env
在Next.js中访问绑定:
typescript
// app/api/route.ts
import type { NextRequest } from 'next/server';

export async function GET(request: NextRequest) {
  // 访问Cloudflare绑定
  const env = process.env as any;

  // D1数据库查询
  const result = await env.DB.prepare('SELECT * FROM users').all();

  // R2存储访问
  const file = await env.BUCKET.get('file.txt');

  // KV存储访问
  const value = await env.KV.get('key');

  // Workers AI推理
  const response = await env.AI.run('@cf/meta/llama-3-8b-instruct', {
    prompt: 'Hello AI'
  });

  return Response.json({ result });
}

Error Prevention (10+ Documented Errors)

错误预防(10余种已记录错误)

1. Worker Size Limit Exceeded (3 MiB - Free Plan)

1. Worker大小限制超出(免费版3 MiB)

Error:
"Your Worker exceeded the size limit of 3 MiB"
Cause: Workers Free plan limits Worker size to 3 MiB (gzip-compressed)
Solutions:
  • Upgrade to Workers Paid plan (10 MiB limit)
  • Analyze bundle size and remove unused dependencies
  • Use dynamic imports to code-split large dependencies
Bundle analysis:
bash
npx opennextjs-cloudflare build
cd .open-next/server-functions/default
错误信息
"Your Worker exceeded the size limit of 3 MiB"
原因:Workers免费版限制Worker大小为3 MiB(gzip压缩后)
解决方案
  • 升级到Workers付费版(限制为10 MiB)
  • 分析包大小并移除未使用的依赖
  • 使用动态导入对大型依赖进行代码分割
包分析命令
bash
npx opennextjs-cloudflare build
cd .open-next/server-functions/default

Analyze handler.mjs.meta.json with ESBuild Bundle Analyzer

使用ESBuild Bundle Analyzer分析handler.mjs.meta.json


**Source**: https://opennext.js.org/cloudflare/troubleshooting#worker-size-limits

---

**来源**:https://opennext.js.org/cloudflare/troubleshooting#worker-size-limits

---

2. Worker Size Limit Exceeded (10 MiB - Paid Plan)

2. Worker大小限制超出(付费版10 MiB)

Error:
"Your Worker exceeded the size limit of 10 MiB"
Cause: Unnecessary code bundled into Worker
Debug workflow:
  1. Run
    npx opennextjs-cloudflare build
  2. Navigate to
    .open-next/server-functions/default
  3. Analyze
    handler.mjs.meta.json
    using ESBuild Bundle Analyzer
  4. Identify and remove/externalize large dependencies

错误信息
"Your Worker exceeded the size limit of 10 MiB"
原因:不必要的代码被打包到Worker中
调试流程
  1. 运行
    npx opennextjs-cloudflare build
  2. 进入
    .open-next/server-functions/default
    目录
  3. 使用ESBuild Bundle Analyzer分析
    handler.mjs.meta.json
  4. 识别并移除/外部化大型依赖

3. FinalizationRegistry Not Defined

3. FinalizationRegistry未定义

Error:
"ReferenceError: FinalizationRegistry is not defined"
Cause:
compatibility_date
in wrangler.jsonc is too old
Solution: Update
compatibility_date
to
2025-05-05
or later:
jsonc
{
  "compatibility_date": "2025-05-05"  // Minimum for FinalizationRegistry
}

错误信息
"ReferenceError: FinalizationRegistry is not defined"
原因:wrangler.jsonc中的
compatibility_date
版本过旧
解决方案:将
compatibility_date
更新为
2025-05-05
或更高版本:
jsonc
{
  "compatibility_date": "2025-05-05"  // 支持FinalizationRegistry的最低版本
}

4. Cannot Perform I/O on Behalf of Different Request

4. 无法代表其他请求执行I/O操作

Error:
"Cannot perform I/O on behalf of a different request"
Cause: Database client created globally and reused across requests
Problem code:
typescript
// ❌ WRONG: Global DB client
import { Pool } from 'pg';
const pool = new Pool({ connectionString: process.env.DATABASE_URL });

export async function GET() {
  // This will fail - pool created in different request context
  const result = await pool.query('SELECT * FROM users');
  return Response.json(result);
}
Solution: Create database clients inside request handlers:
typescript
// ✅ CORRECT: Request-scoped DB client
import { Pool } from 'pg';

export async function GET() {
  // Create client within request context
  const pool = new Pool({ connectionString: process.env.DATABASE_URL });
  const result = await pool.query('SELECT * FROM users');
  await pool.end();
  return Response.json(result);
}
Alternative: Use Cloudflare D1 (designed for Workers) instead of external databases:
typescript
// ✅ BEST: Use D1 (no connection pooling needed)
export async function GET(request: NextRequest) {
  const env = process.env as any;
  const result = await env.DB.prepare('SELECT * FROM users').all();
  return Response.json(result);
}

错误信息
"Cannot perform I/O on behalf of a different request"
原因:数据库客户端在全局创建并跨请求复用
错误代码示例
typescript
// ❌ 错误:全局DB客户端
import { Pool } from 'pg';
const pool = new Pool({ connectionString: process.env.DATABASE_URL });

export async function GET() {
  // 此操作会失败 - 连接池在不同请求上下文中创建
  const result = await pool.query('SELECT * FROM users');
  return Response.json(result);
}
解决方案:在请求处理程序内部创建数据库客户端:
typescript
// ✅ 正确:请求作用域的DB客户端
import { Pool } from 'pg';

export async function GET() {
  // 在请求上下文中创建客户端
  const pool = new Pool({ connectionString: process.env.DATABASE_URL });
  const result = await pool.query('SELECT * FROM users');
  await pool.end();
  return Response.json(result);
}
替代方案(推荐):使用Cloudflare D1(为Workers设计)替代外部数据库:
typescript
// ✅ 最佳方案:使用D1(无需连接池)
export async function GET(request: NextRequest) {
  const env = process.env as any;
  const result = await env.DB.prepare('SELECT * FROM users').all();
  return Response.json(result);
}

5. NPM Package Import Failures

5. NPM包导入失败

Error:
"Could not resolve '<package>'"
Cause: Missing
nodejs_compat
flag or package export conditions
Solution 1: Enable
nodejs_compat
flag:
jsonc
{
  "compatibility_flags": ["nodejs_compat"]
}
Solution 2: For packages with multiple exports, create
.env
:
env
WRANGLER_BUILD_CONDITIONS=""
WRANGLER_BUILD_PLATFORM="node"

错误信息
"Could not resolve '<package>'"
原因:缺少
nodejs_compat
标志或包导出条件配置错误
解决方案1:启用
nodejs_compat
标志:
jsonc
{
  "compatibility_flags": ["nodejs_compat"]
}
解决方案2:对于包含多个导出的包,创建
.env
文件:
env
WRANGLER_BUILD_CONDITIONS=""
WRANGLER_BUILD_PLATFORM="node"

6. Failed to Load Chunk (Turbopack)

6. 加载代码块失败(Turbopack)

Error:
"Failed to load chunk server/chunks/ssr/"
Cause: Next.js built with Turbopack (
next build --turbo
)
Solution: Use standard build (Turbopack not supported by adapter):
json
{
  "scripts": {
    "build": "next build"  // ✅ Correct
    // "build": "next build --turbo"  // ❌ Don't use Turbopack
  }
}

错误信息
"Failed to load chunk server/chunks/ssr/"
原因:使用Turbopack构建Next.js(
next build --turbo
解决方案:使用标准构建方式(适配器不支持Turbopack):
json
{
  "scripts": {
    "build": "next build"  // ✅ 正确
    // "build": "next build --turbo"  // ❌ 不要使用Turbopack
  }
}

7. SSRF Vulnerability (CVE-2025-6087)

7. SSRF漏洞(CVE-2025-6087)

Vulnerability: Server-Side Request Forgery via
/_next/image
endpoint
Affected versions:
@opennextjs/cloudflare
< 1.3.0
Solution: Upgrade to version 1.3.0 or later:
bash
npm install --save-dev @opennextjs/cloudflare@^1.3.0
Impact: Allows unauthenticated users to proxy arbitrary remote content

漏洞描述:通过
/_next/image
端点实现服务器端请求伪造
受影响版本
@opennextjs/cloudflare
< 1.3.0
解决方案:升级到1.3.0或更高版本:
bash
npm install --save-dev @opennextjs/cloudflare@^1.3.0
影响:允许未授权用户代理任意远程内容

8. Durable Objects Binding Warnings

8. Durable Objects绑定警告

Warning:
"You have defined bindings to the following internal Durable Objects... will not work in local development, but they should work in production"
Cause: OpenNext uses Durable Objects for caching (
DOQueueHandler
,
DOShardedTagCache
)
Solution: Safe to ignore - warning is expected behavior
Alternative (to suppress warning): Define Durable Objects in separate Worker with own config

警告信息
"You have defined bindings to the following internal Durable Objects... will not work in local development, but they should work in production"
原因:OpenNext使用Durable Objects实现缓存(
DOQueueHandler
DOShardedTagCache
解决方案可安全忽略 - 该警告为预期行为
替代方案(抑制警告):在单独的Worker中定义Durable Objects并使用独立配置

9. Prisma + D1 Middleware Conflicts

9. Prisma + D1中间件冲突

Error: Build errors when using
@prisma/client
+
@prisma/adapter-d1
in Next.js middleware
Cause: Database initialization in middleware context
Workaround: Initialize Prisma client in route handlers, not middleware

错误信息:在Next.js中间件中使用
@prisma/client
+
@prisma/adapter-d1
时出现构建错误
原因:在中间件上下文中初始化数据库
临时解决方案:在路由处理程序中初始化Prisma客户端,而非中间件

10. cross-fetch Library Errors

10. cross-fetch库错误

Error: Errors when using libraries that depend on
cross-fetch
Cause: OpenNext patches deployment package causing
cross-fetch
to try using Node.js libraries when native fetch is available
Solution: Use native
fetch
API directly instead of
cross-fetch
:
typescript
// ✅ Use native fetch
const response = await fetch('https://api.example.com/data');

// ❌ Avoid cross-fetch
// import fetch from 'cross-fetch';

错误信息:使用依赖
cross-fetch
的库时出现错误
原因:OpenNext会修补部署包,导致
cross-fetch
在原生fetch可用时尝试使用Node.js库
解决方案:直接使用原生
fetch
API替代
cross-fetch
typescript
// ✅ 使用原生fetch
const response = await fetch('https://api.example.com/data');

// ❌ 避免使用cross-fetch
// import fetch from 'cross-fetch';

11. Windows Development Issues

11. Windows开发问题

Issue: Full Windows support not guaranteed
Cause: Underlying Next.js tooling issues on Windows
Solutions:
  • Use WSL (Windows Subsystem for Linux)
  • Use virtual machine with Linux
  • Use Linux-based CI/CD for deployments
问题描述:无法保证完整的Windows支持
原因:Next.js底层工具在Windows上存在问题
解决方案
  • 使用WSL(Windows Subsystem for Linux)
  • 使用Linux虚拟机
  • 使用基于Linux的CI/CD进行部署

Feature Support Matrix

功能支持矩阵

FeatureStatusNotes
App Router✅ Fully SupportedLatest App Router features work
Pages Router✅ Fully SupportedLegacy Pages Router supported
Route Handlers✅ Fully SupportedAPI routes work as expected
React Server Components✅ Fully SupportedRSC fully functional
Server Actions✅ Fully SupportedServer Actions work
SSG✅ Fully SupportedStatic Site Generation
SSR✅ Fully SupportedServer-Side Rendering
ISR✅ Fully SupportedIncremental Static Regeneration
Middleware✅ SupportedExcept Node.js middleware (15.2+)
Image Optimization✅ SupportedVia Cloudflare Images
Partial Prerendering (PPR)✅ SupportedExperimental in Next.js
Composable Caching✅ Supported
'use cache'
directive
Response Streaming✅ SupportedStreaming responses work
next/after
API
✅ SupportedPost-response async work
Node.js Middleware (15.2+)❌ Not SupportedFuture support planned
Edge Runtime❌ Not SupportedUse Node.js runtime
功能状态说明
App Router✅ 完全支持最新App Router功能均可使用
Pages Router✅ 完全支持支持传统Pages Router
Route Handlers✅ 完全支持API路由正常工作
React Server Components✅ 完全支持RSC功能完整
Server Actions✅ 完全支持Server Actions可正常使用
SSG✅ 完全支持静态站点生成
SSR✅ 完全支持服务端渲染
ISR✅ 完全支持增量静态再生
Middleware✅ 支持不支持Node.js中间件(15.2+)
图片优化✅ 支持通过Cloudflare Images实现
部分预渲染(PPR)✅ 支持Next.js中的实验性功能
可组合缓存✅ 支持
'use cache'
指令
响应流✅ 支持流式响应可正常工作
next/after
API
✅ 支持响应后异步操作
Node.js中间件(15.2+)❌ 不支持计划在未来版本中支持
Edge运行时❌ 不支持使用Node.js运行时

Integration with Cloudflare Services

与Cloudflare服务的集成

D1 Database (SQL)

D1数据库(SQL)

typescript
// app/api/users/route.ts
import type { NextRequest } from 'next/server';

export async function GET(request: NextRequest) {
  const env = process.env as any;

  const result = await env.DB.prepare(
    'SELECT * FROM users WHERE active = ?'
  ).bind(true).all();

  return Response.json(result.results);
}

export async function POST(request: NextRequest) {
  const env = process.env as any;
  const { name, email } = await request.json();

  const result = await env.DB.prepare(
    'INSERT INTO users (name, email) VALUES (?, ?)'
  ).bind(name, email).run();

  return Response.json({ id: result.meta.last_row_id });
}
Wrangler config:
jsonc
{
  "d1_databases": [
    {
      "binding": "DB",
      "database_name": "production-db",
      "database_id": "your-database-id"
    }
  ]
}
See also:
cloudflare-d1
skill for complete D1 patterns

typescript
// app/api/users/route.ts
import type { NextRequest } from 'next/server';

export async function GET(request: NextRequest) {
  const env = process.env as any;

  const result = await env.DB.prepare(
    'SELECT * FROM users WHERE active = ?'
  ).bind(true).all();

  return Response.json(result.results);
}

export async function POST(request: NextRequest) {
  const env = process.env as any;
  const { name, email } = await request.json();

  const result = await env.DB.prepare(
    'INSERT INTO users (name, email) VALUES (?, ?)'
  ).bind(name, email).run();

  return Response.json({ id: result.meta.last_row_id });
}
Wrangler配置
jsonc
{
  "d1_databases": [
    {
      "binding": "DB",
      "database_name": "production-db",
      "database_id": "your-database-id"
    }
  ]
}
另请参考
cloudflare-d1
技能文档获取完整D1使用模式

R2 Storage (Object Storage)

R2存储(对象存储)

typescript
// app/api/upload/route.ts
import type { NextRequest } from 'next/server';

export async function POST(request: NextRequest) {
  const env = process.env as any;
  const formData = await request.formData();
  const file = formData.get('file') as File;

  // Upload to R2
  await env.BUCKET.put(file.name, file.stream(), {
    httpMetadata: {
      contentType: file.type
    }
  });

  return Response.json({ success: true, filename: file.name });
}

export async function GET(request: NextRequest) {
  const env = process.env as any;
  const { searchParams } = new URL(request.url);
  const filename = searchParams.get('file');

  const object = await env.BUCKET.get(filename);
  if (!object) {
    return new Response('Not found', { status: 404 });
  }

  return new Response(object.body, {
    headers: {
      'Content-Type': object.httpMetadata?.contentType || 'application/octet-stream'
    }
  });
}
See also:
cloudflare-r2
skill for complete R2 patterns

typescript
// app/api/upload/route.ts
import type { NextRequest } from 'next/server';

export async function POST(request: NextRequest) {
  const env = process.env as any;
  const formData = await request.formData();
  const file = formData.get('file') as File;

  // 上传到R2
  await env.BUCKET.put(file.name, file.stream(), {
    httpMetadata: {
      contentType: file.type
    }
  });

  return Response.json({ success: true, filename: file.name });
}

export async function GET(request: NextRequest) {
  const env = process.env as any;
  const { searchParams } = new URL(request.url);
  const filename = searchParams.get('file');

  const object = await env.BUCKET.get(filename);
  if (!object) {
    return new Response('Not found', { status: 404 });
  }

  return new Response(object.body, {
    headers: {
      'Content-Type': object.httpMetadata?.contentType || 'application/octet-stream'
    }
  });
}
另请参考
cloudflare-r2
技能文档获取完整R2使用模式

Workers AI (Model Inference)

Workers AI(模型推理)

typescript
// app/api/ai/route.ts
import type { NextRequest } from 'next/server';

export async function POST(request: NextRequest) {
  const env = process.env as any;
  const { prompt } = await request.json();

  const response = await env.AI.run('@cf/meta/llama-3-8b-instruct', {
    prompt
  });

  return Response.json(response);
}
Wrangler config:
jsonc
{
  "ai": {
    "binding": "AI"
  }
}
See also:
cloudflare-workers-ai
skill for complete AI patterns

typescript
// app/api/ai/route.ts
import type { NextRequest } from 'next/server';

export async function POST(request: NextRequest) {
  const env = process.env as any;
  const { prompt } = await request.json();

  const response = await env.AI.run('@cf/meta/llama-3-8b-instruct', {
    prompt
  });

  return Response.json(response);
}
Wrangler配置
jsonc
{
  "ai": {
    "binding": "AI"
  }
}
另请参考
cloudflare-workers-ai
技能文档获取完整AI使用模式

KV Storage (Key-Value)

KV存储(键值对)

typescript
// app/api/cache/route.ts
import type { NextRequest } from 'next/server';

export async function GET(request: NextRequest) {
  const env = process.env as any;
  const { searchParams } = new URL(request.url);
  const key = searchParams.get('key');

  const value = await env.KV.get(key);
  return Response.json({ key, value });
}

export async function PUT(request: NextRequest) {
  const env = process.env as any;
  const { key, value, ttl } = await request.json();

  await env.KV.put(key, value, { expirationTtl: ttl });
  return Response.json({ success: true });
}
See also:
cloudflare-kv
skill for complete KV patterns
typescript
// app/api/cache/route.ts
import type { NextRequest } from 'next/server';

export async function GET(request: NextRequest) {
  const env = process.env as any;
  const { searchParams } = new URL(request.url);
  const key = searchParams.get('key');

  const value = await env.KV.get(key);
  return Response.json({ key, value });
}

export async function PUT(request: NextRequest) {
  const env = process.env as any;
  const { key, value, ttl } = await request.json();

  await env.KV.put(key, value, { expirationTtl: ttl });
  return Response.json({ success: true });
}
另请参考
cloudflare-kv
技能文档获取完整KV使用模式

Image Optimization

图片优化

Next.js image optimization works via Cloudflare Images. Configure in
open-next.config.ts
:
typescript
import { defineCloudflareConfig } from "@opennextjs/cloudflare";

export default defineCloudflareConfig({
  imageOptimization: {
    loader: 'cloudflare'
  }
});
Usage in components:
tsx
import Image from 'next/image';

export default function Avatar() {
  return (
    <Image
      src="/avatar.jpg"
      alt="User avatar"
      width={200}
      height={200}
      // Automatically optimized via Cloudflare Images
    />
  );
}
Billing: Cloudflare Images usage is billed separately
Next.js图片优化通过Cloudflare Images实现。在
open-next.config.ts
中配置:
typescript
import { defineCloudflareConfig } from "@opennextjs/cloudflare";

export default defineCloudflareConfig({
  imageOptimization: {
    loader: 'cloudflare'
  }
});
在组件中使用:
tsx
import Image from 'next/image';

export default function Avatar() {
  return (
    <Image
      src="/avatar.jpg"
      alt="用户头像"
      width={200}
      height={200}
      // 自动通过Cloudflare Images优化
    />
  );
}
计费说明:Cloudflare Images使用量单独计费

Caching Configuration

缓存配置

Configure caching behavior in
open-next.config.ts
:
typescript
import { defineCloudflareConfig } from "@opennextjs/cloudflare";

export default defineCloudflareConfig({
  // Custom cache configuration
  cache: {
    // Override default cache behavior
    // See: https://opennext.js.org/cloudflare/caching
  }
});
Default behavior: OpenNext provides sensible caching defaults
Advanced usage: See official OpenNext caching documentation
open-next.config.ts
中配置缓存行为:
typescript
import { defineCloudflareConfig } from "@opennextjs/cloudflare";

export default defineCloudflareConfig({
  // 自定义缓存配置
  cache: {
    // 覆盖默认缓存行为
    // 参考:https://opennext.js.org/cloudflare/caching
  }
});
默认行为:OpenNext提供合理的缓存默认值
高级用法:参考OpenNext官方缓存文档

Known Limitations

已知限制

Not Yet Supported

暂不支持的功能

  1. Node.js Middleware (Next.js 15.2+)
    • Introduced in Next.js 15.2
    • Support planned for future releases
    • Use standard middleware for now
  2. Edge Runtime
    • Only Node.js runtime supported
    • Remove
      export const runtime = "edge"
      from your app
  3. Full Windows Support
    • Development on Windows not fully guaranteed
    • Use WSL, VM, or Linux-based CI/CD
  1. Node.js中间件(Next.js 15.2+)
    • 在Next.js 15.2中引入
    • 计划在未来版本中支持
    • 目前使用标准中间件
  2. Edge运行时
    • 仅支持Node.js运行时
    • 从应用中移除
      export const runtime = "edge"
  3. 完整Windows支持
    • Windows开发环境未完全兼容
    • 使用WSL、虚拟机或基于Linux的CI/CD

Worker Size Constraints

Worker大小限制

  • Free plan: 3 MiB limit (gzip-compressed)
  • Paid plan: 10 MiB limit (gzip-compressed)
  • Monitor bundle size during development
  • Use dynamic imports for code splitting
  • 免费版:3 MiB限制(gzip压缩后)
  • 付费版:10 MiB限制(gzip压缩后)
  • 开发过程中监控包大小
  • 使用动态导入进行代码分割

Database Connections

数据库连接

  • External database clients (PostgreSQL, MySQL) must be request-scoped
  • Cannot reuse connections across requests (Workers limitation)
  • Prefer Cloudflare D1 for database needs (designed for Workers)
  • 外部数据库客户端(PostgreSQL、MySQL)必须为请求作用域
  • 无法跨请求复用连接(Workers限制)
  • 优先使用Cloudflare D1(为Workers设计)

Deployment

部署

Deploy from Local Machine

从本地机器部署

bash
undefined
bash
undefined

Build and deploy in one command

一键构建并部署

npm run deploy
npm run deploy

Or step by step:

或分步执行:

npx opennextjs-cloudflare build npx opennextjs-cloudflare deploy
undefined
npx opennextjs-cloudflare build npx opennextjs-cloudflare deploy
undefined

Deploy from CI/CD

从CI/CD部署

Configure deployment command in your CI/CD system:
bash
npm run deploy
Examples:
  • GitHub Actions:
    .github/workflows/deploy.yml
  • GitLab CI:
    .gitlab-ci.yml
  • Cloudflare Workers Builds: Auto-detects
    npm run deploy
Environment variables: Set secrets in Cloudflare dashboard or CI/CD system
在CI/CD系统中配置部署命令:
bash
npm run deploy
示例
  • GitHub Actions:
    .github/workflows/deploy.yml
  • GitLab CI:
    .gitlab-ci.yml
  • Cloudflare Workers Builds:自动检测
    npm run deploy
环境变量:在Cloudflare控制台或CI/CD系统中设置密钥

Custom Domains

自定义域名

Add custom domain in Cloudflare dashboard:
  1. Navigate to Workers & Pages
  2. Select your Worker
  3. Settings → Domains & Routes
  4. Add custom domain
DNS: Domain must be on Cloudflare (zone required)
在Cloudflare控制台中添加自定义域名:
  1. 导航到Workers & Pages
  2. 选择您的Worker
  3. 设置 → 域名与路由
  4. 添加自定义域名
DNS要求:域名必须托管在Cloudflare(需要Zone)

TypeScript Support

TypeScript支持

Generate types for Cloudflare bindings:
bash
npm run cf-typegen
Creates
cloudflare-env.d.ts
with types for your bindings:
typescript
// cloudflare-env.d.ts (auto-generated)
interface CloudflareEnv {
  DB: D1Database;
  BUCKET: R2Bucket;
  KV: KVNamespace;
  AI: Ai;
}
Use in route handlers:
typescript
import type { NextRequest } from 'next/server';

export async function GET(request: NextRequest) {
  const env = process.env as CloudflareEnv;
  // Now env.DB, env.BUCKET, etc. are typed
}
为Cloudflare绑定生成类型:
bash
npm run cf-typegen
生成包含绑定类型的
cloudflare-env.d.ts
文件:
typescript
// cloudflare-env.d.ts(自动生成)
interface CloudflareEnv {
  DB: D1Database;
  BUCKET: R2Bucket;
  KV: KVNamespace;
  AI: Ai;
}
在路由处理程序中使用:
typescript
import type { NextRequest } from 'next/server';

export async function GET(request: NextRequest) {
  const env = process.env as CloudflareEnv;
  // 现在env.DB、env.BUCKET等均已类型化
}

Testing

测试

Local Testing (Development)

本地测试(开发阶段)

bash
undefined
bash
undefined

Next.js dev server (fast iteration)

Next.js开发服务器(快速迭代)

npm run dev
undefined
npm run dev
undefined

Local Testing (Production-like)

本地测试(类生产环境)

bash
undefined
bash
undefined

Workerd runtime (catches Workers-specific issues)

Workerd运行时(捕获Workers专属问题)

npm run preview
undefined
npm run preview
undefined

Integration Testing

集成测试

Always test in
preview
mode before deploying:
bash
undefined
部署前务必在
preview
模式下测试:
bash
undefined

Build and run in workerd

构建并在workerd中运行

npm run preview
npm run preview

Test bindings (D1, R2, KV, AI)

测试绑定(D1、R2、KV、AI)

Test middleware

测试中间件

Test API routes

测试API路由

Test SSR/ISR behavior

测试SSR/ISR行为

undefined
undefined

Migration from Other Platforms

从其他平台迁移

From Vercel

从Vercel迁移

  1. Copy existing Next.js project
  2. Run existing project migration steps (above)
  3. Update environment variables in Cloudflare dashboard
  4. Replace Vercel-specific features:
    • Vercel Postgres → Cloudflare D1
    • Vercel Blob → Cloudflare R2
    • Vercel KV → Cloudflare KV
    • Vercel Edge Config → Cloudflare KV
  5. Test thoroughly with
    npm run preview
  6. Deploy with
    npm run deploy
  1. 复制现有Next.js项目
  2. 执行上述现有项目迁移步骤
  3. 在Cloudflare控制台中更新环境变量
  4. 替换Vercel专属功能:
    • Vercel Postgres → Cloudflare D1
    • Vercel Blob → Cloudflare R2
    • Vercel KV → Cloudflare KV
    • Vercel Edge Config → Cloudflare KV
  5. 使用
    npm run preview
    进行全面测试
  6. 使用
    npm run deploy
    部署

From AWS / Other Platforms

从AWS / 其他平台迁移

Same process as Vercel migration - the adapter handles Next.js standard features automatically.
与Vercel迁移流程相同 - 适配器会自动处理Next.js标准功能。

Resources

资源

Official Documentation

官方文档

Troubleshooting

故障排除

Related Skills

相关技能

  • cloudflare-worker-base
    - Base Worker setup with Hono + Vite + React
  • cloudflare-d1
    - D1 database integration
  • cloudflare-r2
    - R2 object storage
  • cloudflare-kv
    - KV key-value storage
  • cloudflare-workers-ai
    - Workers AI integration
  • cloudflare-vectorize
    - Vector database for RAG
  • cloudflare-worker-base
    - 基于Hono + Vite + React的基础Worker配置
  • cloudflare-d1
    - D1数据库集成
  • cloudflare-r2
    - R2对象存储
  • cloudflare-kv
    - KV键值对存储
  • cloudflare-workers-ai
    - Workers AI集成
  • cloudflare-vectorize
    - 用于RAG的向量数据库

Quick Reference

快速参考

Essential Commands

核心命令

bash
undefined
bash
undefined

New project

新项目初始化

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

Development

开发

npm run dev # Fast iteration (Next.js dev server) npm run preview # Test in workerd (production-like)
npm run dev # 快速迭代(Next.js开发服务器) npm run preview # 类生产环境测试(workerd运行时)

Deployment

部署

npm run deploy # Build and deploy to Cloudflare
npm run deploy # 构建并部署到Cloudflare

TypeScript

TypeScript类型生成

npm run cf-typegen # Generate binding types
undefined
npm run cf-typegen # 生成绑定类型
undefined

Critical Configuration

关键配置

jsonc
// wrangler.jsonc
{
  "compatibility_date": "2025-05-05",  // Minimum!
  "compatibility_flags": ["nodejs_compat"]  // Required!
}
jsonc
// wrangler.jsonc
{
  "compatibility_date": "2025-05-05",  // 最低要求!
  "compatibility_flags": ["nodejs_compat"]  // 必需!
}

Common Pitfalls

常见陷阱

  1. ❌ Using Edge runtime → ✅ Use Node.js runtime
  2. ❌ Global DB clients → ✅ Request-scoped clients
  3. ❌ Old compatibility_date → ✅ Use 2025-05-05+
  4. ❌ Missing nodejs_compat → ✅ Add to compatibility_flags
  5. ❌ Only testing in
    dev
    → ✅ Always test
    preview
    before deploy
  6. ❌ Using Turbopack → ✅ Use standard Next.js build

Production Tested: Official Cloudflare support and active community Token Savings: ~59% vs manual setup Errors Prevented: 10+ documented issues Last Verified: 2025-10-21
  1. ❌ 使用Edge运行时 → ✅ 使用Node.js运行时
  2. ❌ 全局DB客户端 → ✅ 请求作用域客户端
  3. ❌ 旧版compatibility_date → ✅ 使用2025-05-05及以上版本
  4. ❌ 缺少nodejs_compat → ✅ 添加到compatibility_flags
  5. ❌ 仅在
    dev
    中测试 → ✅ 部署前务必测试
    preview
  6. ❌ 使用Turbopack → ✅ 使用标准Next.js构建

生产验证:官方Cloudflare支持,活跃社区维护 时间节省:相比手动配置节省约59%的时间 错误预防:10余种已记录问题 最后验证时间:2025-10-21