最近部署在 Vercel 的项目被多个 AI 爬虫攻击后,超过了免费用量帐号直接被暂停了,等了几周也没有恢复,所以打算迁移到 Cloudflare Pages。此前听过说过 Vercel 的流量费用非常贵,但是没想到还有超量就暂停帐号的手段,除了升级订阅服务没有任何办法。总之,有相似问题的小伙伴可以参考这篇博客进行迁移。
前言
首先,要将原本运行在 Vercel 和 Cloudflare Pages 的项目运行环境是不一样的。
| 部署方式 | 运行时 | 说明 |
|---|---|---|
| Vercel | Node.js Runtime | 默认运行时,它具有访问所有 Node.js API 的权限,并用于渲染您的应用。 |
| Cloudflare Pages | Edge Runtime | 只包含有限 API 的中间件运行时,不支持所有 Node.js API,不支持增量静态再生 (ISR)。 |
因为 Cloudflare Pages 使用的是 Edge Runtime,所以一些有关 Node.js 的依赖库不会正常工作,例如 path、fs 等文件读写这些。如果项目中有用了 Edge Runtime 不支持的数据操作,那最好改成 fetch 去获取数据。
安装构建依赖
Cloudflare Pages 提供了一个 @cloudflare/next-on-pages 依赖库,可以把 Next.js 项目编译为 Pages 兼容的编译文件。
npm install -D @cloudflare/next-on-pages
yarn add -D @cloudflare/next-on-pages
pnpm install -D @cloudflare/next-on-pages然后,我们需要在 package.json 中补充三条 script
"scripts": {
"pages:build": "npx @cloudflare/next-on-pages",
"preview": "npm run pages:build && wrangler pages dev",
"deploy": "npm run pages:build && wrangler pages deploy"
}添加配置支持
同时,我们还需要在 next.config.ts 中额外添加配置,用于构建时初始化 @cloudflare/next-on-pages
import { setupDevPlatform } from '@cloudflare/next-on-pages/next-dev'
// Export an async default function that returns the NextConfig.
// Next supports the config being a Promise, so we can run async
// setup here without using top-level await or an IIFE.
export default async function (): Promise<NextConfig> {
if (process.env.NODE_ENV === 'development') {
await setupDevPlatform()
}
return nextConfig
}Nodejs 兼容标识和指定构建路径
除此之外,还需要在项目的根目录中添加一个 wrangler.toml 文件,用于指定构建后的路径和配置。
name = "PROJECT_NAME"
compatibility_date = "2025-10-04"
compatibility_flags = ["nodejs_compat"]
pages_build_output_dir = ".vercel/output/static"这里可以直接复制配置,然后更改 name 为项目名字和 compatibility_date 为最新日期就好了。
运行时声明
为了让 Next.js 运行在 Edge Runtime,需要在所有的服务端界面("use server")和 API 的顶层进行显式的 runtime 声明。大部分情况下,只需要在 app/layout.tsx 和 app/api/*.ts 文件的顶部添加一行声明就好了。
export const runtime = 'edge'添加 NotFound 界面
通过 @cloudflare/next-on-pages 依赖构建后会在文件中默认生成一个 _not-found 界面,但是这个界面也是运行在服务端的,如果在项目中没有声明 runtime,那么就会在部署时报错。
所以,我们需要在项目中添加 app/not-found.tsx 文件
import { Button } from '@/components/ui/button'
import Link from 'next/link'
export const runtime = 'edge'
export default function NotFound() {
return (
<div className="flex min-h-70 flex-col items-center justify-center">
<h1 className="mt-4 text-4xl font-bold tracking-tight text-zinc-800 sm:text-5xl dark:text-zinc-100">
Page not found
</h1>
<p className="mt-4 text-base text-zinc-600 dark:text-zinc-400">
Sorry, we couldn’t find the page you’re looking for.
</p>
<Link href="/" className="mt-4 cursor-pointer">
<Button variant="secondary" className="cursor-pointer">
Go back home
</Button>
</Link>
</div>
)
}部署到 Cloudflare Pages
然后,我们在 Cloudflare Pages 导入现有 Git 存储库

然后选择要部署的 Github 存储库

选择框架预设为 Next.js,默认配置保持不变,然后点击保存并部署

如果有缺少的界面没有配置 runtime,在部署的日志都会显示出来,我们只需要根据错误再次调整就好了

部署成功后就是下面的显示的日志输出,我们就可以访问网站了

结语
至此,我们就完成了部署,不过这种方法只适合现有的 Next.js 项目进行迁移。现在 Cloudflare 的 @cloudflare/next-on-pages 依赖仓库已经被归档了,官方更推荐使用 Open Next 通过 CLI 的方式进行构建和部署。