跳转到主要内容

如何在 Turborepo 中使用 Prisma ORM

Prisma 是一个用于管理数据库的强大 ORM,而 Turborepo 简化了 monorepo 工作流程。通过结合使用这些工具,您可以为您的项目创建可扩展的模块化架构。

本指南将向您展示如何在 Turborepo monorepo 中将 Prisma 设置为独立包,从而实现跨多个应用程序的高效配置、类型共享和数据库管理。

您将学到什么:

  • 如何在 Turborepo monorepo 中设置 Prisma。
  • 跨包生成和重用 PrismaClient 的步骤。
  • 将 Prisma 包集成到 monorepo 中的其他应用程序中。
注意

本指南已使用 Turborepo 版本 2.3.3 和 Prisma ORM 版本 6.1.0 进行了测试。

1. 使用 turborepo 创建您的 monorepo

要设置一个名为 hello-world 的 Turborepo monorepo,请运行以下命令

npx create-turbo@latest hello-world

设置完成后,为项目选择一个包管理器。导航到项目根目录,并将 Turborepo 安装为开发依赖项

cd ./hello-world
npm install turbo --save-dev

有关安装 Turborepo 的更多信息,请参阅 官方 Turborepo 指南

2. 向 hello-world monorepo 添加一个新的 database

packages 目录中创建一个 database 包。然后,通过运行以下命令为该包创建一个 package.json 文件

cd packages/
mkdir database
cd database
touch package.json

按如下方式定义 package.json 文件

{
"name": "@repo/db",
"version": "0.0.0"
}

接下来,安装使用 Prisma ORM 所需的依赖项。使用您首选的包管理器

npm install prisma --save-dev
npm install @prisma/client

3. 通过运行 prisma init 初始化 prisma

database 目录中,通过运行以下命令初始化 prisma

npx prisma init

这应该在 packages/database 中创建几个文件

  • schema.prisma 是您的 Prisma 模式所在的位置。在这里,您可以修改数据库的形状。默认情况下,prisma init 命令将创建用于 PostgreSQL 的配置。您可以修改该模式以使用 Prisma ORM 支持的任何其他受支持的数据库
  • .gitignore 将一些忽略的文件添加到 git
  • .env 允许您手动为 prisma 指定 DATABASE_URL
警告

请确保将 packages/database/.env 内的 DATABASE_URL 替换为有效的数据库 URL。

database/prisma/schema.prisma 中向您的 Prisma 模式添加一个模型

datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}

generator client {
provider = "prisma-client-js"
output = "../generated/client"
}

model User {
id Int @id @default(autoincrement())
createdAt DateTime @default(now())
email String @unique
name String?
}

自定义目录中生成 Prisma 类型的重要性

schema.prisma 文件中,我们指定了一个自定义的 output 路径,Prisma 将在此路径中生成其类型。这可确保在不同的包管理器中正确解析 Prisma 的类型。

在本指南中,这些类型将在 database/generated/client 目录中生成。

4. 创建脚本来执行 Prisma CLI 命令

让我们在 packages/database 内的 package.json 中添加一些脚本

{
"scripts": {
"db:generate": "prisma generate",
"db:migrate": "prisma migrate dev --skip-generate",
"db:deploy": "prisma migrate deploy"
}
}

让我们也将这些脚本添加到根目录中的 turbo.json

{
"tasks": {
"db:generate": {
"cache": false
},
"db:migrate": {
"cache": false,
"persistent": true // This is necessary to interact with the CLI and assign names to your database migrations.
},
"db:deploy": {
"cache": false
}
}
}

1. 迁移您的 prisma.schema 并生成类型

导航到项目根目录并运行以下命令来自动迁移我们的数据库

npx turbo db:migrate

2. 生成您的 prisma.schema

要从 Prisma 模式生成类型,请从项目根目录运行

npx turbo db:generate

5. 导出 prisma 类型和 PrismaClient 的实例以在 monorepo 中使用

接下来,导出生成的类型和 PrismaClient 的实例,以便在您的应用程序中使用。

packages/database 目录中,创建一个 src 文件夹并添加一个 client.ts 文件。此文件将定义 PrismaClient 的实例

packages/database/src/client.ts
import { PrismaClient } from "../generated/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;

然后在 src 文件夹中创建一个 index.ts 文件,以重新导出生成的 prisma 类型和 PrismaClient 实例

packages/database/src/index.ts
export { prisma } from './client' // exports instance of prisma 
export * from "../generated/client" // exports generated types from prisma

遵循 即时打包模式并在 packages/database/package.json 中创建一个包的入口点

{
"exports": {
".": "./src/index.ts"
}
}

完成这些步骤后,您将使 Prisma 类型和 PrismaClient 实例在整个 monorepo 中都可访问。

6. 将 database 包导入 monorepo 中的 web 应用程序

hello-world 项目应在 apps/web 处有一个名为 web 的应用程序。将 database 依赖项添加到 apps/web/package.json

{
"dependencies": {
"@repo/db": "*"
}
}

apps/web 目录中运行您的包管理器的安装命令

cd apps/web
npm install

让我们在 page.tsx 文件中从 database 包中导入实例化的 prisma 客户端

import styles from "./page.module.css";
import { prisma } from "@repo/db";

export default async function Home() {
const user = await prisma.user.findFirst()
return (
<div className={styles.page}>
{user?.name ?? "No user added yet"}
</div>
);
}

然后在 web 目录中创建一个 .env 文件,并复制 database 目录中包含 DATABASE_URL.env 文件的内容。

DATABASE_URL="Same database url as used in the database directory"
注意

如果您想在 Turborepo 设置中跨应用程序和包使用根目录中的单个 .env 文件,请考虑使用诸如 dotenvx 之类的包。

要实现此目的,请更新每个包或应用程序的 package.json 文件,以确保它们从共享的 .env 文件加载所需的环境变量。有关详细说明,请参阅 dotenvx Turborepo 指南

请记住,Turborepo 建议为每个包使用单独的 .env 文件,以提高模块化并避免潜在的冲突。

7. 设置依赖任务

db:generatedb:deploy 脚本尚未针对 monorepo 设置进行优化,但对于 devbuild 任务至关重要。

如果新开发人员在没有首先运行 db:generate 的情况下在应用程序上运行 turbo dev,他们将会遇到错误。

为了防止这种情况,请确保在运行 devbuild 之前始终执行 db:generate。此外,确保在 db:build 之前执行 db:deploydb:generate。以下是如何在 turbo.json 文件中配置此项的方法

{
"tasks": {
"dev": {
"dependsOn": ["^db:generate"],
"cache": false
// Additional configuration for dev tasks
},
"build": {
"dependsOn": ["^db:generate"],
// Additional configuration for build tasks
}
}
}

8. 在开发环境中运行项目

然后从项目根目录运行项目

npx turbo run dev --filter=web

导航到 https://127.0.0.1:3000,您应该会看到消息

No user added yet
注意

您可以通过创建种子脚本或使用 Prisma Studio 手动向数据库添加用户。

要使用 Prisma Studio 通过 GUI 手动添加数据,请导航到 packages/database 目录并使用您的包管理器运行 prisma studio

npx prisma studio

此命令会启动一个服务器,其 GUI 位于 https://127.0.0.1:5555,允许您查看和修改数据。

恭喜,您已完成为 Turborepo 设置 Prisma!