nest框架官方文档中使用的是本地文件配置,也就是@nestjs/config
包。本地配置文件的好处是简单,但是对于一些更新较快的项目,难免会增加配置数据,曾经吃过不少配置文件的亏,在发布的时候很容易因为缺少配置文件直接把服务发挂了,或者直接在服务器上修改配置很容易修改错误导致服务发布失败。
集中的配置中心可以解决上面问题,但前提是搭建配置中心。因公司已经有了配置中心,所以直接使用即可。 但是会出现这样的问题:从配置中心获取数据库连接信息,再去连接会连接失败,因为在连接的时候还没有获取到配置信息。 先看代码再解释。
// main.ts
import { 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配置还没获取到,所以就不能正常连接了。那么就只能使用动态连接方式咯。