如何將 Prisma ORM 與 Turborepo 搭配使用
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檔案。 - 一個名為
generated/prisma的目錄,用於存放產生的 Prisma Client。
在 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.build/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 schema 產生型別,請在專案根目錄執行
- 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
遵循 及時打包 (Just-in-Time packaging) 模式,並在 packages/database/package.json 中建立套件進入點
如果您沒有使用打包工具 (bundler),請改用 編譯套件 (Compiled Packages) 策略。
{
"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"
}
}
完成這些步驟後,您就可以在整個 Monorepo 中存取 Prisma 型別與 PrismaClient 實例。
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
讓我們在 web 應用程式中匯入 database 套件中已實例化的 prisma 客戶端。
在 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 檔案載入所需的環境變數。詳細說明請參考 Turborepo 的 dotenvx 指南。
請記住,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.build/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
您可以透過建立種子腳本 (seed script) 或使用 Prisma Studio 手動將使用者新增至您的資料庫。
若要使用 Prisma Studio 透過圖形介面 (GUI) 手動新增資料,請導航至 packages/database 目錄,並使用您的套件管理器執行 prisma studio
- npm
- yarn
- pnpm
npx prisma studio
yarn prisma studio
pnpm prisma studio
此指令會啟動一個帶有 GUI 的伺服器,網址為 https://:5555,讓您可以查看並修改資料。
恭喜,您已經完成為 Turborepo 設定 Prisma 的工作!
後續步驟
- 擴展您的 Prisma 模型以處理更複雜的資料關係。
- 實作額外的 CRUD 操作以增強應用程式的功能。
- 查看 Prisma Postgres 以了解如何擴展您的應用程式。
更多資訊
與 Prisma 保持聯繫
透過以下方式與我們聯繫,繼續您的 Prisma 旅程: 我們的活躍社群。保持資訊靈通、參與其中,並與其他開發者合作
- 在 X 上關注我們 以獲取公告、現場活動和實用技巧。
- 加入我們的 Discord 提出問題、與社群對話,並透過對話獲得積極支援。
- 在 YouTube 上訂閱 查看教學、演示和直播。
- 在 GitHub 上交流 透過為存放庫加星標、報告問題或為 issue 做出貢獻。