我的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
文件中可靠地访问环境变量?
答案 0 :(得分:2)
我刚刚意识到我也解决了我的问题,只需在我的模块 (auth.module.ts) 的开头导入 dotenv 并调用方法配置。
import "dotenv" from dotenv;
dotenv.config({path:<path-to-env-file>})
如果您使用的是项目根目录中的默认 .env 文件,则无需指定路径。
答案 1 :(得分:1)
实例化.env
时尚未读入您的JwtModule
文件。所以要么早点阅读它在创建嵌套应用或更好的嵌套应用之前,在您的main.ts
中:创建一个ConfigService
并明确显示对配置的依赖关系:
JwtModule.registerAsync({
imports: [ConfigModule],
useFactory: async (configService: ConfigService) => ({
secretOrPrivateKey: configService.jwtSecret,
}),
inject: [ConfigService],
}),
有关如何创建ConfigService
的信息,请参见this answer。
答案 2 :(得分:1)
您可以将其用作全局模块,以便从其他模块进行访问。
要在其他模块中使用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
答案 3 :(得分:0)
就像@KimKen所说的那样,问题在于,在实例化JwtModule时,环境变量仍未加载。但是,我对@KimKen的回答有另一种方法,您可能也会对此感兴趣。
首先,NestJS提供了一个ConfigModule来加载环境变量,因此您无需创建一个ConfigModule,除非您希望以不同于通常的方式处理它。 (https://docs.nestjs.com/techniques/configuration)
现在,为了解决此问题,我使模块(auth.module.ts)动态化。 简而言之,动态模块是接收参数的模块,它的正确实例取决于输入参数。(https://docs.nestjs.com/fundamentals/dynamic-modules)
这里发生的事情是,JwtModule也是一个动态模块,因为它依赖于变量进行正确的实例化。因此,这也会导致您的模块也依赖参数进行正确的实例化,因此使其动态! :)。
然后您的身份验证模块将类似于:
@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)
但是似乎动态模块最后被加载了,所以没有必要。
答案 4 :(得分:0)
声明顺序在您的用例中很重要。
这有效:
@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 之前或之后加载。