跳至主要内容

使用 Next.js 实例化 Prisma Client 的最佳实践

提示

如果你想学习如何使用 Next.js 和 Prisma ORM 构建应用程序,请查看此全面的视频教程.

问题

许多用户在使用 Next.js 开发时遇到了此警告

warn(prisma-client) There are already 10 instances of Prisma Client actively running.

有一个相关的讨论问题都提到了类似问题。

在开发环境中,命令 next dev 会在运行时清除 Node.js 缓存。这反过来又会由于热重载导致每次都初始化一个新的 PrismaClient 实例,从而创建一个与数据库的连接。由于每个 PrismaClient 实例都拥有自己的连接池,这会导致数据库连接很快耗尽。

解决方案

在这种情况下,解决方案是实例化一个 PrismaClient 实例并将其保存在globalThis 对象上。然后,我们进行检查,仅在 globalThis 对象上不存在 PrismaClient 时才实例化 PrismaClient,否则如果 PrismaClient 实例已存在,则使用相同的实例来防止实例化额外的 PrismaClient 实例。

db.ts
import { PrismaClient } from '@prisma/client'

const prismaClientSingleton = () => {
return new PrismaClient()
}

declare const globalThis: {
prismaGlobal: ReturnType<typeof prismaClientSingleton>;
} & typeof global;

const prisma = globalThis.prismaGlobal ?? prismaClientSingleton()

export default prisma

if (process.env.NODE_ENV !== 'production') globalThis.prismaGlobal = prisma

你可以通过在实例化 Prisma Client 时附加 $extends 客户端方法来使用 Prisma Client 扩展来扩展 Prisma Client,如下所示

import { PrismaClient } from '@prisma/client'

const prismaClientSingleton = () => {
return new PrismaClient().$extends({
result: {
user: {
fullName: {
needs: { firstName: true, lastName: true },
compute(user) {
return `${user.firstName} ${user.lastName}`
},
},
},
},
})
}

创建此文件后,你可以在 Next.js pages 中的任何地方导入扩展的 PrismaClient 实例,如下所示

// e.g. in `pages/index.tsx`
import prisma from './db'

export const getServerSideProps = async () => {
const posts = await prisma.post.findMany()

return { props: { posts } }
}