
字节笔记本
2026年10月6日 · 约 11 分钟读完
把 Next.js 部署到 Cloudflare Pages
如果你在用 Next.js 做全栈应用,又想要全球访问速度和足够低的成本,Cloudflare Pages 值得认真考虑。它提供遍布全球的边缘网络、自动构建部署和慷慨的免费套餐,Workers 的边缘运行时基于 V8 引擎,请求处理延迟很低。本文整理自 Cloudflare 官方文档中的 Next.js 部署指南,从方案选型讲到绑定集成与问题排查,帮你把整个流程一次跑通。
一、先选对部署方案
Next.js 是广受欢迎的 React 全栈框架,服务端渲染(SSR)、静态站点生成(SSG)和 API 路由都能胜任;Cloudflare Pages 则是一个专注前端与全栈托管的 JAMstack 平台,自带全球 CDN 和持续集成能力。把两者接起来,目前有两条官方路线:
1. @cloudflare/next-on-pages:官方支持的 Pages 部署适配器,适合大多数标准 Next.js 应用,流程简单直接,但只支持 Edge Runtime。
2. @opennextjs/cloudflare:把 Next.js 应用构建并部署到 Cloudflare Workers,可以使用 Workers 所支持的 Node.js API,覆盖的 Next.js 特性更多,不过在文档成文时该项目仍在开发中。
选型时可以参考官方提供的 OpenNext 文档,以及 Workers 与 Pages 的兼容性矩阵:应用若只用边缘运行时能覆盖的能力,选 next-on-pages 最省事;依赖更完整的 Node.js 生态时,重点评估 OpenNext。版本方面,next-on-pages 支持 Next.js 13 和 14 的所有次版本,官方会定期做兼容性测试来保证稳定性。
二、五步完成项目改造
第 1 步:安装依赖
npm install --save-dev @cloudflare/next-on-pages全新项目也可以直接用官方脚手架创建:
pnpm create cloudflare@latest my-next-app --framework=next第 2 步:添加 wrangler.toml
在项目根目录创建 wrangler.toml:
name = "my-app"
compatibility_date = "2024-07-29"
compatibility_flags = ["nodejs_compat"]
pages_build_output_dir = ".vercel/output/static"compatibility_date 决定运行时行为对齐到哪个日期的版本;nodejs_compat 开启 Node.js 兼容层;pages_build_output_dir 指向适配器的构建产物目录。
第 3 步:改造 next.config.mjs
import { setupDevPlatform } from '@cloudflare/next-on-pages/next-dev';
/** @type {import('next').NextConfig} */
const nextConfig = {};
if (process.env.NODE_ENV === 'development') {
await setupDevPlatform();
}
export default nextConfig;setupDevPlatform 只在开发环境生效,作用是给本地开发接入 Cloudflare 的开发平台能力,让绑定在本地也能用。
第 4 步:服务端路由切换 Edge Runtime
所有服务端渲染的路由都需要声明使用 Edge Runtime,这是最容易漏掉的一步:
// app/api/hello/route.js
export const runtime = "edge";
export async function GET() {
return new Response('Hello World');
}第 5 步:补充构建脚本
在 package.json 中加入三个命令:
{
"scripts": {
"pages:build": "npx @cloudflare/next-on-pages",
"preview": "npm run pages:build && wrangler pages dev",
"deploy": "npm run pages:build && wrangler pages deploy"
}
}pages:build 负责把 Next.js 构建成 Pages 可用的产物,preview 在本地起预览服务,deploy 直接推上生产环境。至此项目改造完成,整条链路如下图:

三、用绑定访问 KV、R2 等云服务
部署到边缘之后,应用可以通过绑定(Bindings)访问 Cloudflare 的 KV、R2、D1 等存储服务。适配器提供了 getRequestContext 方法,在任意路由中都能拿到当前请求的上下文:
import { getRequestContext } from "@cloudflare/next-on-pages";
export const runtime = "edge";
export async function GET(request) {
const { env, cf, ctx } = getRequestContext();
const data = await env.MY_KV.get("key");
return new Response(data);
}env 里是你在 wrangler.toml 中声明的各类绑定,cf 携带传入请求的上下文信息,ctx 提供生命周期方法。
为了拿到准确的 TypeScript 类型,先安装官方类型包:
npm install --save-dev @cloudflare/workers-types在 tsconfig.json 的 types 中引入,日期替换为你项目的兼容日期:
"types": ["@cloudflare/workers-types/2024-07-29"]再在项目根目录创建 env.d.ts,逐个声明绑定的类型:
interface CloudflareEnv {
MY_KV: KVNamespace;
MY_R2: R2Bucket;
MY_DO: DurableObjectNamespace;
}一次动态请求在边缘节点内部的完整处理过程如下图:

四、自定义 Worker 入口:请求前后插逻辑
如果需要在 Next.js 应用处理请求之前或之后执行自己的代码,比如拦截日志、兜底未捕获的异常、给响应补充头信息,可以创建自定义 Worker 入口:
import nextOnPagesHandler from "@cloudflare/next-on-pages/fetch-handler";
export default {
async fetch(request, env, ctx) {
// 请求前处理
console.log("收到请求:", request.url);
const response = await nextOnPagesHandler.fetch(request, env, ctx);
// 响应后处理
response.headers.set("X-Custom-Header", "value");
return response;
},
} as ExportedHandler<{ ASSETS: Fetcher }>;它看起来像一个独立 Worker,但并不需要自己的 wrangler.toml 文件,可以理解为一段用来包装构建产物的代码。写好后把入口文件路径作为参数传给 next-on-pages 命令即可。
五、_routes.json:静态资源不走 Worker
使用框架适配器时,@cloudflare/next-on-pages 会在输出目录自动生成 _routes.json,定义哪些路径属于静态资源。对这些路径,Cloudflare 不会启动 Worker,而是直接返回对应的静态文件,比如图片或客户端 JavaScript 代码块。
多数情况下你不需要手工维护这个文件。确有需要时,可以在项目根目录放一份自己的 _routes.json,构建时其中的条目会与自动生成的文件合并。例如把网站图标声明为纯静态资源:
{
"version": 1,
"exclude": ["/favicon.ico"]
}六、预览、上线与持续集成
本地验证跑 npm run preview,确认没问题后用 npm run deploy 发布。团队协作场景更推荐接入持续集成:在 Cloudflare 控制台连接 GitHub 或 GitLab 仓库,之后每次推送都会自动触发构建和部署,环境变量与绑定在控制台配置即可。
七、常见问题排查
运行时报错:优先检查是否所有服务端路由都设置了 Edge Runtime,再核对 Node.js API 的使用是否超出边缘运行时的限制。
构建失败:确认依赖版本兼容、配置文件格式正确,并检查本地 Node.js 版本是否满足要求。
绑定访问失败:核对 wrangler.toml 中的绑定声明与代码里使用的名字是否一致,确认类型声明文件没有遗漏,必要时检查权限设置。
写在最后
整套流程的关键点可以归纳为四条:选对适配器、服务端路由全部切到 Edge Runtime、按需配置绑定与自定义入口、上线前做好本地预览。跑通一次之后,后续迭代就只剩下推送代码,构建和部署全部自动完成。



