NestJs中动态获取项目配置(以配置typeorm举例)
NestJs中有多种方式来获取项目配置,如下所示为本文介绍的两种方法(均为真实用例)
- 通过文件读取项目配置
- 通过配置中心获取项目配置
一、文件读取项目配置
方法
- 读取.env文件,通过dotenv.parse方法形成key-value pairs,存在envConfig变量里
实现
- 通过命令生成Config模块,并更新如下文件
$ nest g service config
$ nest g module config
config.service.ts
import { Injectable, Logger } from '@nestjs/common';
import * as dotenv from 'dotenv';
import * as fs from 'fs';
@Injectable()
export class ConfigService {
private envConfig: {[key: string]: string};
constructor(filePath: string) {
// 读取.env文件,通过dotenv.parse方法形成key-value pairs
// 存在envConfig变量里
this.envConfig = dotenv.parse(fs.readFileSync(filePath));
}
get(key: string){
return this.envConfig[key];
}
}
config.module.ts
import { Module } from '@nestjs/common';
import { ConfigService } from './config.service';
@Module({
providers: [
{
provide: ConfigService,
// 刚刚的ConfigService要传入.env路径及文件名
useValue: new ConfigService(__dirname + `/../../env/${process.env.NODE_ENV || 'development'}.env`),
},
],
exports: [ConfigService]
})
export class ConfigModule { }
- 配置TypeOrm模块
typeorm.service.ts
import { TypeOrmModuleOptions, TypeOrmOptionsFactory } from '@nestjs/typeorm';
import { ConfigService } from './config.service';
import { Injectable } from '@nestjs/common';
@Injectable()
export class TypeOrmConfigService implements TypeOrmOptionsFactory {
// 注入config service取得env变量
constructor(private readonly configService: ConfigService) { }
// 就是回传TypeOrmOptions对象
createTypeOrmOptions(): TypeOrmModuleOptions {
return {
type: 'mysql', // configService.get('DB_TYPE') as DatabaseType,
host: this.configService.get('DB_HOST'),
port: this.configService.get('DB_PORT'),,
username: this.configService.get('DB_USER'),
password: this.configService.get('DB_PW'),
database: this.configService.get('DB_NAME'),
synchronize: this.configService.get('DB_TYPEORM_SYNC') === 'true',
logging: this.configService.get('DB_TYPEORM_LOG') === 'true',
entities: [
__dirname + '/../**/*.entity{.ts,.js}',
],
timezone: 'UTC'
};
}
}
- 更新App的Module模块
app.module.ts
import { Module, NestModule } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import {TypeOrmModule} from "@nestjs/typeorm";
import { ConfigModule } from './config/config.module';
import { TypeOrmConfigService } from './config/typeorm.service';
import { ConfigService } from './config/config.service';
@Module({
imports: [TypeOrmModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
useClass: TypeOrmConfigService,
}), ConfigModule],
controllers: [AppController],
providers: [AppService,TypeOrmConfigService],
})
export class AppModule{
}
优势
- 快速查看项目的配置信息
- 对某些配置进行相关处理,比如密码处理
缺陷
- 项目中存在example.env文件,每次部署都要重新编写
- 暴露项目重要配置信息
- 更改后重启项目配置生效
二、配置中心获取项目配置
因公司使用Apollo搭建的公共配置中心,所以把数据库的连接信息等相关配置存储在配置中心中,启动时获取环境变量信息
方法
- 使用node-apollo-client插件获取配置信息,存在envConfig变量里
- 还有别的apollo的包可以使用,这里不做分析
实现
- 添加node-apollo-client插件
$ npm install --save-dev node-apollo-client
or
$ yarn add node-apollo-client
- 更新Config的Module模块,来获取配置信息
config.module.ts
import { Module } from '@nestjs/common';
import { ConfigService } from './config.service';
import Apollo = require('node-apollo-client/dist');
@Module({
providers: [
{
provide: ConfigService,
useFactory: async () => {
const apollo = new Apollo({
configServerUrl: 'https://ip:port',
appId: 'app-id',
cluster: 'default', // [optional] default to `default`
namespaces: ['application'],
listenOnNotification: true, // [optional] default to true
fetchCacheInterval: 5 * 60e3,
});
const key = ['DB_HOST','DB_PORT','DB_NAME','DB_USER','DB_PW','DB_TYPEORM_SYNC','DB_TYPEORM_LOG']
const config = await apollo.fetchConfigs({ keys: key });
return new ConfigService(config);
},
},
],
exports: [ConfigService]
})
export class ConfigModule { }
- 更新Config的Service模块, 这里依旧存储在envConfig中
config.service.ts
import { Injectable, Logger } from '@nestjs/common';
@Injectable()
export class ConfigService {
private envConfig: {[key: string]: string};
constructor(config: any) {
this.envConfig = config
}
get(key: string){
return this.envConfig[key];
}
}
优势
- 提升项目配置信息的灵活性,且部分配置可多项目复用
- 不需要每次部署都写一遍配置
- 更改配置信息不需要重启项目
缺陷
- 无法直观的查看数据库配置
- 每次更新配置都需要到配置中心去发布