使用 OpenNext 将 Next.js 部署到 Cloudflare Workers

January 20, 2024

在 Cloudflare Workers 上部署 Next.js 项目完整指南

前言

Cloudflare Workers 是一个强大的边缘计算平台,可以在全球数百个数据中心运行你的应用代码。随着 OpenNext 项目的 Cloudflare 适配器的发布,现在可以将 Next.js 应用完整地部署到 Cloudflare Workers 上,享受边缘计算带来的极致性能。

本文将详细介绍如何使用 @opennextjs/cloudflare 适配器将 Next.js 项目部署到 Cloudflare Workers(注意:这与 Cloudflare Pages 是不同的部署方式)。

什么是 @opennextjs/cloudflare?

@opennextjs/cloudflare 是 OpenNext 项目的 Cloudflare 适配器,它可以将 Next.js 的构建输出转换为可以在 Cloudflare Workers 上运行的格式。这个适配器使用 Cloudflare 的 Node.js 兼容层,让 Next.js 应用能够在 Workers 的 workerd 运行时中执行。

支持的功能

  • ✅ 静态站点生成 (SSG)
  • ✅ 服务端渲染 (SSR)
  • ✅ 增量静态再生成 (ISR)
  • ✅ API 路由
  • ✅ 中间件
  • ✅ 图片优化
  • ✅ Next.js 14 和 15

准备工作

在开始之前,确保你已经安装:

  • Node.js 18 或更高版本
  • npm、pnpm 或 yarn
  • 一个 Cloudflare 账号
  • 已有的 Next.js 项目(或准备创建一个新项目)

方案一:创建新的 Next.js 项目(推荐新手)

使用 create-cloudflare CLI

Cloudflare 提供了官方的 CLI 工具来快速搭建项目:

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

这个命令会:

  1. 创建一个新的 Next.js 项目
  2. 自动配置 @opennextjs/cloudflare 适配器
  3. 生成必要的配置文件
  4. 安装所有依赖

创建完成后,进入项目目录:

cd my-next-app

方案二:为现有项目添加 Cloudflare Workers 支持

第一步:安装依赖

在你的 Next.js 项目根目录执行:

# 使用 npm
npm install @opennextjs/cloudflare@latest
npm install --save-dev wrangler@latest

# 或使用 pnpm
pnpm install @opennextjs/cloudflare@latest
pnpm install --save-dev wrangler@latest

# 或使用 yarn
yarn add @opennextjs/cloudflare@latest
yarn add --dev wrangler@latest

第二步:配置 package.json

package.json 中添加以下脚本:

{
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "build-open": "opennextjs-cloudflare build",
    "preview": "opennextjs-cloudflare build && opennextjs-cloudflare preview",
    "deploy": "opennextjs-cloudflare build && opennextjs-cloudflare deploy",
    "upload": "opennextjs-cloudflare build && opennextjs-cloudflare upload",
    "cf-typegen": "wrangler types --env-interface CloudflareEnv cloudflare-env.d.ts"
  }
}

命令说明:

  • build: Next.js 标准构建命令
  • build-open: 使用 OpenNext 适配器构建
  • preview: 本地预览 Worker
  • deploy: 部署到 Cloudflare(立即生效)
  • upload: 上传新版本(用于渐进式部署)

第三步:配置 next.config.js

修改 next.config.js 以支持 Cloudflare 开发环境:

import { initOpenNextCloudflareForDev } from "@opennextjs/cloudflare";

// 仅在开发环境初始化
if (process.env.NODE_ENV === "development") {
  await initOpenNextCloudflareForDev();
}

/** @type {import('next').NextConfig} */
const nextConfig = {
  // 你的其他配置...
};

export default nextConfig;

第四步:创建 wrangler.jsonc 配置文件

在项目根目录创建 wrangler.jsonc 文件:

{
  "$schema": "node_modules/wrangler/config-schema.json",
  "name": "my-nextjs-app",
  "main": ".open-next/worker.js",
  "compatibility_date": "2024-12-30",
  "compatibility_flags": [
    "nodejs_compat",
    "global_fetch_strictly_public"
  ],
  "assets": {
    "directory": ".open-next/assets"
  }
}

重要配置说明:

  • compatibility_date: 必须设置为 2024-09-23 或更新的日期,这样 process.env 才能正常工作
  • nodejs_compat: 必须启用,提供 Node.js API 兼容性
  • main: 指向构建后的 Worker 入口文件
  • assets: 静态资源目录

第五步:创建 open-next.config.ts(可选)

如果需要使用 R2 进行缓存,创建 open-next.config.ts

import { defineCloudflareConfig } from "@opennextjs/cloudflare";
import r2IncrementalCache from "@opennextjs/cloudflare/overrides/incremental-cache/r2-incremental-cache";

export default defineCloudflareConfig({
  incrementalCache: r2IncrementalCache,
});

本地开发和测试

开发模式

使用标准的 Next.js 开发服务器:

npm run dev

在浏览器访问 http://localhost:3000

预览 Worker

在本地 Workers 运行时中测试应用:

npm run preview

这会:

  1. 构建你的应用
  2. 在 workerd 运行时中启动本地服务器
  3. 模拟生产环境

重要提示: 预览模式更接近生产环境,建议在部署前先运行预览测试。

部署到 Cloudflare Workers

方法一:从本地部署

首先登录 Cloudflare:

npx wrangler login

然后部署:

npm run deploy

首次部署会提示你选择 Cloudflare 账号和创建 Worker 名称。

方法二:使用 Workers Builds(CI/CD)

Workers Builds 是 Cloudflare 提供的持续集成服务,可以自动构建和部署。

步骤 1:推送代码到 Git

确保你的代码已推送到 GitHub 或 GitLab。

步骤 2:在 Cloudflare 中配置

  1. 登录 Cloudflare Dashboard
  2. 进入 "Workers & Pages"
  3. 点击 "Create application"
  4. 选择 "Workers"
  5. 选择 "Connect to Git"
  6. 授权并选择你的仓库

步骤 3:配置构建设置

在构建配置中设置:

  • Framework preset: 选择 "None" 或 "Next.js"
  • Build command: npm run build-opennpx opennextjs-cloudflare build
  • Build output directory: .open-next

步骤 4:添加环境变量

在 "Settings" > "Environment variables" 中添加:

NODE_VERSION=18

以及你的应用需要的其他环境变量。

步骤 5:部署

保存配置后,Cloudflare 会自动触发第一次构建和部署。

配置缓存(使用 R2)

为了获得更好的性能,建议配置 R2 存储桶用于 ISR 缓存。

创建 R2 存储桶

npx wrangler r2 bucket create next-cache

在 wrangler.jsonc 中绑定

{
  "r2_buckets": [
    {
      "binding": "NEXT_INC_CACHE_R2_BUCKET",
      "bucket_name": "next-cache"
    }
  ]
}

配置 open-next.config.ts

import { defineCloudflareConfig } from "@opennextjs/cloudflare";
import r2IncrementalCache from "@opennextjs/cloudflare/overrides/incremental-cache/r2-incremental-cache";

export default defineCloudflareConfig({
  incrementalCache: r2IncrementalCache,
});

使用 Cloudflare 绑定

Cloudflare Workers 可以通过绑定访问各种服务。

配置 KV 存储

wrangler.jsonc 中添加:

{
  "kv_namespaces": [
    {
      "binding": "MY_KV",
      "id": "your-kv-namespace-id"
    }
  ]
}

在 Next.js 中使用

API 路由中访问

// app/api/data/route.ts
import { NextRequest } from "next/server";

export const runtime = "edge";

export async function GET(request: NextRequest) {
  // 从环境中获取绑定
  const env = process.env as any;
  const value = await env.MY_KV.get("mykey");
  
  return Response.json({ value });
}

服务端组件中访问

// app/page.tsx
import { getCloudflareContext } from "@opennextjs/cloudflare";

export default async function Home() {
  const { env } = await getCloudflareContext();
  const data = await env.MY_KV.get("mykey");
  
  return <div>{data}</div>;
}

环境变量管理

本地开发

创建 .dev.vars 文件(类似 .env.local):

API_KEY=dev-api-key
DATABASE_URL=http://localhost:3000

生产环境

通过 Wrangler 设置:

npx wrangler secret put API_KEY

或在 Cloudflare Dashboard 的 "Settings" > "Variables and Secrets" 中配置。

限制和注意事项

1. 仅支持 Node.js 运行时

目前适配器仅支持 Next.js 的 Node.js 运行时,不支持 Edge Runtime。如果你的代码中有:

export const runtime = "edge";

需要移除这行,或将其改为:

export const runtime = "nodejs";

但不用担心,即使使用 Node.js 运行时,代码仍然运行在全球边缘节点上。

2. CPU 时间限制

Cloudflare Workers 有 CPU 时间限制:

  • 免费计划:10ms CPU 时间
  • 付费计划:30ms CPU 时间(可配置更高)

3. 内存限制

Workers 的内存限制为 128MB,需要注意避免内存密集型操作。

4. 不支持的功能

  • next/image 的某些优化功能可能受限
  • 某些 Node.js 原生模块可能不兼容
  • 文件系统操作受限

性能优化建议

1. 启用 ISR

使用增量静态再生成来平衡性能和内容新鲜度:

export const revalidate = 3600; // 每小时重新验证

2. 使用边缘缓存

在 API 路由中设置缓存头:

export async function GET() {
  return new Response(JSON.stringify(data), {
    headers: {
      "Cache-Control": "public, s-maxage=3600",
      "Content-Type": "application/json",
    },
  });
}

3. 优化依赖包大小

Workers 对包大小有限制,使用以下命令分析:

npx wrangler deploy --dry-run --outdir=dist

4. 使用 Cloudflare Images

对于图片优化,使用 Cloudflare Images 服务而不是 Next.js 内置的图片优化。

监控和调试

查看实时日志

npx wrangler tail

查看部署日志

在 Cloudflare Dashboard 的 "Workers & Pages" > 你的项目 > "Deployments" 中查看。

分析性能

使用 Cloudflare 的 Analytics 面板查看:

  • 请求量
  • 错误率
  • P50/P99 延迟
  • CPU 使用时间

渐进式部署

使用 upload 命令而不是 deploy 来创建新版本而不立即激活:

npm run upload

然后在 Cloudflare Dashboard 中手动控制流量切换百分比:

  • 0.05% → 0.5% → 3% → 10% → 25% → 50% → 75% → 100%

这样可以安全地测试新版本,发现问题时快速回滚。

自定义域名

在 Cloudflare Dashboard 中:

  1. 进入你的 Worker 项目
  2. 点击 "Settings" > "Domains & Routes"
  3. 添加自定义域名
  4. 配置 DNS 记录(如果域名在 Cloudflare)

故障排查

构建失败:找不到 wrangler.jsonc

确保文件在项目根目录,或运行:

npm run build-open

它会自动生成默认配置。

环境变量为空

检查 wrangler.jsonc 中的 compatibility_date 是否为 2024-09-23 或更新。

内存超限

优化代码,减少内存占用,或考虑将部分逻辑移到外部 API。

Node.js API 不兼容

查看 Cloudflare 的 Node.js 兼容性列表,使用支持的 API 或寻找替代方案。

完整示例项目

这是一个最小化的项目结构:

my-nextjs-app/
├── app/
│   ├── api/
│   │   └── hello/
│   │       └── route.ts
│   ├── layout.tsx
│   └── page.tsx
├── next.config.js
├── wrangler.jsonc
├── open-next.config.ts
├── package.json
├── .dev.vars
└── .gitignore

package.json

{
  "name": "my-nextjs-app",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "build-open": "opennextjs-cloudflare build",
    "preview": "opennextjs-cloudflare build && opennextjs-cloudflare preview",
    "deploy": "opennextjs-cloudflare build && opennextjs-cloudflare deploy"
  },
  "dependencies": {
    "next": "^15.0.0",
    "react": "^18.3.0",
    "react-dom": "^18.3.0",
    "@opennextjs/cloudflare": "latest"
  },
  "devDependencies": {
    "wrangler": "latest",
    "typescript": "^5",
    "@types/node": "^20",
    "@types/react": "^18",
    "@types/react-dom": "^18"
  }
}

与其他平台对比

与其他平台对比

总结

在 Cloudflare Workers 上部署 Next.js 项目通过 @opennextjs/cloudflare 适配器已经变得非常成熟和可靠。这种部署方式的主要优势:

优势

  • 全球边缘部署:代码运行在离用户最近的数据中心
  • 极低延迟:冷启动时间几乎可以忽略不计
  • 成本效益:慷慨的免费额度,按需付费
  • 强大的生态:深度集成 KV、R2、D1 等 Cloudflare 服务
  • 渐进式部署:安全地测试和发布新版本

适用场景

  • 全球化应用,需要低延迟
  • 高流量网站,需要边缘缓存
  • API 密集型应用
  • 需要与 Cloudflare 生态集成的项目

不适用场景

  • 需要长时间运行的后台任务
  • 需要大量文件系统操作
  • 依赖特定 Node.js 原生模块

通过本指南,你应该能够成功将 Next.js 项目部署到 Cloudflare Workers,并充分利用边缘计算的优势。祝你部署顺利!

参考资源