cloudflare-nextjs by jackspace/claudeskillz
npx skills add https://github.com/jackspace/claudeskillz --skill cloudflare-nextjs使用 OpenNext Cloudflare 适配器将 Next.js 应用程序部署到 Cloudflare Workers,实现生产就绪的无服务器 Next.js 托管。
OpenNext Cloudflare 适配器(@opennextjs/cloudflare)将 Next.js 构建输出转换为 Cloudflare Worker 兼容的格式。这与标准的 Next.js 部署有根本区别:
next build → OpenNext 转换 → Worker 部署| 方面 | 标准 Next.js |
|---|
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
| Cloudflare Workers |
|---|
| 运行时 | Node.js 或 Edge | Node.js(通过 nodejs_compat) |
| 开发服务器 | next dev | next dev + opennextjs-cloudflare preview |
| 部署 | 平台特定 | opennextjs-cloudflare deploy |
| Worker 大小 | 无限制 | 3 MiB(免费)/ 10 MiB(付费) |
| 数据库连接 | 全局客户端可用 | 必须是请求作用域 |
| 图片优化 | 内置 | 通过 Cloudflare Images |
| 缓存 | Next.js 缓存 | OpenNext 配置 + Workers 缓存 |
使用 Cloudflare 的 create-cloudflare(C3)CLI 来搭建一个为 Workers 预配置的新 Next.js 项目:
npm create cloudflare@latest -- my-next-app --framework=next
此命令的作用:
create-next-app)@opennextjs/cloudflare 适配器wrangler.jsoncopen-next.config.tspackage.json开发工作流:
npm run dev # Next.js 开发服务器(快速重载)
npm run preview # 在 workerd 运行时中测试(类生产环境)
npm run deploy # 构建并部署到 Cloudflare
要将 OpenNext 适配器添加到现有的 Next.js 应用程序:
npm install --save-dev @opennextjs/cloudflare
{
"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 运行时)import { defineCloudflareConfig } from "@opennextjs/cloudflare";
export default defineCloudflareConfig({
// 缓存配置(可选)
// 参见:https://opennext.js.org/cloudflare/caching
});
{
"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:构建 + 部署到 Cloudflarecf-typegen:为 Cloudflare 绑定生成 TypeScript 类型从你的应用中移除 Edge 运行时导出:
// ❌ 移除此项(不支持 Edge 运行时)
export const runtime = "edge";
// ✅ 使用 Node.js 运行时(默认)
// 无需导出 - Node.js 是默认值
始终在两个环境中测试:
Next.js 开发服务器(npm run dev)
Workerd 运行时(npm run preview)
# 迭代 UI/逻辑 → 使用 Next.js 开发服务器
npm run dev
# 测试集成(D1、R2、KV) → 使用预览
npm run preview
# 部署前 → 始终测试预览
npm run preview
# 部署到生产环境
npm run deploy
wrangler.jsonc 中的最低要求:
{
"name": "your-app-name",
"compatibility_date": "2025-05-05", // FinalizationRegistry 所需的最低版本
"compatibility_flags": ["nodejs_compat"] // Node.js 运行时必需
}
如果使用具有多个导出条件的 npm 包,请创建 .env:
WRANGLER_BUILD_CONDITIONS=""
WRANGLER_BUILD_PLATFORM="node"
这确保 Wrangler 在有 node 导出时优先使用它。
在 wrangler.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 中访问绑定:
// 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 });
}
错误:"Your Worker exceeded the size limit of 3 MiB"
原因:Workers 免费计划将 Worker 大小限制为 3 MiB(gzip 压缩后)
解决方案:
包分析:
npx opennextjs-cloudflare build
cd .open-next/server-functions/default
# 使用 ESBuild Bundle Analyzer 分析 handler.mjs.meta.json
错误:"Your Worker exceeded the size limit of 10 MiB"
原因:不必要的代码被打包到 Worker 中
调试工作流:
npx opennextjs-cloudflare build.open-next/server-functions/defaulthandler.mjs.meta.json错误:"ReferenceError: FinalizationRegistry is not defined"
原因:wrangler.jsonc 中的 compatibility_date 太旧
解决方案:将 compatibility_date 更新为 2025-05-05 或更高版本:
{
"compatibility_date": "2025-05-05" // FinalizationRegistry 所需的最低版本
}
错误:"Cannot perform I/O on behalf of a different request"
原因:数据库客户端在全局创建并在多个请求间重用
问题代码:
// ❌ 错误:全局 DB 客户端
import { Pool } from 'pg';
const pool = new Pool({ connectionString: process.env.DATABASE_URL });
export async function GET() {
// 这将失败 - pool 在不同的请求上下文中创建
const result = await pool.query('SELECT * FROM users');
return Response.json(result);
}
解决方案:在请求处理程序内部创建数据库客户端:
// ✅ 正确:请求作用域的 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 设计)而非外部数据库:
// ✅ 最佳:使用 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);
}
错误:"Could not resolve '<package>'"
原因:缺少 nodejs_compat 标志或包导出条件
解决方案 1:启用 nodejs_compat 标志:
{
"compatibility_flags": ["nodejs_compat"]
}
解决方案 2:对于具有多个导出的包,创建 .env:
WRANGLER_BUILD_CONDITIONS=""
WRANGLER_BUILD_PLATFORM="node"
错误:"Failed to load chunk server/chunks/ssr/"
原因:Next.js 使用 Turbopack 构建(next build --turbo)
解决方案:使用标准构建(适配器不支持 Turbopack):
{
"scripts": {
"build": "next build" // ✅ 正确
// "build": "next build --turbo" // ❌ 不要使用 Turbopack
}
}
漏洞:通过 /_next/image 端点进行服务器端请求伪造
受影响版本:@opennextjs/cloudflare < 1.3.0
解决方案:升级到 1.3.0 或更高版本:
npm install --save-dev @opennextjs/cloudflare@^1.3.0
影响:允许未经身份验证的用户代理任意远程内容
警告:"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
错误:在 Next.js 中间件中使用 @prisma/client + @prisma/adapter-d1 时出现构建错误
原因:在中间件上下文中初始化数据库
变通方案:在路由处理程序中初始化 Prisma 客户端,而非中间件
错误:使用依赖 cross-fetch 的库时出现错误
原因:OpenNext 修补了部署包,导致 cross-fetch 在原生 fetch 可用时尝试使用 Node.js 库
解决方案:直接使用原生 fetch API 而非 cross-fetch:
// ✅ 使用原生 fetch
const response = await fetch('https://api.example.com/data');
// ❌ 避免使用 cross-fetch
// import fetch from 'cross-fetch';
问题:不保证完整的 Windows 支持
原因:底层 Next.js 工具在 Windows 上的问题
解决方案:
| 功能 | 状态 | 备注 |
|---|---|---|
| App Router | ✅ 完全支持 | 最新的 App Router 功能可用 |
| Pages Router | ✅ 完全支持 | 支持旧版 Pages Router |
| 路由处理器 | ✅ 完全支持 | API 路由按预期工作 |
| React 服务器组件 | ✅ 完全支持 | RSC 功能完整 |
| 服务器操作 | ✅ 完全支持 | 服务器操作可用 |
| SSG | ✅ 完全支持 | 静态站点生成 |
| SSR | ✅ 完全支持 | 服务器端渲染 |
| ISR | ✅ 完全支持 | 增量静态再生 |
| 中间件 | ✅ 支持 | 除了 Node.js 中间件(15.2+) |
| 图片优化 | ✅ 支持 | 通过 Cloudflare Images |
| 部分预渲染(PPR) | ✅ 支持 | Next.js 中的实验性功能 |
| 可组合缓存 | ✅ 支持 | 'use cache' 指令 |
| 响应流式传输 | ✅ 支持 | 流式响应可用 |
next/after API | ✅ 支持 | 响应后异步工作 |
| Node.js 中间件(15.2+) | ❌ 不支持 | 计划未来支持 |
| Edge 运行时 | ❌ 不支持 | 使用 Node.js 运行时 |
// 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 配置:
{
"d1_databases": [
{
"binding": "DB",
"database_name": "production-db",
"database_id": "your-database-id"
}
]
}
另请参阅:cloudflare-d1 技能以获取完整的 D1 模式
// 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 模式
// 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 配置:
{
"ai": {
"binding": "AI"
}
}
另请参阅:cloudflare-workers-ai 技能以获取完整的 AI 模式
// 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 模式
Next.js 图片优化通过 Cloudflare Images 工作。在 open-next.config.ts 中配置:
import { defineCloudflareConfig } from "@opennextjs/cloudflare";
export default defineCloudflareConfig({
imageOptimization: {
loader: 'cloudflare'
}
});
在组件中使用:
import Image from 'next/image';
export default function Avatar() {
return (
<Image
src="/avatar.jpg"
alt="User avatar"
width={200}
height={200}
// 通过 Cloudflare Images 自动优化
/>
);
}
计费:Cloudflare Images 使用单独计费
在 open-next.config.ts 中配置缓存行为:
import { defineCloudflareConfig } from "@opennextjs/cloudflare";
export default defineCloudflareConfig({
// 自定义缓存配置
cache: {
// 覆盖默认缓存行为
// 参见:https://opennext.js.org/cloudflare/caching
}
});
默认行为:OpenNext 提供合理的缓存默认值
高级用法:参见 OpenNext 官方缓存文档
Node.js 中间件(Next.js 15.2+)
Edge 运行时
export const runtime = "edge"完整的 Windows 支持
# 在一个命令中构建和部署
npm run deploy
# 或分步执行:
npx opennextjs-cloudflare build
npx opennextjs-cloudflare deploy
在你的 CI/CD 系统中配置部署命令:
npm run deploy
示例:
.github/workflows/deploy.yml.gitlab-ci.ymlnpm run deploy环境变量:在 Cloudflare 仪表板或 CI/CD 系统中设置密钥
在 Cloudflare 仪表板中添加自定义域名:
DNS:域名必须在 Cloudflare 上(需要区域)
为 Cloudflare 绑定生成类型:
npm run cf-typegen
创建包含绑定类型的 cloudflare-env.d.ts:
// cloudflare-env.d.ts(自动生成)
interface CloudflareEnv {
DB: D1Database;
BUCKET: R2Bucket;
KV: KVNamespace;
AI: Ai;
}
在路由处理器中使用:
import type { NextRequest } from 'next/server';
export async function GET(request: NextRequest) {
const env = process.env as CloudflareEnv;
// 现在 env.DB、env.BUCKET 等已具有类型
}
# Next.js 开发服务器(快速迭代)
npm run dev
# Workerd 运行时(捕获 Workers 特定问题)
npm run preview
部署前始终在 preview 模式下测试:
# 构建并在 workerd 中运行
npm run preview
# 测试绑定(D1、R2、KV、AI)
# 测试中间件
# 测试 API 路由
# 测试 SSR/ISR 行为
npm run preview 彻底测试npm run deploy 部署与 Vercel 迁移过程相同 - 适配器会自动处理 Next.js 标准功能。
cloudflare-worker-base - 使用 Hono + Vite + React 的基础 Worker 设置cloudflare-d1 - D1 数据库集成cloudflare-r2 - R2 对象存储cloudflare-kv - KV 键值存储cloudflare-workers-ai - Workers AI 集成cloudflare-vectorize - 用于 RAG 的向量数据库# 新项目
npm create cloudflare@latest -- my-next-app --framework=next
# 开发
npm run dev # 快速迭代(Next.js 开发服务器)
npm run preview # 在 workerd 中测试(类生产环境)
# 部署
npm run deploy # 构建并部署到 Cloudflare
# TypeScript
npm run cf-typegen # 生成绑定类型
// wrangler.jsonc
{
"compatibility_date": "2025-05-05", // 最低要求!
"compatibility_flags": ["nodejs_compat"] // 必需!
}
dev 中测试 → ✅ 部署前始终测试 preview生产环境测试:官方 Cloudflare 支持和活跃社区 节省 Token:与手动设置相比约 59% 预防错误:10+ 个已记录问题 最后验证:2025-10-21
每周安装
73
仓库
GitHub Stars
10
首次出现
Jan 24, 2026
安全审计
已安装于
opencode63
gemini-cli62
codex58
cursor54
github-copilot51
claude-code49
Deploy Next.js applications to Cloudflare Workers using the OpenNext Cloudflare adapter for production-ready serverless Next.js hosting.
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:
next build → OpenNext transformation → Worker deployment| Aspect | Standard Next.js | Cloudflare Workers |
|---|---|---|
| Runtime | Node.js or Edge | Node.js (via nodejs_compat) |
| Dev Server | next dev | next dev + opennextjs-cloudflare preview |
| Deployment | Platform-specific | opennextjs-cloudflare deploy |
| Worker Size | No limit | 3 MiB (free) / 10 MiB (paid) |
| Database Connections | Global clients OK | Must be request-scoped |
| Image Optimization |
Use Cloudflare's create-cloudflare (C3) CLI to scaffold a new Next.js project pre-configured for Workers:
npm create cloudflare@latest -- my-next-app --framework=next
What this does :
create-next-app)@opennextjs/cloudflare adapterwrangler.jsonc with correct configurationopen-next.config.ts for caching configurationpackage.jsonDevelopment workflow :
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
To add the OpenNext adapter to an existing Next.js application:
npm install --save-dev @opennextjs/cloudflare
{
"name": "my-next-app",
"compatibility_date": "2025-05-05",
"compatibility_flags": ["nodejs_compat"]
}
Critical configuration :
compatibility_date: Minimum2025-05-05 (for FinalizationRegistry support)compatibility_flags: Must includenodejs_compat (for Node.js runtime)import { defineCloudflareConfig } from "@opennextjs/cloudflare";
export default defineCloudflareConfig({
// Caching configuration (optional)
// See: https://opennext.js.org/cloudflare/caching
});
{
"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 Cloudflarecf-typegen: Generate TypeScript types for Cloudflare bindingsRemove Edge runtime exports from your app:
// ❌ REMOVE THIS (Edge runtime not supported)
export const runtime = "edge";
// ✅ Use Node.js runtime (default)
// No export needed - Node.js is default
Always test in BOTH environments :
Next.js Dev Server (npm run dev)
Workerd Runtime (npm run preview)
# Iterating on UI/logic → Use Next.js dev server
npm run dev
# Testing integrations (D1, R2, KV) → Use preview
npm run preview
# Before deploying → ALWAYS test preview
npm run preview
# Deploy to production
npm run deploy
Minimum requirements in wrangler.jsonc:
{
"name": "your-app-name",
"compatibility_date": "2025-05-05", // Minimum for FinalizationRegistry
"compatibility_flags": ["nodejs_compat"] // Required for Node.js runtime
}
If using npm packages with multiple export conditions, create .env:
WRANGLER_BUILD_CONDITIONS=""
WRANGLER_BUILD_PLATFORM="node"
This ensures Wrangler prioritizes the node export when available.
Add bindings in wrangler.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:
// 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 });
}
Error : "Your Worker exceeded the size limit of 3 MiB"
Cause : Workers Free plan limits Worker size to 3 MiB (gzip-compressed)
Solutions :
Bundle analysis :
npx opennextjs-cloudflare build
cd .open-next/server-functions/default
# Analyze handler.mjs.meta.json with ESBuild Bundle Analyzer
Source : https://opennext.js.org/cloudflare/troubleshooting#worker-size-limits
Error : "Your Worker exceeded the size limit of 10 MiB"
Cause : Unnecessary code bundled into Worker
Debug workflow :
npx opennextjs-cloudflare build.open-next/server-functions/defaulthandler.mjs.meta.json using ESBuild Bundle AnalyzerSource : https://opennext.js.org/cloudflare/troubleshooting#worker-size-limits
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:
{
"compatibility_date": "2025-05-05" // Minimum for FinalizationRegistry
}
Source : https://opennext.js.org/cloudflare/troubleshooting#finalizationregistry-is-not-defined
Error : "Cannot perform I/O on behalf of a different request"
Cause : Database client created globally and reused across requests
Problem code :
// ❌ 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:
// ✅ 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:
// ✅ 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);
}
Error : "Could not resolve '<package>'"
Cause : Missing nodejs_compat flag or package export conditions
Solution 1 : Enable nodejs_compat flag:
{
"compatibility_flags": ["nodejs_compat"]
}
Solution 2 : For packages with multiple exports, create .env:
WRANGLER_BUILD_CONDITIONS=""
WRANGLER_BUILD_PLATFORM="node"
Source : https://opennext.js.org/cloudflare/troubleshooting#npm-packages-fail-to-import
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):
{
"scripts": {
"build": "next build" // ✅ Correct
// "build": "next build --turbo" // ❌ Don't use Turbopack
}
}
Source : https://opennext.js.org/cloudflare/troubleshooting#failed-to-load-chunk
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:
npm install --save-dev @opennextjs/cloudflare@^1.3.0
Impact : Allows unauthenticated users to proxy arbitrary remote content
Source : https://github.com/advisories/GHSA-rvpw-p7vw-wj3m
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
Source : https://opennext.js.org/cloudflare/known-issues#caching-durable-objects
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
Source : https://github.com/opennextjs/opennextjs-cloudflare/issues/471
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:
// ✅ Use native fetch
const response = await fetch('https://api.example.com/data');
// ❌ Avoid cross-fetch
// import fetch from 'cross-fetch';
Source : https://opennext.js.org/cloudflare/troubleshooting
Issue : Full Windows support not guaranteed
Cause : Underlying Next.js tooling issues on Windows
Solutions :
Source : https://opennext.js.org/cloudflare#windows-support
| Feature | Status | Notes |
|---|---|---|
| App Router | ✅ Fully Supported | Latest App Router features work |
| Pages Router | ✅ Fully Supported | Legacy Pages Router supported |
| Route Handlers | ✅ Fully Supported | API routes work as expected |
| React Server Components | ✅ Fully Supported | RSC fully functional |
| Server Actions | ✅ Fully Supported | Server Actions work |
| SSG | ✅ Fully Supported | Static Site Generation |
| SSR | ✅ Fully Supported | Server-Side Rendering |
| ISR |
// 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 :
{
"d1_databases": [
{
"binding": "DB",
"database_name": "production-db",
"database_id": "your-database-id"
}
]
}
See also : cloudflare-d1 skill for complete D1 patterns
// 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
// 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 :
{
"ai": {
"binding": "AI"
}
}
See also : cloudflare-workers-ai skill for complete AI patterns
// 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
Next.js image optimization works via Cloudflare Images. Configure in open-next.config.ts:
import { defineCloudflareConfig } from "@opennextjs/cloudflare";
export default defineCloudflareConfig({
imageOptimization: {
loader: 'cloudflare'
}
});
Usage in components:
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
Docs : https://developers.cloudflare.com/images/
Configure caching behavior in open-next.config.ts:
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
Node.js Middleware (Next.js 15.2+)
Edge Runtime
export const runtime = "edge" from your appFull Windows Support
# Build and deploy in one command
npm run deploy
# Or step by step:
npx opennextjs-cloudflare build
npx opennextjs-cloudflare deploy
Configure deployment command in your CI/CD system:
npm run deploy
Examples :
.github/workflows/deploy.yml.gitlab-ci.ymlnpm run deployEnvironment variables : Set secrets in Cloudflare dashboard or CI/CD system
Add custom domain in Cloudflare dashboard:
DNS : Domain must be on Cloudflare (zone required)
Generate types for Cloudflare bindings:
npm run cf-typegen
Creates cloudflare-env.d.ts with types for your bindings:
// cloudflare-env.d.ts (auto-generated)
interface CloudflareEnv {
DB: D1Database;
BUCKET: R2Bucket;
KV: KVNamespace;
AI: Ai;
}
Use in route handlers:
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
}
# Next.js dev server (fast iteration)
npm run dev
# Workerd runtime (catches Workers-specific issues)
npm run preview
Always test in preview mode before deploying:
# Build and run in workerd
npm run preview
# Test bindings (D1, R2, KV, AI)
# Test middleware
# Test API routes
# Test SSR/ISR behavior
npm run previewnpm run deploySame process as Vercel migration - the adapter handles Next.js standard features automatically.
cloudflare-worker-base - Base Worker setup with Hono + Vite + Reactcloudflare-d1 - D1 database integrationcloudflare-r2 - R2 object storagecloudflare-kv - KV key-value storagecloudflare-workers-ai - Workers AI integrationcloudflare-vectorize - Vector database for RAG# New project
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)
# Deployment
npm run deploy # Build and deploy to Cloudflare
# TypeScript
npm run cf-typegen # Generate binding types
// wrangler.jsonc
{
"compatibility_date": "2025-05-05", // Minimum!
"compatibility_flags": ["nodejs_compat"] // Required!
}
dev → ✅ Always test preview before deployProduction Tested : Official Cloudflare support and active community Token Savings : ~59% vs manual setup Errors Prevented : 10+ documented issues Last Verified : 2025-10-21
Weekly Installs
73
Repository
GitHub Stars
10
First Seen
Jan 24, 2026
Security Audits
Gen Agent Trust HubWarnSocketPassSnykPass
Installed on
opencode63
gemini-cli62
codex58
cursor54
github-copilot51
claude-code49
Azure Data Explorer (Kusto) 查询技能:KQL数据分析、日志遥测与时间序列处理
145,500 周安装
| Built-in |
| Via Cloudflare Images |
| Caching | Next.js cache | OpenNext config + Workers cache |
| ✅ Fully Supported |
| Incremental Static Regeneration |
| Middleware | ✅ Supported | Except Node.js middleware (15.2+) |
| Image Optimization | ✅ Supported | Via Cloudflare Images |
| Partial Prerendering (PPR) | ✅ Supported | Experimental in Next.js |
| Composable Caching | ✅ Supported | 'use cache' directive |
| Response Streaming | ✅ Supported | Streaming responses work |
next/after API | ✅ Supported | Post-response async work |
| Node.js Middleware (15.2+) | ❌ Not Supported | Future support planned |
| Edge Runtime | ❌ Not Supported | Use Node.js runtime |