Car*_*ven 12 javascript node.js typescript nestjs dotenv
我的.envNestJs 项目的根目录中有一个文件,其中包含一些 env 变量。
奇怪的是,我能够读取服务文件中的变量,但不能读取模块文件中的变量。
所以在像这样的服务文件中users.service.ts,这有效:
saveAvatar() {
const path = process.env.AVATAR_PATH // returns value from .env
}
Run Code Online (Sandbox Code Playgroud)
但是,当访问模块文件中的路径时,如auth.module.ts,这将返回一个空值:
@Module({
imports: [
JwtModule.register({
secretOrPrivateKey: process.env.SECRET // process.env.SECRET returns an empty string
})
]
})
Run Code Online (Sandbox Code Playgroud)
为什么呢?如何.env在 NestJs 中可靠地访问文件中的环境变量?
Kim*_*ern 18
您的.env文件还没有看过,当你在JwtModule被实例化。因此,要么在main.ts创建 nest 应用程序之前先阅读它,要么在您创建 nest 应用程序之前阅读它,或者更好:创建一个ConfigService并明确对您的配置的依赖:
JwtModule.registerAsync({
imports: [ConfigModule],
useFactory: async (configService: ConfigService) => ({
secretOrPrivateKey: configService.jwtSecret,
}),
inject: [ConfigService],
}),
Run Code Online (Sandbox Code Playgroud)
见这个答案就如何创建ConfigService。
声明顺序在您的用例中很重要。
这有效:
@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 {}
Run Code Online (Sandbox Code Playgroud)
当这不
@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 {}
Run Code Online (Sandbox Code Playgroud)
这是因为 ConfigModule 是在 TypeOrmModule 之前或之后加载的。
小智 6
我刚刚意识到我也解决了我的问题,只需导入 dotenv 并在我的模块(auth.module.ts)开头调用方法配置。
import dotenv from "dotenv";
dotenv.config({path:<path-to-env-file>})
Run Code Online (Sandbox Code Playgroud)
如果您使用项目根目录下的默认 .env 文件,则无需指定路径。
小智 5
就像@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
}
}
Run Code Online (Sandbox Code Playgroud)
然后它将像在 app.module 中一样简单,或者在加载 auth.module 的任何位置通过 forRoot 静态方法导入它。
import { ConfigModule } from '@nestjs/config';
@Module({
imports: [ConfigModule.forRoot(), AuthModule.forRoot()]
})
Run Code Online (Sandbox Code Playgroud)
注意:我建议在 app.module.ts 中导入一次 ConfigModule
PD:您可以使动态 auth.module 在 forRoot 方法中接收参数,并在 app.module 中传递环境变量process.env.SECRET
AuthModule.forRoot(process.env.SECRET)
Run Code Online (Sandbox Code Playgroud)
但似乎动态模块是最后加载的,因此不需要这样做。