Next.js15+Auth.js+Prisma在Vercel部署的Edge Runtime兼容问题
解决Vercel部署中Auth.js v5 + Prisma Adapter的Runtime不兼容问题
问题原因
Auth.js v5 默认在Edge Runtime环境下运行其认证路由和回调,但Prisma Client依赖Node.js Runtime的系统级二进制文件(查询引擎),无法在Edge环境中加载,这直接导致了你遇到的PrismaClientInitializationError——找不到对应rhel-openssl-3.0.x环境的查询引擎。
核心解决方案:强制Auth.js使用Node.js Runtime
1. 为Auth路由指定Node.js Runtime
在apps/web/app/api/auth/[...nextauth]/route.ts中添加Runtime声明:
export { GET, POST } from "@repo/authjs-core"; // 强制该路由使用Node.js Runtime export const runtime = "nodejs";
2. 调整Next.js配置适配Monorepo + Prisma
修改next.config.mjs,优化Prisma的打包处理:
import { PrismaPlugin } from "@prisma/nextjs-monorepo-workaround-plugin"; const nextConfig = { serverExternalPackages: ["@prisma/client", "prisma"], webpack: (config, { isServer }) => { if (isServer) { config.plugins = [...config.plugins, new PrismaPlugin()]; } // 避免webpack打包Prisma引擎文件 config.externals.push({ "@prisma/client": "commonjs @prisma/client", }); return config; }, // 仅转译authjs-core,Prisma相关包无需转译 transpilePackages: ["@repo/authjs-core"], }; export default nextConfig;
3. 确保Prisma引擎正确生成
在项目根目录package.json中添加构建前置命令,保证Vercel构建时生成对应环境的引擎:
{ "scripts": { "build": "prisma generate && turbo build" } }
同时在@repo/database的package.json中添加依赖安装后的自动生成:
{ "scripts": { "postinstall": "prisma generate" } }
4. 修正Prisma Client导入路径
调整@repo/database/src/index.ts的导入逻辑,直接从生成的客户端导入:
import { PrismaClient, PrismaClientOptions } from "../generated/client"; export function createPrismaClient(options?: PrismaClientOptions): PrismaClient { const clientConfig: Prisma.PrismaClientOptions = {}; if (options?.connectionString) { clientConfig.datasources = { db: { url: options.connectionString } }; } return new PrismaClient(clientConfig); } const defaultOptions: PrismaClientOptions = { connectionString: process.env.DATABASE_URL }; const prismaClientSingleton = () => createPrismaClient(defaultOptions); declare const globalThis: { prismaGlobal: ReturnType<typeof prismaClientSingleton>; } & typeof global; const prisma = globalThis.prismaGlobal ?? prismaClientSingleton(); export { prisma }; if (process.env.NODE_ENV !== "production") globalThis.prismaGlobal = prisma; export * from "../generated/client";
替代方案:分离Prisma操作到独立API路由
如果上述配置仍有问题,可将Auth.js回调中的Prisma操作移到单独的Node.js Runtime路由:
- 创建
apps/web/app/api/auth/user/route.ts:
import { prisma } from "@repo/database"; import { NextResponse } from "next/server"; export const runtime = "nodejs"; export async function GET(request: Request) { const { searchParams } = new URL(request.url); const userId = searchParams.get("id"); if (!userId) return NextResponse.json({ error: "Missing user ID" }, { status: 400 }); const user = await prisma.user.findUnique({ where: { id: userId } }); return NextResponse.json(user); }
- 在Auth.js的回调中调用该API:
async authorize(credentials) { // 替换原Prisma调用为API请求 const res = await fetch(`${process.env.NEXT_PUBLIC_APP_URL}/api/auth/user?id=${userId}`); const user = await res.json(); return user; }
额外检查项
- 确认Vercel环境变量
DATABASE_URL正确指向Supabase PostgreSQL地址 - 保持
schema.prisma中binaryTargets包含rhel-openssl-3.0.x配置 - 避免在Edge Runtime组件中直接导入
@repo/database,所有Prisma操作仅在Node.js Runtime路由/Server Components中执行
内容的提问来源于stack exchange,提问作者Michal Masar
相关产品推荐
相关产品推荐

