You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NestJS中MikroORM配置文件无法读取环境变量问题

问题原因

你的问题出在模块加载顺序上:database.config.ts里的代码在Nest的ConfigModule初始化之前就被执行了。当AppModule导入config对象时,Node会先加载database.config.ts并执行其中的代码,这时候ConfigModule还没来得及把环境变量注入到process.env中,所以process.env.DB_PASSWORD是undefined。而控制器等文件是在模块初始化完成后才被实例化的,这时候环境变量已经加载完成,所以能正常读取。

解决方案

推荐使用MikroORM的异步配置方式,借助Nest的依赖注入确保ConfigService已经加载了环境变量,具体步骤如下:

方案1:直接在AppModule中使用异步配置

修改app.module.ts,替换MikroOrmModule.forRoot(config)为异步配置:

import { ConfigModule, ConfigService } from '@nestjs/config';
import { Module } from '@nestjs/common';
import { MikroOrmModule } from '@mikro-orm/nestjs';
import { MySqlDriver } from '@mikro-orm/mysql';
import { BaseRepository } from 'src/libs/db/base-repository.repository';
import { Migrator } from '@mikro-orm/migrations';
// ...其他导入

@Module({
  imports: [
    ConfigModule.forRoot({ isGlobal: true }), // 设为全局模块,避免重复导入
    MikroOrmModule.forRootAsync({
      useFactory: (configService: ConfigService) => ({
        entities: ['./dist/core/entities'],
        entitiesTs: ['./src/core/entities/*.*'],
        dbName: 'invoice-app-be',
        driver: MySqlDriver,
        entityRepository: BaseRepository,
        password: configService.get<string>('DB_PASSWORD'),
        migrations: {
          tableName: 'mikro_orm_migrations',
          path: './lib/db/migrations/',
          allOrNothing: true,
        },
        extensions: [Migrator],
      }),
      inject: [ConfigService], // 注入ConfigService
    }),
  ],
  controllers: [AppController],
  providers: [
    AppService, 
    UserService, 
    InvoiceService, 
    LineItemService, 
    BillToService, 
    BillFromService,
  ],
})
export class AppModule {}

这种方式不需要单独的database.config.ts,直接把配置逻辑放在useFactory函数里,useFactory会在ConfigService初始化完成后执行,确保能拿到环境变量。

方案2:保留配置文件,改为函数式配置

如果想保留单独的配置文件,可以把database.config.ts改成接受ConfigService的函数:

import { Migrator } from '@mikro-orm/migrations';
import { MySqlDriver } from '@mikro-orm/mysql';
import { BaseRepository } from 'src/libs/db/base-repository.repository';
import { ConfigService } from '@nestjs/config';

export const getMikroOrmConfig = (configService: ConfigService) => ({
    entities: ['./dist/core/entities'],
    entitiesTs: ['./src/core/entities/*.*'],
    dbName: 'invoice-app-be',
    driver: MySqlDriver,
    entityRepository: BaseRepository,
    password: configService.get<string>('DB_PASSWORD'),
    migrations: {
      tableName: 'mikro_orm_migrations',
      path: './lib/db/migrations/',
      allOrNothing: true,
    },
    extensions: [Migrator],
});

然后在app.module.ts中调用这个函数:

import { ConfigModule, ConfigService } from '@nestjs/config';
import { Module } from '@nestjs/common';
import { MikroOrmModule } from '@mikro-orm/nestjs';
import { getMikroOrmConfig } from './configs/database.config';
// ...其他导入

@Module({
  imports: [
    ConfigModule.forRoot({ isGlobal: true }),
    MikroOrmModule.forRootAsync({
      useFactory: (configService: ConfigService) => getMikroOrmConfig(configService),
      inject: [ConfigService],
    }),
  ],
  // ...控制器和提供者
})
export class AppModule {}

备选方案:手动加载环境变量(不推荐)

如果不想用异步配置,也可以在database.config.ts顶部手动加载.env文件:

import 'dotenv/config'; // 手动加载.env
import { Migrator } from '@mikro-orm/migrations';
// ...其他导入

console.log(process.env.DB_PASSWORD) // 现在能获取到值

export const config = {
    // ...原配置内容
};

但这种方式可能和ConfigModule的配置冲突(比如自定义env路径),所以仅作为备选。

内容的提问来源于stack exchange,提问作者Daniel Benisti

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 09:26:35