13

.env我的 NestJs 项目的根目录中有一个文件,其中包含一些环境变量。

奇怪的是,我能够读取服务文件中的变量,但不能读取模块文件中的变量。

所以在像这样的服务文件中users.service.ts,这是有效的:

saveAvatar() {
    const path = process.env.AVATAR_PATH    // returns value from .env
}

但是,当访问模块文件中的路径时auth.module.ts,这将返回一个空值:

@Module({
    imports: [
       JwtModule.register({
          secretOrPrivateKey: process.env.SECRET   // process.env.SECRET returns an empty string
       })
    ]
})

为什么呢?如何可靠地访问.envNestJs 文件中的环境变量?

4

5 回答 5

20

实例化您的.env文件时尚未读入您的文件。JwtModule因此,要么在之前阅读它,例如在main.ts创建嵌套应用程序之前阅读它,要么更好:创建一个ConfigService并明确对您的配置的依赖:

JwtModule.registerAsync({
    imports: [ConfigModule],
    useFactory: async (configService: ConfigService) => ({
      secretOrPrivateKey: configService.jwtSecret,
    }),
    inject: [ConfigService],
}),

有关如何创建ConfigService.

于 2019-04-14T09:04:13.300 回答
3

我只是意识到我也解决了我的问题,只是在我的模块(auth.module.ts)的开头导入 dotenv 并调用方法配置。

import "dotenv" from dotenv;

dotenv.config({path:<path-to-env-file>})

如果您使用项目根目录中的默认 .env 文件,则无需指定路径。

于 2021-01-18T14:32:43.933 回答
3

您可以将其用作全局以便从其他模块进行访问。

当您想在其他模块中使用 ConfigModule 时,您需要导入它(这是任何 Nest 模块的标准配置)。或者,通过将选项对象的 isGlobal 属性设置为 true 来将其声明为全局模块,如下所示。在这种情况下,一旦将 ConfigModule 加载到根模块(例如,AppModule)中,您就不需要在其他模块中导入它

.https://docs.nestjs.com/techniques/configuration#use-module-globally

ConfigModule.forRoot({
  isGlobal: true
});

您还可以在这里找到如何使用配置服务:https ://docs.nestjs.com/techniques/configuration#using-the-configservice

于 2020-07-24T11:51:03.577 回答
3

声明顺序在您的用例中很重要。

这有效:

@Module({
  imports: [
    ConfigModule.forRoot(),
    ScheduleModule.forRoot(),
    TypeOrmModule.forRoot({
      type: 'mongodb',
      host: process.env.SYN_MONGO_HOST,
      port: +process.env.SYN_MONGO_PORT,
      username: process.env.SYN_MONGO_USERNAME,
      password: process.env.SYN_MONGO_PASSWORD,
      database: process.env.SYN_MONGO_DATABASE,
      authSource: 'admin',
      autoLoadEntities: true,
    }),
  ],
  controllers: [],
  providers: [],
})
export class ConfigurationModule {}

当这不

@Module({
  imports: [
    ScheduleModule.forRoot(),
    TypeOrmModule.forRoot({
      type: 'mongodb',
      host: process.env.SYN_MONGO_HOST,
      port: +process.env.SYN_MONGO_PORT,
      username: process.env.SYN_MONGO_USERNAME,
      password: process.env.SYN_MONGO_PASSWORD,
      database: process.env.SYN_MONGO_DATABASE,
      authSource: 'admin',
      autoLoadEntities: true,
    }),
    ConfigModule.forRoot(),
  ],
  controllers: [],
  providers: [],
})
export class ConfigurationModule {}

这是因为 ConfigModule 在 TypeOrmModule 之前或之后加载。

于 2021-07-29T12:19:15.087 回答
1

就像@KimKen 所说,问题在于,在实例化 JwtModule 时,环境变量仍未加载。但是,我对@KimKen 的回答有不同的方法,您可能也会感兴趣。

首先,NestJS 提供了一个加载环境变量的 ConfigModule,所以你不需要创建一个,除非你希望处理它不同于平常。(https://docs.nestjs.com/techniques/configuration

现在,为了解决这个问题,我使模块(auth.module.ts)动态化。简而言之,动态模块是接收参数的模块,它依赖于输入参数进行正确的实例化。(https://docs.nestjs.com/fundamentals/dynamic-modules

这里真正发生的事情是,JwtModule 也是一个动态模块,因为它依赖于一个变量来进行正确的实例化。所以,这导致你的模块也依赖于参数来进行正确的实例化,所以让它动态化!:)。

然后您的 auth.module 将类似于:

@Module({})
export class AuthModule {

    static forRoot(): DynamicModule {
        return {
            imports: [
                JwtModule.register({
                    secretOrPrivateKey: process.env.SECRET   // process.env.SECRET will return the proper value
                })
            ],
            module: AuthModule
        }
    }

然后它将像在您的 app.module 中一样简单,或者在您加载 auth.module 的任何地方通过 forRoot 静态方法导入它。

import { ConfigModule } from '@nestjs/config';

@Module({
    imports: [ConfigModule.forRoot(), AuthModule.forRoot()]
})

注意:我建议在 app.module.ts 中导入一次 ConfigModule

PD:您可以让动态 auth.module 在 forRoot 方法中接收参数,并在 app.module 中传递环境变量process.env.SECRET

AuthModule.forRoot(process.env.SECRET)

但似乎动态模块是最后加载的,所以不需要这样做。

于 2020-12-03T18:21:32.593 回答