1. 什么是模块化
在 NestJS 中,模块是应用程序中功能的包。每当你创建一个新的功能时,你都需要创建一个新模块。就Nest而言,模块可以把它当作一个特定的功能包。
上面这个图片,分别有 controller
service
service
.spec
controller
表示控制器,主要处理路由和请求。
service
表示服务,主要是处理业务逻辑,包括数据获取和处理,通常是通过数据库进行操作
entity
表示实体,用于数据库交互,定义数据结构。
spec
表示测试文件,通常用于模块内部的测试。
2. 创建模块
2.1 手动创建模块
import {Module} from "@nestjs/common"
@Module({
imports:[], // 导入模块
provider:[], // 注入服务
controller:[], // 导入控制器
exports: [], // 导出服务,这里导出后,其他模块的服务可以使用当前模块的服务。
})
export class UserModule {}
2.2 CLI创建模块(推荐)
nest g module user --no-flat
3. 共享模块
什么是共享模块,在B模块中需要调用 A模块中的A.service ,这个时候,需要把A.service导出给B模块使用。
A模块
import {Module} from "@nestjs/common";
@Module({
provider:[Aservice],
export:[Aservice] // 导出服务,这里导出后,其他模块的服务可以使用当前模块的服务。
})
export class AModule {}
B模块
import {Module} from "@nestjs/common"
import AModule from "./A/A.module"
@Module({
imports:[Amodules]
})
BService
import {Injectable, Inject} from "@nestjs/common"
import {AService} from "./A/A.service"
@Injectable()
export class BService {
constructor(
// 注入Aservice,方法一 (推荐)
private readonly aService: AService
){}
// 方法二,不使用constructor
@Inject(AService)
private readonly aService:AService
}
4. 全局模块
全局模块,理所当然,就是给全局的模块使用,方便管理。简单。
import {Module,Global} from "@nestjs/common";
@Global()
@Module({
provider:[Aservice],
export:[Aservice] // 导出服务,这里导出后,其他模块的服务可以使用当前模块的服务。
})
export class AModule {}
5. 动态模块
动态模块,其实可以理解为,在应用运行的时候,异步去加载创建模块,通常用于动态读取配置或者根据权限判断加载模块的。比如:数据库的配置,Redis配置。
动态模块通常通过静态方法 forRoot()
或 forRootAsync()
来创建,这些方法可以根据需要接受不同的配置参数。它们返回一个 Module
对象,可以用于模块的导入。
5.1 使用 forRoot() 方法
forRoot()
方法通常用于配置和初始化模块,返回一个配置后的模块。
创建一个动态模块
import { Module, DynamicModule } from '@nestjs/common';
@Module({})
export class MyDynamicModule {
static forRoot(config: string): DynamicModule {
return {
module: MyDynamicModule,
providers: [
{
provide: 'CONFIG',
useValue: config,
},
],
exports: ['CONFIG'],
};
}
}
使用动态模块
import { Module } from '@nestjs/common';
import { MyDynamicModule } from './my-dynamic.module';
@Module({
imports: [
MyDynamicModule.forRoot('My Custom Configuration'), // 传递自定义配置
],
})
export class AppModule {}
在这个例子中,MyDynamicModule
模块接受一个配置字符串,并将其作为一个提供者注入到模块中。
5.2 使用 forRootAsync() 方法
当你需要异步加载配置时,使用 forRootAsync()
方法会更方便。这个方法通常用于从外部配置源(比如数据库、环境变量或配置文件)动态加载配置。
import { Module, DynamicModule, Global } from '@nestjs/common';
import { ConfigService } from './config.service';
@Global() // 使模块在全局范围内可用
@Module({})
export class MyDynamicModule {
static forRootAsync(): DynamicModule {
return {
module: MyDynamicModule,
imports: [ConfigService],
providers: [
{
provide: 'CONFIG',
useFactory: async (configService: ConfigService) => {
return await configService.loadConfig(); // 异步加载配置
},
inject: [ConfigService],
},
],
exports: ['CONFIG'],
};
}
}
使用异步配置模块
import { Module } from '@nestjs/common';
import { MyDynamicModule } from './my-dynamic.module';
import { ConfigService } from './config.service';
@Module({
imports: [MyDynamicModule.forRootAsync()],
providers: [ConfigService],
})
export class AppModule {}
在这个例子中,forRootAsync()
使用一个工厂方法来加载异步配置。
5.3 配置和依赖注入
动态模块的一个重要用途是处理不同配置的依赖注入。在创建模块时,可以提供不同的配置参数或服务,NestJS 将根据这些信息进行相应的初始化。
5.4 动态模块的应用场景
- 数据库连接配置:根据不同环境(开发、测试、生产)动态加载不同的数据库配置。
- 日志服务:根据不同的环境或条件初始化不同的日志记录配置。
- 微服务配置:根据不同的微服务配置条件(如端口、协议等)动态创建微服务模块。
动态模块的关键在于它可以接受配置并根据需求生成模块,这使得在一些复杂的场景中,模块的创建变得非常灵活。
6.创建一个UserModuel
使用 Nest CLI 创建模块
通过运行 nest generate module users
,可以快速生成一个新的用户模块。CLI 会:
-
在
src
目录中创建users
文件夹和users.module.ts
文件。 -
自动将新模块导入到
app.module.ts
文件中的imports
数组中。
命名约定:CLI 会遵循 NestJS 的标准文件和类命名格式,减少手动配置工作。
nest g module users
手动生成
在 src
目录中创建一个新目录(例如 users
),并在其中创建 users.module.ts
文件。
定义一个类(例如 UsersModule
),并使用 @Module
装饰器将其声明为模块。
将模块通过导入添加到 app.module.ts
文件中的 imports
数组中,以激活该模块并使其可用。
users.module.ts
import {Module} from '@nestjs/common'@Module({})export class UserModule{}
app.module.ts
import {UsersModule} from './users/users.module'@Module({ imports:[UsersModule]})
验证模块:
-
在终端中查看日志,确认新模块及其依赖项是否已成功初始化。
-
如果模块未正确连接或加载,可以检查文件结构和
app.module.ts
的imports
配置。
建议:
-
默认将
app.module.ts
保留在src
目录中,便于 Nest CLI 自动导入新模块。 -
使用 CLI 工具以减少繁琐的手动配置,提高开发效率。