Repo
Docs
工具
Prisma

在 Turborepo 中使用 Prisma

Prisma (opens in a new tab) 是一个非常流行的 ORM,具有自动迁移、类型安全和集成工具。在 Turborepo 中使用它可以减少您花费在生成代码上的时间,并轻松确保您的生成的 Prisma 代码始终是最新的。

指南

本指南向您展示如何

  1. 在 monorepo 中设置 Prisma
  2. 处理迁移和代码生成脚本
  3. 使用 Turborepo 缓存这些脚本
  4. 确保它们始终在 devbuild 运行时运行

如果您已经在数据库中设置了 Prisma,您可以跳到 步骤 4

1. 创建您的 monorepo

如果您没有现有项目,请使用我们的 快速入门 创建一个新的 monorepo。

2. 添加一个新的 database

在 packages 中创建一个名为 database 的新文件夹,并在其中包含一个 package.json

{
  "name": "database",
  "version": "0.0.0",
  "dependencies": {
    "@prisma/client": "latest"
  },
  "devDependencies": {
    // Replace "latest" with the latest version
    "prisma": "latest"
  }
}

如果您使用的是 pnpm,您应该在根目录添加一个名为 .npmrc 的文件

public-hoist-pattern[]=*prisma*

运行您的包管理器的安装步骤以安装新的依赖项。

3. 运行 prisma init

cdpackages/database

cd packages/database

运行 npx prisma init

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

prisma/schema.prisma
.gitignore
.env
  • schema.prisma 是您的 Prisma 模式 (opens in a new tab) 所在的位置。在这里,您可以修改数据库的形状。
  • .gitignore 将一些忽略的文件添加到 git
  • .env 允许您手动指定您的 DATABASE_URL 用于 prisma。

此时,您应该参考 Prisma 文档以了解 将您的数据库连接到 Prisma (opens in a new tab)

连接数据库后,您可以继续。

4. 设置脚本

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

{
  "scripts": {
    "db:generate": "prisma generate",
    "db:push": "prisma db push --skip-generate"
  }
}

我们也需要在根目录的 turbo.json 中添加这些脚本。

{
  "pipeline": {
    "db:generate": {
      "cache": false
    },
    "db:push": {
      "cache": false
    }
  }
}

现在,我们可以从仓库根目录运行 turbo db:push db:generate,自动迁移数据库并生成类型安全的 Prisma 客户端。

我们在 db:push 上使用 --skip-generate 标志,以确保它在迁移数据库后不会自动运行 prisma generate。当使用 Turborepo 时,这最终会更快,因为我们自动并行化了任务。

5. 导出您的客户端

接下来,我们需要导出 @prisma/client,以便我们可以在应用程序中使用它。让我们在 packages/database 中添加一个 index.ts 文件。

export * from '@prisma/client';

遵循 内部包模式,我们还需要在 packages/database/package.json 内部的 maintypes 中添加 index.ts

{
  "main": "./index.ts",
  "types": "./index.ts"
}

导入 database

现在让我们将数据库包导入到我们的一个应用程序中进行测试。假设您在 apps/web 中有一个应用程序。将依赖项添加到 apps/web/package.json

{
  "dependencies": {
    "database": "*"
  }
}

运行您的包管理器的安装命令。

现在,您可以在应用程序中的任何位置从 database 导入 PrismaClient

import { PrismaClient } from 'database'
 
const client = new PrismaClient();

您可能还需要在应用程序中进行一些配置,以允许它运行内部包。查看我们的 内部包文档 以获取更多信息。

6. 弄清楚脚本

现在我们处于一个相当不错的位置。我们有一个可重用的 database 模块,我们可以将其导入到任何应用程序中。我们有一个 turbo db:push 脚本,我们可以用来将更改推送到数据库。

但是,我们的 db:generate 脚本还没有优化。它们为我们的 devbuild 任务提供了重要的代码。如果新开发人员在没有先运行 db:generate 的情况下,在应用程序上运行 dev,他们会遇到错误。

因此,让我们确保在用户运行 dev 之前,始终运行 db:generate

{
  "pipeline": {
    "dev": {
      "dependsOn": ["^db:generate"],
      "cache": false
    },
    "build": {
      "dependsOn": ["^db:generate"],
      "outputs": ["your-outputs-here"]
    },
    "db:generate": {
      "cache": false
    }
  }
}

查看有关 运行任务 的部分,以了解有关 ^db:generate 语法的更多信息。

7. 缓存 prisma generate 的结果

prisma generate 将文件输出到文件系统,通常在 node_modules 内。理论上,应该可以使用 Turborepo 缓存 prisma generate 的输出,以节省几秒钟。

但是,Prisma 在不同的包管理器中表现不同。这会导致不可预测的结果,这可能会导致某些情况下部署失败。我们建议不要缓存 prisma generate 的结果,而不是记录每种方法的复杂性。由于 prisma generate 通常只需要 5-6 秒,并且在较大的 schema 文件中也不会花费更长时间,这似乎是一个不错的权衡。

您可能希望自己尝试一下。如果您发现一个您认为有效的解决方案,请随时 添加一个问题 (在新标签页中打开),我们可以更新此部分。

  1. 进入生产环境

现在您已经走到了这一步,您已准备好部署您的应用程序。根据您的数据库所在位置,您需要根据数据库设置的文档设计您的部署管道。从这一点开始,需要考虑很多因素,因此我们无法提供一个万能的解决方案。您可能需要访问数据库及其部署平台的文档以了解更多信息。