NestJS - ConfigModule.forRoot的isGlobal选项不起作用。

5

我正在尝试在AuthModule中加载"process.env.AUTH_SECRET",但它给了我一个未定义的错误"Error: secretOrPrivateKey必须有一个值"。

我在AppModule中设置了"isGlobal: true",它能够很好地读取"process.env.MONGO_URL"。

我还安装了dotenv,如果我执行以下操作,它也可以正常读取:

import * as dotenv from 'dotenv';
dotenv.config();

export const jwtConstants = {
  secret: process.env.AUTH_SECRET,
};

但我更愿意按照"NestJs"的方式去做,因为文档中指出,添加isGlobal应该会使环境变量对所有其他模块可用。

auth.module.ts

import { Module } from '@nestjs/common';
import { AuthService } from './auth.service';
import { UserModule } from '../user/user.module';
import { PassportModule } from '@nestjs/passport';
import { LocalStrategy } from './local.strategy';
import { JwtModule } from '@nestjs/jwt';

@Module({
  imports: [
    UserModule,
    PassportModule,
    JwtModule.register({
      secret: process.env.AUTH_SECRET, //Cannot read this.
      signOptions: { expiresIn: '60s' },
    }),
  ],
  providers: [AuthService, LocalStrategy],
  exports: [AuthService, JwtModule],
})
export class AuthModule {}

app.module.ts

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { UserModule } from './user/user.module';
import { MongooseModule } from '@nestjs/mongoose';
import { ConfigModule } from '@nestjs/config';
import { AuthModule } from './auth/auth.module';

@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
    }),
    UserModule,
    MongooseModule.forRoot(process.env.MONGO_URL), // Can read this fine
    AuthModule,
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

我错过了什么或者做错了什么?只是作为参考,我正在尝试遵循这个身份验证教程

谢谢你,


1
尝试使用JwtModule.registerAsync而不是JwtModule.register,以避免使用process.env.*,就像https://docs.nestjs.com/techniques/http-module#async-configuration中所述。 - Micael Levi
1个回答

15

你的MongooseModuleAuthModule依赖于ConfigModule,但它们并不知道这一点。

你的模块正在繁忙地加载中,但是你的ConfigModule必须在准备就绪之前执行异步 I/O 过程(读取你的 .env)。与此同时,Nest 会继续加载而不等待 ConfigModule 完成它的工作,除非它发现另一个模块依赖于它的某个导出项

这就是 *Async 方法派上用场的地方。它们使你可以控制模块的实例化。在这种情况下,它们允许我们注入来自ConfigModuleConfigService,这只有在ConfigService准备就绪后才会发生。

所以,将你的 JWTModule 配置从使用.register更改为.registerAsync来注入ConfigService就是你想要的:

JWTModule.registerAsync({
    inject: [ConfigService],
    useFactory: (config: ConfigService) => {
      secret: config.get<string>('AUTH_SECRET'),
      signOptions: { expiresIn: '60s' }
    }
})

现在,JWTModule将不会加载直到ConfigService准备就绪并在范围内可用。您很可能也需要为MongooseModule执行此操作。

这是“NestJS”的方法。

话虽如此,如果您真正需要做的只是让.env加载到process.env中,请添加:

import * as dotenv from 'dotenv';
import { resolve } from 'path';
dotenv.config({ path: resolve(__dirname, '../.env') });

将其放置在您的 main.ts 文件的开头。这将导致 dotenv 在任何其他操作发生之前同步加载它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接