NestJS中Prisma多环境配置指南
不同环境中使用不同的配置文件,这在开发中是必不可少的,不然会一不小心就会酿成大错。
在 Prisma 的官方文档中也有关于多环境的说明,但是说得还不够仔细。在 Prisma 中因为环境的问题折腾了我好久,一度想放弃使用 Typeorm,但是 Typeorm 使用起来比 Prisma 麻烦,然后还是选择继续折腾 Prisma。
这里我就就根据经验和官方文档教大家配置多环境使用 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
安装完成后我们可以看一下 package.json
文件,可以看到里面已经添加了很多脚本:
为了获取当前环境,我们可以在 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-cli
和 dotenv
:
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
,就可以看到我们的表已经存在了。
我们试着在里面添加几条数据:
然后在 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
中返回的类型。
完美!如想了解更过 nestjs-prisma
的用法,可以查看官方文档。