使用 Prisma ORM 和 Next.js 的综合指南
Prisma ORM 和 Next.js 形成了一个强大的组合,可用于构建现代、服务器端渲染和 API 驱动的 Web 应用。本指南整合了各种技巧和策略,以帮助你最大限度地发挥它们的潜力。无论你是在寻找最佳实践、monorepo 设置指南还是动态使用策略,我们都能满足你的需求。
¥Prisma ORM and Next.js form a powerful combination for building modern, server-side rendered, and API-driven web applications. This guide consolidates various tips and strategies to help you maximize their potential. Whether you’re looking for best practices, monorepo setup guidance, or strategies for dynamic usage, we’ve got you covered.
在开发中使用 Prisma Client 的最佳实践
¥Best practices for using Prisma Client in development
避免多个 Prisma Client 实例
¥Avoid multiple Prisma Client instances
在开发 Next.js 应用时,一个常见问题是意外创建了多个 Prisma Client 实例。这通常是由于 Next.js 在开发中的热重载功能而发生的。
¥When developing a Next.js application, one common issue is accidentally creating multiple instances of the Prisma Client. This often occurs due to Next.js’s hot-reloading feature in development.
为什么会发生这种情况
¥Why this happens
Next.js 的热重载功能会频繁重新加载模块以立即反映代码更改。但是,这可能导致创建多个 Prisma Client 实例,从而消耗资源并可能导致意外行为。
¥Next.js’s hot-reloading feature reloads modules frequently to reflect code changes instantly. However, this can lead to multiple instances of Prisma Client being created, which consumes resources and might cause unexpected behavior.
推荐解决方案
¥Recommended solution
为避免这种情况,请使用全局变量创建单个 Prisma Client 实例:
¥To avoid this, create a single Prisma Client instance by using a global variable:
// lib/prisma.ts
import { PrismaClient } from "@prisma/client";
const globalForPrisma = global as unknown as { prisma: PrismaClient };
export const prisma =
globalForPrisma.prisma || new PrismaClient();
if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma;
使用此方法可确保只有一个 Prisma Client 实例存在,即使在开发过程中进行热重载时也是如此。
¥Using this approach ensures that only one instance of Prisma Client exists, even during hot-reloading in development.
在 Monorepo 中设置 Prisma ORM
¥Setting Up Prisma ORM in a Monorepo
在 Monorepos 中使用 Prisma ORM 的挑战
¥Challenges of using Prisma ORM in monorepos
Monorepos 允许多个项目共享代码和依赖,使其成为现代开发的热门选择。但是,在 monorepo 中使用 Prisma ORM 可能会带来与依赖解析和模式管理相关的挑战。
¥Monorepos allow multiple projects to share code and dependencies, making them a popular choice for modern development. However, using Prisma ORM in a monorepo can present challenges related to dependency resolution and schema management.
关键问题
¥Key issues
-
依赖解析:如果 monorepo 中的多个包使用不同版本的 Prisma ORM,则可能会导致冲突。
¥Dependency Resolution: Multiple packages in a monorepo might lead to conflicts if they use different version of Prisma ORM.
-
模式集中化:在多个项目中管理单个 Prisma 模式可能很复杂。
¥Schema Centralization: Managing a single Prisma Schema across multiple projects can be complex.
Monorepo 集成的最佳实践
¥Best practices for monorepo integration
-
集中 Prisma 模式:将
schema.prisma
文件放在共享包(例如@myorg/db
)中,以确保一致性。¥Centralize the Prisma Schema: Place the
schema.prisma
file in a shared package, such as@myorg/db
, to ensure consistency. -
对生成的客户端使用自定义输出目录:为生成的 Prisma Client 定义一个 自定义输出目录,以保持包之间的一致性。
¥Use a custom output directory for generated client: Define a custom output directory for the generated Prisma Client to maintain consistency across packages.
-
在根目录中安装依赖:为防止版本冲突,请在 monorepo 的根目录中安装 Prisma ORM。如果单个包需要直接访问 Prisma(例如,用于本地客户端生成),也请将其安装在这些包中。你可以使用 monorepo 工具(如 Turborepo)并遵循其 最佳实践,或采用类似策略来保持依赖在你的应用中同步。
¥Install dependencies in the root: To prevent version conflicts, install Prisma ORM at the root of the monorepo. If individual packages need direct access to Prisma (e.g., for local client generation), install it within those packages as well. You can use a monorepo tool like Turborepo, following its best practices, or adopt a similar strategy to keep dependencies synchronized across your app.
-
使用 NPM 脚本进行生成:
¥Use NPM Scripts for Generation:
{
"scripts": {
"prisma:generate": "prisma generate --schema=./packages/db/schema.prisma"
}
}
此方法可让你的 Prisma Schema 和生成的客户端在 monorepo 中的所有项目中保持同步。
¥This approach keeps your Prisma Schema and generated client in sync across all projects in the monorepo.
在 Next.js 中动态使用 Prisma Client
¥Dynamic usage of Prisma Client in Next.js
处理动态场景
¥Handling dynamic scenarios
动态用例(例如使用特定于租户的数据库)在将 Prisma ORM 与 Next.js 结合使用时需要额外考虑。
¥Dynamic use cases, such as working with tenant-specific databases, require additional consideration when using Prisma ORM with Next.js.
问题
¥Problem
每个租户可能都有自己的数据库,因此需要在运行时创建单独的 Prisma 客户端。由于其混合渲染模型,这在 Next.js 中可能很复杂。
¥Each tenant might have its own database, necessitating the creation of separate Prisma Clients at runtime. This can be complex in Next.js due to its hybrid rendering model.
解决方案
¥Solution
使用工厂函数根据特定于租户的配置动态创建 Prisma Client:
¥Use a factory function to dynamically create Prisma Clients based on tenant-specific configurations:
// lib/prismaDynamic.ts
import { PrismaClient } from "@prisma/client";
type TenantConfig = {
databaseUrl: string;
};
export function createPrismaClient(config: TenantConfig): PrismaClient {
return new PrismaClient({
datasources: {
db: {
url: config.databaseUrl,
},
},
});
}
确保你管理动态创建的 Prisma 客户端的生命周期以避免资源耗尽。
¥Ensure that you manage the lifecycle of dynamically created Prisma Clients to avoid resource exhaustion.