typescript NestJs:无法读取模块文件中的env变量,但可以读取服务文件中的env变量?

zphenhs4  于 2023-03-04  发布在  TypeScript
关注(0)|答案(7)|浏览(413)

我在NestJs项目的根目录下有一个.env文件,其中包含一些env变量。
奇怪的是,我能够读取服务文件中的变量,但不能读取模块文件中的变量。
因此,在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
       })
    ]
})

为什么会这样呢?我怎样才能可靠地访问NestJs中.env文件中的环境变量呢?

rbl8hiat

rbl8hiat1#

当您的JwtModule示例化时,您的.env文件尚未读入。因此,请在创建nest应用之前提前读入它,例如在您的main.ts中读入,或者更好:创建一个ConfigService,并明确依赖于您的配置:

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

关于如何创建ConfigService,请参见this answer

xqkwcwgp

xqkwcwgp2#

声明顺序在您的用例中很重要。
这是可行的:

@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之前或之后加载。

lbsnaicq

lbsnaicq3#

您可以将其用作全局变量,以便从其他模块进行访问。
当你想在其他模块中使用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

wn9m85ua

wn9m85ua4#

正如@KimKen所说,问题在于,当JwtModule示例化时,环境变量仍然没有加载。然而,我对@KimKen的回答有一个不同的方法,您可能也会感兴趣。
首先,NestJS提供了一个加载环境变量的ConfigModule,所以你不需要创建一个,除非你想处理它不同于通常.(https://docs.nestjs.com/techniques/configuration
现在,为了解决这个问题,我把这个模块(auth.module.ts)动态化了。简而言之,动态模块是接收参数的模块,它依赖于输入参数来进行正确的示例化。(https://docs.nestjs.com/fundamentals/dynamic-modules
这里的真实的情况是,JwtModule也是一个动态模块,因为它依赖于一个变量来进行正确的示例化。因此,这也导致了您的模块依赖于参数来进行正确的示例化,因此使其动态化!:)。
那么您的auth.模块将类似于:

@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
        }
    }

然后,它将是一样容易,因为在您的应用程序。模块或任何地方,你加载的auth。模块导入它通过forRoot静态方法。

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

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

注意:我建议在app.module.ts中导入一次ConfigModule
PD:您可以让动态auth.模块接收forRoot方法中的参数,并在app.模块中传递环境变量process.env.SECRET

AuthModule.forRoot(process.env.SECRET)

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

r6vfmomb

r6vfmomb5#

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

import dotenv from "dotenv";

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

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

6rqinv9w

6rqinv9w6#

这对我很有效

@Module({
    imports: [ConfigModule.forRoot({
        envFilePath: join(process.cwd(), 'env', `.env.${process.env.SCOPE.trim()}`),
    })]
})

解决方案是使用trim()函数,因为在Windows中,空格会添加到环境变量值的末尾

wlwcrazw

wlwcrazw7#

我也遇到过类似的问题。我在另一台机器上编写代码,运行良好。将repo克隆到另一台机器上,尝试运行,但遇到了env变量问题,因为我没有.env文件。复制了它,但仍然收到错误消息。删除node_modules并安装,然后nom run build为我解决了这个问题

相关问题