Nest环境变量配置,手把手教学

293 阅读3分钟

这个配置十分重要!!!比如像密码等私密全局变量不能硬编码放在代码当中,需要使用单独的.env文件进行存储。这个多环境配置就是实现了.env文件的变量读取,并且可以配置自己用的是dev或prod环境下的变量!!!

有两种多环境配置方案:dotenvconfig配置,这里使用的是官方方案config配置

  1. 先下载config这个模块:

      
      pnpm i --save @nestjs/config@2
    

然后在package里面查看是否安装成功:

配置查看.png

2、根目录创建一个.env文件测试

  
  DB=mysql
  DB_HOST=127.0.0.1

3、全局模块导入config

  //app.moudule.ts
  //isClobal属性运行configModule可以其他模块引入使用import { Module } from '@nestjs/common';
  import { UserModule } from './user/user.module';
  import { ConfigModule } from '@nestjs/config';
  ​
  @Module({
    imports: [ConfigModule.forRoot({isGlobal:true}),UserModule],
    controllers: [],
    providers: []
  })
  export class AppModule {}
  ​

4、接下来我们在user模块进行测试

  //user.controller.tsimport { Controller, Get, Post} from '@nestjs/common';
  import { UserService } from './user.service';
  import { ConfigService } from '@nestjs/config';
  import { ConfigEnum } from '../enum/config.enum';
  ​
  @Controller('user')
  export class UserController {
  ​
    constructor(
      private readonly useService: UserService,
      private readonly ConfigService: ConfigService
    ) {}
    @Get('test')
    getUsers(): any {
      const db = this.ConfigService.get(ConfigEnum.DB)
      const host_db = this.ConfigService.get(ConfigEnum.DB_HOST)
      console.log(db);
      console.log(host_db);
      
      return this.useService.getUsers();
    }
  ​
    @Post() 
    postUsers(): any {
      return this.useService.postUsers();
    }
  ​
    @Get('range')
    postNum(): any {
      return this.useService.postNum();
    }
  }
  ​

启动服务,在浏览器运行localhost:3000/user/test可以实现DBHOST_DB的打印(这种形式,我是现在 配置完成开发和生产环境的打印)

1748920078294.png

!!!这里可以注意到我的代码是使用的enum中的值实现的,使用的ts中的枚举,这样更加规范,操作如下:

1748920262985.png

  
  //config.enum.ts
  ​
  export enum ConfigEnum {
    DB = 'DB',
    DB_HOST = 'DB_HOST',
  }

这样就实现了配置最基本的config用法,但是在实际开发中有生产和开发两个环境,可能对应着不同的.env全局变量,那么该如何进行配置 呢?接着往下看.....

5、由于config模块中的特性,可以指定启动的.env文件---使用envFilePath指定文件,接下来创建一个 .env.deve* *lopment**文件,文件内容:

  
  //.env.development
  ​
  DB=mysql-dev
  DB_HOST=127.0.0.1

在app.module里面新增envFilePath属性指定路径:

  //app.module.ts
  //isClobal属性运行configModule可以其他模块引入使用
  //
  ​
  import { Module } from '@nestjs/common';
  import { UserModule } from './user/user.module';
  import { ConfigModule } from '@nestjs/config';
  ​
  @Module({
    imports: [ConfigModule.forRoot({
          isGlobal:true,
          envFilePath:".env.development"
    }),UserModule],
    controllers: [],
    providers: []
  })
  export class AppModule {}
  ​

再次运行可以得到 .env.development中的变量。

同理再配置 .env.production文件并读取:

  
  DB=mysql-prod
  DB_HOST=127.0.0.1

6、现在我们去package文件当中进行配置script命令:

需要下载

  
  pnpm i -D cross-env
  
  "scripts": {
      "build": "nest build",
      "format": "prettier --write "src/**/*.ts" "test/**/*.ts"",
      "start": "nest start",
      "start:dev": "cross-env NODE_ENV=development nest build --webpack --webpackPath webpack-hmr.config.js --watch",
      "start:debug": "nest start --debug --watch",
      "start:prod": "cross-env NODE_ENV=production node dist/main ",
      "lint": "eslint "{src,apps,libs,test}/**/*.ts" --fix",
      "test": "jest",
      "test:watch": "jest --watch",
      "test:cov": "jest --coverage",
      "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
      "test:e2e": "jest --config ./test/jest-e2e.json"
    },

这里需要注意命令中各个部分的顺序!!!

继续将env路径变量改写替换:

  
  envFilePath:`.env.${process.env.NODE_ENV ||'development'}`

现在执行不同的指令就可以实现读取不同的.env啦

7、开发和生产环境肯定有共享的模块,总不能都分开重复吧?嘿嘿,这里可以使用.env共享变量,如果各自模块更新将会替换掉共享变量。使用的是load方法

首先下载dotenv

  
  pnpm i dotenv

再配置app.module可以实现共享

  
  import { Module } from '@nestjs/common';
  import { UserModule } from './user/user.module';
  import { ConfigModule } from '@nestjs/config';
  import *as dotenv from 'dotenv';
  ​
  @Module({
    imports: [ConfigModule.forRoot({
      isGlobal:true,
      envFilePath:`.env.${process.env.NODE_ENV || 'development'}`,
      load:[() => dotenv.config({path:'.env'})]
      
    }),UserModule],
    controllers: [],
    providers: []
  })
  export class AppModule {}
  ​

8、如果用户传递的变量不符合.env中的变量要求,接下来我们就需要这些配置来进行校验(joi库):

安装joi库:

  pnpm install --save joi

可以设置范围等等,参考JOI官网:

  //app.module.ts
  ​
  import { Module } from '@nestjs/common';
  import { UserModule } from './user/user.module';
  import { ConfigModule } from '@nestjs/config';
  import *as dotenv from 'dotenv';
  import *as Joi from 'joi';
  ​
  @Module({
    imports: [ConfigModule.forRoot({
      isGlobal:true,
      envFilePath:`.env.${process.env.NODE_ENV || 'development'}`,
      load:[() => dotenv.config({path:'.env'})],
      validationSchema: Joi.object({
        DB_PORT: Joi.number().default(3306),
      })
    }),UserModule],
    controllers: [],
    providers: []
  })
  export class AppModule {}
  ​