(三)NestJS 使用自定义配置文件

上一篇文章介绍了环境变量的使用,很多需要保密的信息或者根据运行环境有所变化的信息应该都可以放在里面。项目不大或者配置不是很多用上面的方式进行配置就够用了。但如果环境变量很多,需要有层级关系,需要二次加工时使用ConfigService效率更高。

NestJs 的文档关于自定义配置文件,写的非常详细。写这篇文章的时候,我自觉有点多余。但想到写这个专栏的目的是为让帮助不熟悉NestJS的朋友可以按专栏提供的方法迅速上手,所以还是简单当作复述一下。

1 启用自定义配置文件

跟启用环境的环境变量配置类似,开起ConfigService 配置的方式同样是在app.module中引入时,添加配置文件的属性。

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { ConfigModule } from '@nestjs/config';
import { UsersModule } from './users/users.module';
import AppConfig from './configs/appConfigs'; // 自定义的配置文件
@Module({
 imports: [
   ConfigModule.forRoot({
     envFilePath: '.env',
     load: [AppConfig], // 启用自定义的配置文件
  }),
   UsersModule,
],
 controllers: [AppController],
 providers: [AppService],
})
export class AppModule {}

同时添加自定义配置文件,这里我在src目录下创建了configs文件夹以及appConfigs文件,appConfigs默认返回一个函数

export default () => {
 return {
   port: parseInt(process.env.APP_PORT, 10),
   db: {
     host: process.env.DATABASE_HOST,
     port: process.env.DATABASE_PORT,
  },
};
};

2 引用自定义配置

2.1 在功能模块中引用

自定义配置文件加载完成后,所有配置都会被加载在ConfigModule中,在功能模块中引用自定义配置也很简单,分两个步骤引入

  • 在功能模块下 module 文件中引入 ConfigModule
  • 在功能模块下Controller或Service文件中引入ConfigService
  • 下面以Users模块为例,在Users中使用ConfigService,创建Users模块很简单,这里为了目录更清晰没有生产测试文件,运行下面的命令,目录会自定生产

    // 创建 users module
    nest g mo users --no-spect
    // 创建 users controller
    nest g co users  --no-spect

    image-20230815213743097.png

    接着在 users.module.ts 文件中引入 ConfigModule

    import { Module } from '@nestjs/common';
    import { UsersController } from './users.controller';
    import { ConfigModule } from '@nestjs/config'; // 引入ConfigModule
    @Module({
     imports: [ConfigModule], // 引入ConfigModule
     controllers: [UsersController],
    })
    export class UsersModule {}

    接着在 users.controller.ts 文件中引入 ConfigService, Service文件中引入的方式完全一致。

    import { Controller, Get } from '@nestjs/common';
    import { ConfigService } from '@nestjs/config';
    @Controller('users')
    export class UsersController {
     constructor(private readonly configService: ConfigService) {}
     @Get('/')
     getUsers() {
       console.log(process.env.APP_PORT);
       console.log(this.configService.get('port'));
       return [];
    }
    }

    这里示例中展示了从Node环境变量中获取配置和ConfigService中使用的方式,ConfigService需要使用get方法获取对应的配置属性同时也可以穿入对应的类型。 这里参数APP_PORT在AppConfigs文件中转换为了int数字,打印变量时可以看出区别

    image-20230815215111748.png

    2.2 在AppModule模块引入的初始化函数中使用

    这个场景也是我用到ConfigService比较多的,比如数据库连接,微服务注册时。下面我用MongoDB为例展示一下ConfigService的使用,连接不会成功,只是打印一下ConfigService的配置:

    import { Module } from '@nestjs/common';
    import { AppController } from './app.controller';
    import { AppService } from './app.service';
    import { ConfigModule, ConfigService } from '@nestjs/config';
    import { MongooseModule } from '@nestjs/mongoose';
    import { UsersModule } from './users/users.module';
    import AppConfig from './configs/appConfigs';
    @Module({
     imports: [
       ConfigModule.forRoot({
         envFilePath: '.env',
         load: [AppConfig],
      }),
       MongooseModule.forRootAsync({
         connectionName: 'APP_DB',
         imports: [ConfigModule],
         inject: [ConfigService],
         useFactory: (configService: ConfigService) => {
           const dbConfig = configService.get('db');
           console.log(dbConfig);
           return dbConfig;
        },
      }),
       UsersModule,
    ],
     controllers: [AppController],
     providers: [AppService],
    })
    export class AppModule {}

    image-20230815215733399.png