如何在 Turborepo 中使用 Prisma ORM
Prisma 是一个用于管理数据库的强大 ORM,而 Turborepo 简化了 monorepo 工作流程。通过结合这些工具,您可以为项目创建可扩展的模块化架构。
本指南将向您展示如何在 Turborepo monorepo 中将 Prisma 设置为独立包,从而实现跨多个应用程序的高效配置、类型共享和数据库管理。
您将学习:
- 如何在 Turborepo monorepo 中设置 Prisma。
- 跨包生成和重用 PrismaClient 的步骤。
- 将 Prisma 包集成到 monorepo 中的其他应用程序。
先决条件
1. 设置项目
要设置名为 turborepo-prisma 的 Turborepo monorepo,请运行以下命令
npx create-turbo@latest turborepo-prisma
系统将提示您选择包管理器,本指南将使用 npm
- 您想使用哪个包管理器?
npm
设置完成后,为项目选择一个包管理器。导航到项目根目录并安装 Turborepo 作为开发依赖项
- npm
- yarn
- pnpm
cd turborepo-prisma
npm install turbo --save-dev
cd turborepo-prisma
yarn add turbo --dev --ignore-workspace-root-check
cd turborepo-prisma
pnpm add turbo --save-dev --ignore-workspace-root-check
有关安装 Turborepo 的更多信息,请参阅 Turborepo 官方指南。
2. 向 monorepo 添加一个新的 database 包
2.1 创建包并安装 Prisma
在 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
- yarn
- pnpm
npm install prisma @types/pg --save-dev
npm install @prisma/client @prisma/adapter-pg dotenv pg
yarn add prisma @types/pg --dev
yarn add @prisma/client @prisma/adapter-pg dotenv pg
pnpm add prisma @types/pg --save-dev
pnpm add @prisma/client @prisma/adapter-pg dotenv pg
如果你使用的是其他数据库提供程序(MySQL、SQL Server、SQLite),请安装相应的驱动程序适配器包,而不是 @prisma/adapter-pg。有关更多信息,请参阅 数据库驱动程序。
2.2. 初始化 Prisma 并定义模型
在 database 目录中,通过运行以下命令初始化 prisma
- npm
- yarn
- pnpm
npx prisma init --db --output ../generated/prisma
yarn prisma init --db --output ../generated/prisma
pnpm prisma init --db --output ../generated/prisma
这将在 packages/database 内部创建几个文件
- 一个包含
schema.prisma文件的prisma目录。 - 一个用于配置 Prisma 的
prisma.config.ts文件 - 一个 Prisma Postgres 数据库。
- 项目根目录中包含
DATABASE_URL的.env文件。 - 用于生成 Prisma Client 的
output目录,名称为generated/prisma。
在 packages/database/prisma/schema.prisma 文件中,添加以下模型
generator client {
provider = "prisma-client"
output = "../generated/prisma"
}
datasource db {
provider = "postgresql"
}
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
title String
content String?
published Boolean @default(false)
authorId Int
author User @relation(fields: [authorId], references: [id])
}
在 packages/database 目录中创建的 prisma.config.ts 文件应如下所示
import 'dotenv/config'
import { defineConfig, env } from 'prisma/config';
export default defineConfig({
schema: 'prisma/schema.prisma',
migrations: {
path: 'prisma/migrations',
},
datasource: {
url: env('DATABASE_URL'),
},
});
建议将 ../generated/prisma 添加到 .gitignore 文件中,因为它包含平台特定的二进制文件,这可能导致不同环境之间的兼容性问题。
在自定义目录中生成 Prisma 类型的重要性
在 schema.prisma 文件中,我们指定了一个自定义 output 路径,Prisma 将在该路径生成其类型。这确保了 Prisma 的类型在不同的包管理器中得到正确解析。
在本指南中,类型将生成在 database/generated/prisma 目录中。
2.3. 添加脚本并运行迁移
让我们在 packages/database 内部的 package.json 中添加一些脚本
{
"name": "@repo/db",
"version": "0.0.0",
"scripts": {
"db:generate": "prisma generate",
"db:migrate": "prisma migrate dev --skip-generate",
"db:deploy": "prisma migrate deploy"
},
"devDependencies": {
"prisma": "^6.6.0"
},
"dependencies": {
"@prisma/client": "^6.6.0"
}
}
我们还将这些脚本添加到根目录的 turbo.json 中,并确保将 DATABASE_URL 添加到环境中
{
"$schema": "https://turbo.net.cn/schema.json",
"ui": "tui",
"tasks": {
"build": {
"dependsOn": ["^build"],
"inputs": ["$TURBO_DEFAULT$", ".env*"],
"outputs": [".next/**", "!.next/cache/**"],
"env": ["DATABASE_URL"]
},
"lint": {
"dependsOn": ["^lint"]
},
"check-types": {
"dependsOn": ["^check-types"]
},
"dev": {
"cache": false,
"persistent": true
},
"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
}
}
迁移您的 prisma.schema 并生成类型
导航到项目根目录并运行以下命令以自动迁移我们的数据库
- npm
- yarn
- pnpm
npx turbo db:migrate
yarn turbo db:migrate
pnpm turbo db:migrate
生成您的 schema.prisma
要从 Prisma 模式生成类型,请从项目根目录运行
- npm
- yarn
- pnpm
npx turbo db:generate
yarn turbo db:generate
pnpm turbo db:generate
2.4. 导出 Prisma 客户端和类型
接下来,导出生成的类型和 PrismaClient 实例,以便在您的应用程序中使用。
在 packages/database 目录中,创建一个 src 文件夹并添加一个 client.ts 文件。该文件将定义 PrismaClient 的实例
import { PrismaClient } from "../generated/prisma/client";
import { PrismaPg } from '@prisma/adapter-pg';
const adapter = new PrismaPg({
connectionString: process.env.DATABASE_URL,
});
const globalForPrisma = global as unknown as { prisma: PrismaClient };
export const prisma =
globalForPrisma.prisma || new PrismaClient({
adapter,
});
if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma;
然后在 src 文件夹中创建一个 index.ts 文件,以重新导出生成的 prisma 类型和 PrismaClient 实例
export { prisma } from './client' // exports instance of prisma
export * from "../generated/prisma/client" // exports generated types from prisma
遵循 即时打包模式 并在 packages/database/package.json 内部创建包的入口点
如果您不使用打包器,请改用 已编译包 策略。
{
"name": "@repo/db",
"version": "0.0.0",
"scripts": {
"db:generate": "npx prisma generate",
"db:migrate": "npx prisma migrate dev --skip-generate",
"db:deploy": "npx prisma migrate deploy"
},
"devDependencies": {
"prisma": "^6.6.0"
},
"dependencies": {
"@prisma/client": "^6.6.0"
},
"exports": {
".": "./src/index.ts"
}
}
通过完成这些步骤,您将使 Prisma 类型和 PrismaClient 实例在整个 monorepo 中可用。
3. 在 web 应用程序中导入 database 包
turborepo-prisma 项目应该在 apps/web 处有一个名为 web 的应用程序。将 database 依赖项添加到 apps/web/package.json
- npm
- yarn
- pnpm
{
// ...
"dependencies": {
"@repo/db": "*"
// ...
}
// ...
}
{
// ...
"dependencies": {
"@repo/db": "*"
// ...
}
// ...
}
{
// ...
"dependencies": {
"@repo/db": "workspace:*"
// ...
}
// ...
}
在 apps/web 目录中运行您的包管理器的安装命令
- npm
- yarn
- pnpm
cd apps/web
npm install
cd apps/web
yarn install
cd apps/web
pnpm install
让我们从 database 包中将实例化的 prisma 客户端导入到 web 应用程序中。
在 apps/web/app 目录中,打开 page.tsx 文件并添加以下代码
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 文件,以促进模块化并避免潜在冲突。
4. 配置 Turborepo 中的任务依赖项
db:generate 和 db:deploy 脚本尚未针对 monorepo 设置进行优化,但对于 dev 和 build 任务至关重要。
如果新开发人员在未首先运行 db:generate 的情况下在应用程序上运行 turbo dev,他们将遇到错误。
为防止这种情况,请确保在运行 dev 或 build 之前始终执行 db:generate。此外,请确保在 db:build 之前执行 db:deploy 和 db:generate。以下是如何在 turbo.json 文件中配置此项
{
"$schema": "https://turbo.net.cn/schema.json",
"ui": "tui",
"tasks": {
"build": {
"dependsOn": ["^build", "^db:generate"],
"inputs": ["$TURBO_DEFAULT$", ".env*"],
"outputs": [".next/**", "!.next/cache/**"],
"env": ["DATABASE_URL"]
},
"lint": {
"dependsOn": ["^lint"]
},
"check-types": {
"dependsOn": ["^check-types"]
},
"dev": {
"dependsOn": ["^db:generate"],
"cache": false,
"persistent": true
},
"db:generate": {
"cache": false
},
"db:migrate": {
"cache": false,
"persistent": true
},
"db:deploy": {
"cache": false
}
}
}
5. 在开发环境中运行项目
在启动开发服务器之前,请注意,如果您使用的是 Next.js v15.2.0,请不要使用 Turbopack,因为存在一个已知 问题。通过更新 apps/web/package.json 从 dev 脚本中删除 Turbopack
"script":{
"dev": "next dev --port 3000",
}
然后从项目根目录运行项目
- npm
- yarn
- pnpm
npx turbo run dev --filter=web
yarn turbo run dev --filter=web
pnpm turbo run dev --filter=web
导航到 https://:3000,您应该会看到消息
No user added yet
您可以通过创建种子脚本或使用 Prisma Studio 手动将用户添加到数据库中。
要使用 Prisma Studio 通过 GUI 手动添加数据,请导航到 packages/database 目录并使用您的包管理器运行 prisma studio
- npm
- yarn
- pnpm
npx prisma studio
yarn prisma studio
pnpm prisma studio
此命令将启动一个带有 GUI 的服务器,位于 https://:5555,允许您查看和修改数据。
恭喜,您已完成 Prisma for Turborepo 的设置!
下一步
- 扩展您的 Prisma 模型以处理更复杂的数据关系。
- 实施额外的 CRUD 操作以增强您的应用程序功能。
- 查看 Prisma Postgres,了解如何扩展您的应用程序。
更多信息
与 Prisma 保持联系
通过以下方式与我们保持联系,继续你的 Prisma 之旅: 我们的活跃社区。保持信息灵通,参与其中,并与其他开发人员协作。
- 在 X 上关注我们 获取公告、直播活动和实用技巧。
- 加入我们的 Discord 提问、与社区交流,并通过对话获得积极支持。
- 在 YouTube 上订阅 获取教程、演示和直播。
- 在 GitHub 上参与 加星收藏存储库、报告问题或为问题做出贡献。