NestJS v10:无法根据Git分支自动加载对应.env文件问题求助
问题根源
你的代码里setConfigModule是异步函数,但NestJS初始化模块时,imports数组的解析是同步的,不会等待异步函数执行完成。这就导致MongooseModule.forRoot初始化时,ConfigModule还没来得及加载对应环境的.env文件,process.env里没有数据库相关变量,自然连接失败。
而直接指定envFilePath时,ConfigModule是同步加载的,.env变量能及时注入process.env,所以可以正常运行。
解决方案
这里提供两种靠谱的解决方式:
方式一:启动前预加载.env文件
在应用启动入口文件main.ts里,先获取当前Git分支,手动加载对应的.env文件,再启动Nest应用。这样所有模块初始化时,process.env已经有值了。
main.ts代码:
import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; import * as dotenv from 'dotenv'; import simpleGit from 'simple-git'; async function bootstrap() { // 获取当前Git分支 const git = simpleGit(); const branchInfo = await git.branch(); const envFilePath = branchInfo.current === 'main' ? '.env.prod' : '.env.dev'; // 加载对应环境变量文件 dotenv.config({ path: envFilePath }); // 启动Nest应用 const app = await NestFactory.create(AppModule); await app.listen(process.env.PORT || 3000); } bootstrap();
AppModule代码:
import { Module } from '@nestjs/common'; import { ConfigModule } from '@nestjs/config'; import { MongooseModule } from '@nestjs/mongoose'; import { AppController } from './app.controller'; import { AppService } from './app.service'; @Module({ imports: [ // 全局加载ConfigModule,无需指定envFilePath(已提前加载) ConfigModule.forRoot({ isGlobal: true }), MongooseModule.forRoot( `mongodb://${process.env.HOST}:${process.env.PORT}/${process.env.NAME}?readPreference=primary&appname=MongoDB%20Compass&directConnection=true&ssl=false`, ), ], controllers: [AppController], providers: [AppService], }) export class AppModule {}
方式二:用异步模块配置确保加载顺序
利用NestJS的异步模块特性,让ConfigModule异步加载对应.env文件,同时让MongooseModule依赖ConfigService,确保环境变量加载完成后再初始化数据库连接。
AppModule代码:
import { Module } from '@nestjs/common'; import { ConfigModule, ConfigService } from '@nestjs/config'; import { MongooseModule } from '@nestjs/mongoose'; import { AppController } from './app.controller'; import { AppService } from './app.service'; import simpleGit from 'simple-git'; // 获取对应环境的.env文件路径 async function getEnvFilePath() { const git = simpleGit(); const branchInfo = await git.branch(); return branchInfo.current === 'main' ? '.env.prod' : '.env.dev'; } @Module({ imports: [ // 异步加载ConfigModule,确保分支获取完成后再加载.env ConfigModule.forRootAsync({ isGlobal: true, useFactory: async () => ({ envFilePath: await getEnvFilePath(), }), }), // 异步初始化MongooseModule,依赖ConfigService获取环境变量 MongooseModule.forRootAsync({ useFactory: (configService: ConfigService) => ({ uri: `mongodb://${configService.get('HOST')}:${configService.get('PORT')}/${configService.get('NAME')}?readPreference=primary&appname=MongoDB%20Compass&directConnection=true&ssl=false`, }), inject: [ConfigService], }), ], controllers: [AppController], providers: [AppService], }) export class AppModule {}
这两种方式都能解决你的问题,方式一更简单直接,方式二更符合NestJS的模块化异步加载规范。
内容的提问来源于stack exchange,提问作者M Nouman
相关产品推荐
相关产品推荐

