故障排除
尝试部署到 Cloudflare Pages 而非 Cloudflare Workers?
@opennextjs/cloudflare
是专门为将 Next.js 应用部署到 Cloudflare Workers (opens in a new tab) 而构建的。
Cloudflare Workers 现已支持 Cloudflare Pages 的大部分功能,并且具备一些 Cloudflare Pages 尚未支持的特性。请参阅 Cloudflare Workers 文档中的 兼容性矩阵 (opens in a new tab)。
如需部署到 Cloudflare Pages,可以使用 @cloudflare/next-on-pages
,并按照 Cloudflare Pages 部署 Next.js 应用指南 (opens in a new tab) 操作。
"您的 Worker 超过了 3 MiB 的大小限制"
您正在部署的 Cloudflare 账户使用的是 Workers 免费计划,该计划 将每个 Worker 的大小限制为 3 MiB (opens in a new tab)。升级到 Workers 付费计划后,每个 Worker 的大小上限将提升至 10 MiB。
部署 Worker 时,wrangler
会显示原始大小和压缩后大小。只有后者(gzip 压缩后大小)会影响这些限制。
"您的 Worker 超过了 10 MiB 的大小限制"
如果您的 Worker 压缩后超过 10 MiB —— 可能是生产包中包含了不必要的代码。您可以通过以下方式可视化和分析:
- 在项目根目录运行
npx opennextjs-cloudflare build
- 进入
.open-next/server-functions/default
目录 - 获取名为
handler.mjs.meta.json
的文件,使用 ESBuild 包分析器 (opens in a new tab) 可视化应用代码,了解生产包中最大的组成部分
应用在导入特定 NPM 包时构建失败
首先,请确保在你的 wrangler 配置文件 (opens in a new tab)中启用了 nodejs_compat
兼容性标志,并且将兼容日期设置为 "2024-09-23" 或之后。有关 Cloudflare Workers 中 Node.js 支持的更多详情,请参考 Node.js Workers 文档 (opens in a new tab)。
某些 NPM 包定义了多个导出项。例如:
"exports": {
"other": "./src/other.js",
"node": "./src/node.js",
"browser": "./src/browser.js",
"default": "./src/default.js"
},
当你使用 @opennextjs/cloudflare
时,Wrangler (opens in a new tab) 会在本地运行或部署到 Cloudflare 之前打包你的代码。Wrangler 在导入模块时需要选择使用哪个导出项。默认情况下,使用 esbuild (opens in a new tab) 的 Wrangler 处理方式可能与某些 NPM 包不兼容。
你可能需要修改 Wrangler 解析多个导出项的方式,以便在导入包时优先使用 node
导出项(如果存在)。可以通过在 Next.js 应用的根目录下的 .env
文件中定义以下变量来实现:
WRANGLER_BUILD_CONDITIONS=""
WRANGLER_BUILD_PLATFORM="node"
Error: Cannot perform I/O on behalf of a different request.
(错误:无法代表不同请求执行 I/O 操作)
某些数据库客户端(如 postgres
(opens in a new tab))在首次实例化时会创建到数据库服务器的连接,并在后续请求中复用该连接。这种编程模型与 Workers 运行时环境不兼容,因为在 Workers 中连接不能在不同请求间复用。
这种情况下会产生以下错误:
⨯ Error: Cannot perform I/O on behalf of a different request. I/O objects (such as streams, request/response bodies, and others) created in the context of one request handler cannot be accessed from a different request's handler. This is a limitation of Cloudflare Workers which allows us to improve overall performance. (I/O type: Writable)
要解决这个问题,你应该在请求上下文中创建数据库客户端,而不是维护一个全局的数据库客户端。
全局客户端将无法工作:
// src/lib/db.ts
import postgres from "postgres";
// `client` 是全局的
// 由于连接会在请求间共享,在 worker 中会失败
export const client = postgres(process.env.DATABASE_URL, { max: 5 });
// src/app/api/route.ts
import { client } from "@/db/db";
export const dynamic = "force-dynamic";
export async function GET() {
return new Response(JSON.stringify(await client`SELECT * FROM users;`));
}
可以通过为每个传入请求创建客户端来修复:
// src/app/api/route.ts
export const dynamic = "force-dynamic";
export async function GET() {
// 为每个传入请求创建客户端,连接不会在请求间共享
const client = postgres(process.env.DATABASE_URL, { max: 5 });
return new Response(JSON.stringify(await client`SELECT * FROM users;`));
}
错误:无法加载 chunk server/chunks/ssr/<chunk_name>.js
如果出现类似以下错误:
✘ [ERROR] ⨯ Error: Failed to load chunk server/chunks/ssr/<chunk_name>.js
at loadChunkPath
(...)
at Object.loadChunk
(...)
at .open-next/server-functions/default/.next/server/app/page.js
这可能是由于您使用了 turbopack 构建 (next build --turbo
),而 OpenNext 目前不支持该功能。
将构建命令改为 next build
即可解决此问题。
X [ERROR] 无法解析 "<package>"
在构建过程中出现以下错误时:
⚙️ 正在打包 OpenNext 服务器...
X [ERROR] Could not resolve "<package name>"
可能是因为该包包含 workerd 特定的代码。
请参阅此解决方案来解决问题。