Nest.js 环境变量配置 
在前端项目中,经常需要使用到项目当前的环境变量。同理的在 Nest.js 中也可以使用环境变量,而且 Nest.js 已经集成了这一块的配置。 要使用环境变量的话,需要安装@nestjs/config依赖库。
pnpm i @nestjs/configpnpm i @nestjs/config现在创建一个.env的环境变量配置文件,随便写入一些信息:
DB = "mysql";
DB_HOST = "127:0:0:3060";DB = "mysql";
DB_HOST = "127:0:0:3060";然后,只需要在对应的模块中引入@nestjs/config的ConfigModule,同时注入到imports中,即可完成对环境变量功能的装载。(envFilePath 为环境变量的文件名,框架会自动去根目录查找)
// 拿user.module.ts为例
import { Module } from "@nestjs/common";
import { UserController } from "./user.controller";
import { UserService } from "./user.service";
import { ConfigModule } from "@nestjs/config";
@Module({
  controllers: [
    UserController,
    ConfigModule.forRoot({
      envFilePath: ".env",
    }),
  ],
  providers: [UserService],
})
export class UserModule {}// 拿user.module.ts为例
import { Module } from "@nestjs/common";
import { UserController } from "./user.controller";
import { UserService } from "./user.service";
import { ConfigModule } from "@nestjs/config";
@Module({
  controllers: [
    UserController,
    ConfigModule.forRoot({
      envFilePath: ".env",
    }),
  ],
  providers: [UserService],
})
export class UserModule {}获取环境变量,只需要在对应的model中的controller中引入@nestjs/config的ConfigServe即可,那么后面就可以在类中constructor初始化即可。
// user.controller.ts
import { Controller, Get, Post } from '@nestjs/common';
import { UserService } from './user.service';
import { ConfigService } from '@nestjs/config';
@Controller('user')
export class UserController {
    constructor(
        private userService: UserService,
        private configService: ConfigService,
    ) { }
    @Get()
    getUser(): any {
        console.log(this.ConfigService.get('DB'))  // log --> mysql
        return this.userService.getUser();
    }
    @Post('/add')
    addUser(): any {
        return this.userService.addUser();
    }
}// user.controller.ts
import { Controller, Get, Post } from '@nestjs/common';
import { UserService } from './user.service';
import { ConfigService } from '@nestjs/config';
@Controller('user')
export class UserController {
    constructor(
        private userService: UserService,
        private configService: ConfigService,
    ) { }
    @Get()
    getUser(): any {
        console.log(this.ConfigService.get('DB'))  // log --> mysql
        return this.userService.getUser();
    }
    @Post('/add')
    addUser(): any {
        return this.userService.addUser();
    }
}当然的,这里稍微一般来说,使用枚举会显得代码专业很多,创建一个枚举类,把环境变量的键写入到枚举中,然后改写上述的例子;
//emum/config.emum
export enum configEmum {
    DB = 'DB',
    DB_HOST = 'DB_HOST',
}//emum/config.emum
export enum configEmum {
    DB = 'DB',
    DB_HOST = 'DB_HOST',
}然后引入即可完成使用
import { configEmum } from "../emum/config.emum";
this.configService.get(configEmum.DB);import { configEmum } from "../emum/config.emum";
this.configService.get(configEmum.DB);环境变量的全局使用 
当然的,现在这个环境变量还只是局部使用,比如说有另一个叫 game 的模块,game.controller无法引入ConfigService来获取环境变量,因为它没有在game.moduel.ts引入ConfigModule进行模块注入,所以如果想要全局,我们需要在根模块(app.module.ts)中引入ConfigModule,同时ConfigModule.forRoot把里面的变量isGlobal置为true,那么这个时候环境变量将可以在任意模块中引入ConfigService进行获取。
import { Module } from "@nestjs/common";
import { UserController } from "./user/user.controller";
import { UserModule } from "./user/user.module";
import { UserService } from "./user/user.service";
import { ConfigModule } from "@nestjs/config";
@Module({
  imports: [
    UserModule,
    ConfigModule.forRoot({
      isGlobal: true,
      envFilePath: ".env",
    }),
  ],
  controllers: [UserController],
  providers: [UserService],
})
export class AppModule {}import { Module } from "@nestjs/common";
import { UserController } from "./user/user.controller";
import { UserModule } from "./user/user.module";
import { UserService } from "./user/user.service";
import { ConfigModule } from "@nestjs/config";
@Module({
  imports: [
    UserModule,
    ConfigModule.forRoot({
      isGlobal: true,
      envFilePath: ".env",
    }),
  ],
  controllers: [UserController],
  providers: [UserService],
})
export class AppModule {}根据不同的环境,使用不同的环境变量 
要想实现不同环境模式使用不同的环境变量,那必然需要在运行阶段传入特定的 key 让代码知道该用什么环境变量,这里采用cross-env库进行操作。
pnpm i cross-envpnpm i cross-env然后就可以在package.json命令中写入环境变量参数
"scripts": {
        "start:dev": "cross-env NODE_ENV=development nest build --webpack --webpackPath webpack-hmr.config.js --watch",
        "start:prod": "cross-env NODE_ENV=production node dist/main",
    },"scripts": {
        "start:dev": "cross-env NODE_ENV=development nest build --webpack --webpackPath webpack-hmr.config.js --watch",
        "start:prod": "cross-env NODE_ENV=production node dist/main",
    },ok,那么现在可以通过p来获取当前的环境,举个例子创建.env.development与.env.production
// 拿app.module.ts 举例
const envFilePath = `.env.${process.env.NODE_ENV || "development"}`;
// log  --->   根据上述配置,start:dev会log.env.development, prod 则是 .env.production
console.log(process.env. NODE_ENV);
@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
      envFilePath,
    }),
  ],
  controllers: [],
  providers: [],
})
export class AppModule {}// 拿app.module.ts 举例
const envFilePath = `.env.${process.env.NODE_ENV || "development"}`;
// log  --->   根据上述配置,start:dev会log.env.development, prod 则是 .env.production
console.log(process.env. NODE_ENV);
@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
      envFilePath,
    }),
  ],
  controllers: [],
  providers: [],
})
export class AppModule {}合并环境变量 
假设现在有好几个环境,那么不同环境中就要写不同的环境变量,但当有一些变量是每个环境中都是一样的情况该如何? Nestjs 这里集成了默认配置的设置 load(它接受一个回调函数,回调函数需要键值对),它会在原有使用的环境变量中,叠加设置的环境变量参数。如果当前的环境变量参数有叠加的环境变量参数,那么它会忽视掉叠加的环境变量参数。 这里同时引入dotenv库来解析.env文件。
// app.moduel.ts
import { Module } from "@nestjs/common";
import { ConfigModule } from "@nestjs/config";
import * as dotenv from "dotenv";
const envFilePath = `.env.${process.env.NODE_ENV || "development"}`;
@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
      envFilePath,
      load: [() => dotenv.config({ path: ".env" })], // 假设.env有DB_hrl ,其他环境变量文件没有,那么它就会叠加到当前环境变量。反之则忽略。
    }),
  ],
  controllers: [],
  providers: [],
})
export class AppModule {}// app.moduel.ts
import { Module } from "@nestjs/common";
import { ConfigModule } from "@nestjs/config";
import * as dotenv from "dotenv";
const envFilePath = `.env.${process.env.NODE_ENV || "development"}`;
@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
      envFilePath,
      load: [() => dotenv.config({ path: ".env" })], // 假设.env有DB_hrl ,其他环境变量文件没有,那么它就会叠加到当前环境变量。反之则忽略。
    }),
  ],
  controllers: [],
  providers: [],
})
export class AppModule {}测试 
搞错数据库是一个顶级大问题,日常工作中难免有概率错改环境配置文件里面的参数,为了防止这种这种 Nest 支持在传进环境变量中校验环境变量是否正常,官方这里推荐是使用joi库来操作。
pnpm i joipnpm i joi然后还是找到ConfigModule.forRoot,这里其中有validationSchema属性,举个例子,用最上述的.env文件为例子,项目所使用的环境变量必须是mysql或者mongodb,那么就可以这样设置:
// app.momdule.ts
@Module({
    imports: [
        UserModule,
        ConfigModule.forRoot({
            isGlobal: true,
            envFilePath,
            load: [() => dotenv.config({ path: '.env' })],
            validationSchema: joi.object({
                DB: joi.string().valid('mysql', 'mongodb').default('mysql'),
            }),
        }),
    ],
    controllers: [UserController],
    providers: [UserService],
})// app.momdule.ts
@Module({
    imports: [
        UserModule,
        ConfigModule.forRoot({
            isGlobal: true,
            envFilePath,
            load: [() => dotenv.config({ path: '.env' })],
            validationSchema: joi.object({
                DB: joi.string().valid('mysql', 'mongodb').default('mysql'),
            }),
        }),
    ],
    controllers: [UserController],
    providers: [UserService],
})上述例子断言了环境参数 DB 必须是字符串,且是mysql或者mongodb ,默认是mysql, 当然 joi 也有很多判断方式,比如joi.number等等,这需要查阅 joi 的官方文档。
 zerone
zerone