NestJS中Prisma多环境配置指南

不同环境中使用不同的配置文件,这在开发中是必不可少的,不然会一不小心就会酿成大错。

在 Prisma 的官方文档中也有关于多环境的说明,但是说得还不够仔细。在 Prisma 中因为环境的问题折腾了我好久,一度想放弃使用 Typeorm,但是 Typeorm 使用起来比 Prisma 麻烦,然后还是选择继续折腾 Prisma。

image

这里我就就根据经验和官方文档教大家配置多环境使用 Prisma。

首先我们有两个或多个环境配置文件。我这里只有 .env.dev.env.prod 两个。

这两个不同的文件中使用了不同的数据库地址,例如我的配置如下:

# .env.dev
DATABASE_URL="mysql://root:0000@localhost:3306/prisma_dev"

# .env.prod
DATABASE_URL="mysql://root:0000@localhost:3306/prisma_prod"

做完以上步骤后,我们需要让程序根据不同的环境加载不同的数据库地址。

这次我们不直接安装 Prisma,而直接使用为 NestJS 量身打造的 nestjs-prisma 插件。

使用命令自动安装:

nest add nestjs-prisma

image

安装完成后我们可以看一下 package.json 文件,可以看到里面已经添加了很多脚本:

image

为了获取当前环境,我们可以在 main.ts 中打印一下:

console.log(process.env.NODE_ENV);

可以在终端中看到,得到的是 underfined。所有我们要设置一下,当我们运行 npm run start 的命令时是开发环境。

更改 package.json 中的一下脚本:

{
    ...
    "script": {
        ...
        "start": "set NODE_ENV=dev&& nest start",
    	"start:dev": "set NODE_ENV=dev&& nest start --watch",
    	"start:debug": "set NODE_ENV=dev&& nest start --debug --watch",
        ...
    }
}

这里没有写错,&& 前面没有空格。如果加了空格,最终获得的环境末尾也有一个空格,会造成一下画面:

process.env.NODE_ENV === 'dev' // false 

我们重新运行启动命令,这时就可以获得当前的 NODE_ENV 的值为 dev

为了配置环境,我们需要使用 config 模块。使用以下命令安装:

npm i --save @nestjs/config

安装好后我们在 app.module.ts 中配置:

import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { AppController } from './app.controller';
import { AppService } from './app.service';

@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
      envFilePath: process.env.NODE_ENV === 'dev' ? '.env.dev' : '.env.prod',
    }),
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

我们打开 schema.prisma 文件,向里面添加一个 mdel:

generator client {
  provider = "prisma-client-js"
}

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

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

然后执行 npm run prisma:generate 。因为我们安装了 nestjs-prisma,它自动帮我们配置好了脚本,并且我们也不需要自己手动创建 Prisma 的 module 和 service 文件。

app.module.ts 中引入 PrismaModule 并配置。

...
import { PrismaModule } from 'nestjs-prisma';

@Module({
  imports: [
    ...,
    PrismaModule.forRootAsync({
      isGlobal: true,
      useFactory: async (configService: ConfigService) => {
        // 查看是否符合预期
        console.log(configService.get('DATABASE_URL'));
        return {
          prismaOptions: {
            datasources: {
              db: {
                url: configService.get('DATABASE_URL'),
              },
            },
          },
          explicitConnect: false,
        };
      },
      inject: [ConfigService],
    }),
  ],
  ...
})
export class AppModule {}

我们运行 npm run migrate:dev,让我们写的 model 能同步到数据库中。执行一下后会发现报错了:

Error: Prisma schema validation - (get-config wasm) 
Error code: P1012
error: Environment variable not found: DATABASE_URL.
  -->  schema.prisma:10
   | 
 9 |   provider = "mysql"
10 |   url      = env("DATABASE_URL")
   | 

Validation Error Count: 1

当然,以上的配置只有你知我知 Nest 知,但是 Prisma 不知,如果这时我们执行 Prisma 命令就会出错。为了让 Prisma 也知道该用哪个文件,我们需要在 package.json 中自主配置一下脚本。

首先安装第三方库 dotenv-clidotenv

npm install -g dotenv-cli

然后更改一下以下脚本:

{
  ...,
  "script": {
    ...,
    "migrate:dev": "npx dotenv -e .env.dev -- prisma migrate dev",
    "prisma:studio": "npx dotenv -e .env.dev -- prisma studio"
  }
}

重新执行一下就 OK 了。我们再执行 npm run prisma:studio ,就可以看到我们的表已经存在了。

我们试着在里面添加几条数据:

image

然后在 app.service.ts 中查询一下:

import { Injectable } from '@nestjs/common';
import { PrismaService } from 'nestjs-prisma/dist/prisma.service';

@Injectable()
export class AppService {
  constructor(private readonly prisma: PrismaService) {}

  getHello() {
    return this.prisma.user.findMany();
  }
}

记得更改一下 app.controller.ts 中返回的类型。

image

完美!如想了解更过 nestjs-prisma 的用法,可以查看官方文档

posted @ 2023-03-17 10:19  菠萝橙子丶  阅读(1016)  评论(0编辑  收藏  举报