细说Nest系列之模块

150 阅读5分钟

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.tsimports 配置。

建议

  • 默认将 app.module.ts 保留在 src 目录中,便于 Nest CLI 自动导入新模块。

  • 使用 CLI 工具以减少繁琐的手动配置,提高开发效率。