在 NestJS 中实现外部定义的配置设置
你可能已经花了一些时间使用了很棒的 NestJS 框架,现在是时候看看如何为你的配置设置获取一些外部定义的值,比如一些键或全局变量,例如:
- 应用监听端口号
- API 全局路由前缀
- JWT 参数(令牌密钥、令牌过期时间,例如以秒为单位)
- 数据库连接参数(类型、主机、端口、用户名、密码、数据库)
- 等等。
NestJS 提供了使用外部配置文件和环境变量处理不同环境(开发、生产等)的必要文档。 因此,如果大家已经看过那里,那么下面提供的案例也将帮助大家开始实施你的(相对简单的)项目。
注意
:假设你已经为自己的项目安装了 @nestjs/config 包,如果还安装了 @nestjs/jwt 包并开始使用 JSON Web 令牌也很好。
因此,大家可以在下面找到在自己的实现中使用的 3 个最简单和最常见的案例。
基础
具有已定义属性及其值(如键/值对)的 .env.dev
环境配置文件
.env.dev
APP_PORT=3000 JWT_SECRET=abcdABCD1234554321 JWT_EXP=60
package.json 文件中的脚本
. . .
"start:dev": "STAGE=dev nest start --watch",
"start:debug": "STAGE=debug nest start --debug --watch",
"start:prod": "STAGE=prod node dist/main",
. . .
例如,我们可以在终端中运行 dev 配置:
$ npm run start:dev
在 AppModule 中全局配置 ConfigModule
import { Module } from '@nestjs/common';
import { UsersModule } from './users/users.module';
import { AuthModule } from './auth/auth.module';
import { ConfigModule } from '@nestjs/config';
@Module({
imports: [
UsersModule,
AuthModule,
ConfigModule.forRoot({
isGlobal: true,
envFilePath: [`.env.${process.env.STAGE}`],
}),
],
})
export class AppModule {}
-
.forRoot()
- 这个静态方法在 ConfigModule 中加载环境变量,配置 ConfigService 提供者,并使其在模块范围内,并且由于这是 AppModule,因此它可以在整个应用程序中使用。 -
isGlobal
— 我们使用 isGlobal 属性并将其设置为 true,这样我们就可以在项目中普遍使用 ConfigModule,而不必在每个模块中单独导入它。 -
envFilePath
——我们使用 envFilePath 属性从文件中加载环境变量——我们传递包含它们的文件的完整路径名。
现在,是时候在我们的项目中使用外部定义的值(通过 ConfigModule)了。
在类/repo/service 中使用 ConfigService
首先,我们必须将它添加到该类/属性/服务所属的 Module 的 imports 属性数组中。
imports: [AuthModule, ConfigModule],
在 UsersModule 中导入 ConfigModule
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { AuthModule } from 'src/auth/auth.module';
import { UsersRepo } from 'src/dataObjects/users.repo';
import { UsersController } from './users.controller';
import { UsersService } from './users.service';
@Module({
//imports: [AuthModule, ConfigModule],
imports: [AuthModule],
controllers: [UsersController],
providers: [UsersService, UsersRepo],
exports: [UsersRepo],
})
export class UsersModule {}
请注意,在我们的例子中,我们已经在 AppModule 中设置了全局使用的 ConfigModule(即,我们将 isGlobal 属性设置为 true),因此,无需在导入属性数组中导入 ConfigModule。
然后,我们必须将它注入到该类/repo/service 的构造函数中:
. . .
constructor(
private jwtService: JwtService,
private configService: ConfigService,
) {
this.myUsers = [this.user1, this.user2];
}
. . .
最后,我们可以“正常”使用它:
. . .
const mySecret = this.configService.get('JWT_SECRET');
const verifyOptions = { secret: mySecret };
. . .
在 main.ts 中使用 ConfigService
由于 main.ts 仅包含 bootstrap() 函数,我们可以将 ConfigService 实例/上下文作为 const 获取,如下所示:
const configService = app.get(ConfigService);
之后,我们就可以使用实例的get方法了,正常的方式,e.g. 对于应用程序侦听端口:
const appPort = configService.get<number>('APP_PORT', 3000);
await app.listen(appPort);
如你所见(正如官方文档所述)“get() 方法还接受一个可选的第二个参数,定义一个默认值,当键不存在时将返回,如上所示”应用程序监听端口 , 默认值为 3000。
我们可以对环境文件中声明的任何其他键执行相同的操作。
main.ts
文件的示例:
import { Logger, ValidationPipe } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { NestFactory } from '@nestjs/core';
import { TransformInterceptor } from './app-interceptors/transform.interceptor';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
const configService = app.get(ConfigService);
const appGlobalPrefix = configService.get<string>('APP_GLOBAL_PREFIX', '');
app.setGlobalPrefix(appGlobalPrefix);
app.useGlobalPipes(new ValidationPipe());
app.useGlobalInterceptors(new TransformInterceptor());
//await app.listen(3000);
const appPort = configService.get<number>('APP_PORT', 3000);
await app.listen(appPort);
const stage = process.env.STAGE;
Logger.log(
'App is running in "' +
stage +
'" stage, and it is listening at: http://localhost:' +
appPort +
'/' +
appGlobalPrefix +
'/',
);
}
bootstrap();
在动态导入的模块中注入和使用 ConfigService
(它被导入到模块的导入属性数组中)
例如,当我们在另一个模块中导入 JwtModule 时就是这种情况,例如。 在授权模块中:AuthModule。 下面是我们如何导入 JwtModule 并直接注册其参数/属性的值:signOptions 中的 secret 和 expiresIn。
这里的第一个提示是异步注册 JwtModule,例如
JwtModule.registerAsync(. . .)
这是必要的,因为我们必须异步读取外部文件,例如 .env 文件。
然后,我们必须在注入属性数组中添加 ConfigModule。 之后,我们可以使用 useFactory() 动态地(和异步地)提供/注入 ConfigService 实例。
完整版 AuthModule 的示例:
import { forwardRef, Module } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { JwtModule } from '@nestjs/jwt';
import { UsersModule } from 'src/users/users.module';
import { AuthController } from './auth.controller';
import { AuthService } from './auth.service';
@Module({
imports: [
forwardRef(() => UsersModule),
// JwtModule.register({
// secret: 'myTopSecret54321',
// signOptions: {
// expiresIn: 3600,
// },
// }),
JwtModule.registerAsync({
// imports: [ConfigModule],
inject: [ConfigService],
useFactory: async (configService: ConfigService) => ({
secret: configService.get('JWT_SECRET'),
signOptions: {
expiresIn: configService.get<number>('JWT_EXP', 60),
},
}),
}),
],
controllers: [AuthController],
providers: [AuthService],
exports: [JwtModule],
})
export class AuthModule {}
同样在这里,也不需要在模块属性数组中声明 ConfigModule
,因为我们已经在 AppModule 中设置了 isGlobal: true
。
相关文章
如何在 NestJS 中使用 DTO 进行验证
发布时间:2022/04/24 浏览次数:609 分类:WEB前端
-
这里我们将讨论 NestJS 中的数据传输对象 (DTO) 以及如何使用它们来验证请求。
Nest.JS 用户注入详细介绍
发布时间:2022/04/23 浏览次数:260 分类:WEB前端
-
Nest.JS 是最流行的 Node.js 框架。 它利用 TypeScript 的全部功能使开发过程快速而简单。 在本文中,我将分享非常酷且有用的技巧“用户注入(User Injection)”,它可以大大简化我们的 Nest.JS
如何在 NestJS 中使用版本控制
发布时间:2022/04/19 浏览次数:316 分类:WEB前端
-
NestJS 是一个用于构建 Node.js 服务器端应用程序的框架。我不会在本文中详细介绍 NestJS 是什么以及为什么要使用它,但我建议查看他们的文档!版本控制已添加到 2021 年 7 月发布的 Nes