nest框架官方文档中使用的是本地文件配置,也就是@nestjs/config包。本地配置文件的好处是简单,但是对于一些更新较快的项目,难免会增加配置数据,曾经吃过不少配置文件的亏,在发布的时候很容易因为缺少配置文件直接把服务发挂了,或者直接在服务器上修改配置很容易修改错误导致服务发布失败。

集中的配置中心可以解决上面问题,但前提是搭建配置中心。因公司已经有了配置中心,所以直接使用即可。 但是会出现这样的问题:从配置中心获取数据库连接信息,再去连接会连接失败,因为在连接的时候还没有获取到配置信息。 先看代码再解释。

// main.tsimport { NestFactory } from '@nestjs/core';import { ExpressAdapter, NestExpressApplication } from '@nestjs/platform-express';import { AppModule } from './app.module';import { MyLogger } from './libs/mylog.service';import { join } from 'path';const Apollo = require('node-apollo');const dotenv = require('dotenv');async function bootstrap() {try {const root = join(__dirname, '../');let envFile = join(root, '.env')
        dotenv.config({ "path": envFile })const {
            APOLLO_APPID,
            APOLLO_ENV,
            APOLLO_HOST,
            APOLLO_NAMESPACE,
            APOLLO_PORT,
            APOLLO_TOKEN,
            APOLLO_ClUSTER
        } = process.env;let apolloEnv = {configServerUrl: `http://${APOLLO_HOST}:${APOLLO_PORT}`,appId: `${APOLLO_APPID}`,clusterName: `${APOLLO_ClUSTER}`,apolloEnv: `${APOLLO_ENV}`,token: `${APOLLO_TOKEN}`,namespaceName: [`${APOLLO_NAMESPACE}`]
        };// 获取到的配置信息let zmConf = await Apollo.remoteConfigService(apolloEnv);console.log(">>>>>>>main.config", zmConf);
        process.env = Object.assign(process.env, zmConf);
    } catch (err) {console.log(`获取环境变量异常:${err}`)
    }const app = await NestFactory.create<NestExpressApplication>(AppModule, new ExpressAdapter());
    app.useLogger(app.get(MyLogger));await app.listen(3434, () => {const logger = new MyLogger('main.ts');
        logger.debug(process.env.NODE_ENV, 'main.ts');
        logger.log('server start on http://localhost:3434');
    });
}
bootstrap();复制代码
// app.module.ts@Module({imports: [// MongooseModule.forRoot(`mongodb://${process.env.DATABASE_USER}:${process.env.DATABASE_PASSWORD}@${process.env.DATABASE_HOST}:${process.env.DATABASE_PORT}/${process.env.DATABASE_DATABASE}`),MongooseModule.forRootAsync({useFactory: () => ({uri: `mongodb://${process.env.DATABASE_USER}:${process.env.DATABASE_PASSWORD}@${process.env.DATABASE_HOST}:${process.env.DATABASE_PORT}/${process.env.DATABASE_DATABASE}`}),
        }),//  Nest can't resolve dependencies of the AppService (?). Please make sure that the argument ArticleService at index [0] is available in the AppModule context.// 在article.service中exports:[ArticleService]ArticleModule,
        LoggerModule,// HttpModule,], // 导入模块所需的导入模块列表controllers: [AppController], // 必须创建的一组控制器providers: [AppService, MyLogger], // 由 Nest 注入器实例化的提供者,并且可以在整个模块中共享})export class AppModule implements NestModule {// 中间件模块在此处添加,可以给某一部分增加中间件,如果要全局增加则在main.ts中使用app.use添加configure(consumer: MiddlewareConsumer) {
        consumer
            .apply()// .with('中间件参数').forRoutes('/*');
    }
}复制代码

使用MongooseModule.forRoot连接数据库肯定是不行的,需要改成异步的:

MongooseModule.forRootAsync({useFactory: () => ({uri: `mongodb://${process.env.DATABASE_USER}:${process.env.DATABASE_PASSWORD}@${process.env.DATABASE_HOST}:${process.env.DATABASE_PORT}/${process.env.DATABASE_DATABASE}`}),
}),复制代码

因为按照nodejs模块导入的顺序,main.ts中先导入AppModule,AppModule中连接数据库,此时main.ts中的Apollo配置还没获取到,所以就不能正常连接了。那么就只能使用动态连接方式咯。