从零开始Node之旅——Nest.js 模块系统(Modules)

Nest.js 的模块系统是其架构的核心组成部分,它借鉴了 Angular 的模块设计思想,通过模块化的方式组织代码,实现关注点分离、依赖管理和代码复用。模块系统让大型应用的结构更加清晰,便于维护和扩展。

一、模块的核心概念与作用

  1. 关注点分离
    将相关功能(如用户管理、认证、日志等)封装到独立模块中,避免代码耦合。
  2. 依赖管理
    明确模块间的依赖关系,通过导入(imports)和导出(exports)控制功能共享。
  3. 依赖注入作用域
    模块定义了 provider 的作用域,确保服务在模块内高效共享。
  4. 代码组织
    模块系统帮助团队按照功能域组织代码,提升项目可维护性。

二、模块的基本结构与创建

Nest.js 模块通过 @Module 装饰器定义,核心属性包括:

  • imports:导入其他模块,获取其导出的功能
  • providers:模块内的服务、工厂等依赖注入对象
  • controllers:模块关联的控制器
  • exports:导出模块内的 providers 或导入的模块,供其他模块使用

示例:创建一个基础模块

typescript 复制代码
// user.module.ts
import { Module } from '@nestjs/common';
import { UserController } from './user.controller';
import { UserService } from './user.service';
import { DatabaseModule } from '../database/database.module';

@Module({
  imports: [DatabaseModule], // 导入数据库模块
  controllers: [UserController], // 注册控制器
  providers: [UserService], // 注册服务
  exports: [UserService], // 导出服务供其他模块使用
})
export class UserModule {}

三、模块的核心属性详解

  1. imports:模块依赖导入
    当模块需要使用其他模块的功能时,通过 imports 导入目标模块。例如:
kotlin 复制代码
@Module({
  imports: [AuthModule, DatabaseModule], // 导入多个模块
})
export class UserModule {}
  1. exports:功能导出
    通过 exports 声明模块内可被其他模块使用的 providers 或导入的模块:
less 复制代码
@Module({
  imports: [DatabaseModule],
  providers: [UserService],
  exports: [UserService, DatabaseModule], // 导出自身服务和导入的模块
})
export class UserModule {}
  1. providers:模块内服务注册
    providers 包含模块所需的所有依赖注入对象(服务、仓库、工厂等),这些对象会在模块内共享:
less 复制代码
@Module({
  providers: [
    UserService,
    {
      provide: 'USER_REPOSITORY',
      useClass: UserRepository,
    },
  ],
})
export class UserModule {}
  1. controllers:控制器注册
    controllers 声明模块关联的控制器,控制器会接收请求并调用模块内的服务:
kotlin 复制代码
@Module({
  controllers: [UserController, AdminController],
})
export class UserModule {}

controllersproviders最大的不同是,每次请求都会创建一个controllers,而providers是单例模式,全局唯一。

四、模块间的依赖与共享

  1. 模块导入与功能共享
    当模块 A 导入模块 B 后,模块 A 可以使用模块 B 导出的所有功能:
kotlin 复制代码
// app.module.ts
@Module({
  imports: [UserModule, AuthModule], // 导入用户模块和认证模块
})
export class AppModule {}
  1. 循环依赖处理
    Nest.js 支持循环依赖,但应尽量避免。若必须使用,可通过以下方式处理:
kotlin 复制代码
// user.module.ts
@Module({
  imports: [
    forwardRef(() => AuthModule), // 使用forwardRef解决循环依赖
  ],
})
export class UserModule {}

五. 类与模块的关系

模块的核心作用是将功能相关的类聚合在一起 ,避免代码散落在项目各处。例如:

一个用户管理模块(UserModule)会包含用户相关的控制器(UserController)、服务(UserService)、守卫(AuthGuard)等类,这些类共同完成用户管理的功能。

less 复制代码
// user.module.ts(模块定义)
@Module({
  controllers: [UserController],  // 声明模块包含的控制器类
  providers: [UserService, AuthGuard],  // 声明模块包含的服务、守卫类
  imports: [DatabaseModule],  // 导入其他模块的类(如数据库连接服务)
  exports: [UserService],  // 导出服务类供其他模块使用
})
export class UserModule {}

六、根模块(Root Module)

每个 Nest.js 应用都有一个根模块(通常为 AppModule),作为应用的入口:

typescript 复制代码
// app.module.ts
import { Module } from '@nestjs/common';
import { UserModule } from './user/user.module';
import { AuthModule } from './auth/auth.module';

@Module({
  imports: [UserModule, AuthModule], // 导入所有子模块
})
export class AppModule {}

main.ts 中引导根模块:

javascript 复制代码
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  await app.listen(3000);
}
bootstrap();

七、动态模块(Dynamic Modules)

动态模块允许在运行时配置模块,常用于需要动态参数的服务(如数据库连接、第三方服务集成)。通过 forRootforFeature 方法实现:

arduino 复制代码
// database.module.ts
import { Module, DynamicModule } from '@nestjs/common';
import { DatabaseService } from './database.service';

@Module({})
export class DatabaseModule {
  // 用于根模块的全局配置
  static forRoot(config: DatabaseConfig): DynamicModule {
    return {
      module: DatabaseModule,
      providers: [
        {
          provide: 'DATABASE_CONFIG',
          useValue: config,
        },
        DatabaseService,
      ],
      exports: [DatabaseService],
    };
  }

  // 用于功能模块的局部配置
  static forFeature(): DynamicModule {
    return {
      module: DatabaseModule,
      exports: [DatabaseService],
    };
  }
}

使用动态模块:

less 复制代码
// app.module.ts
@Module({
  imports: [
    DatabaseModule.forRoot({
      host: 'localhost',
      port: 5432,
      username: 'user',
    }),
  ],
})
export class AppModule {}
相关推荐
uzong3 小时前
技术故障复盘模版
后端
GetcharZp3 小时前
基于 Dify + 通义千问的多模态大模型 搭建发票识别 Agent
后端·llm·agent
桦说编程4 小时前
Java 中如何创建不可变类型
java·后端·函数式编程
IT毕设实战小研4 小时前
基于Spring Boot 4s店车辆管理系统 租车管理系统 停车位管理系统 智慧车辆管理系统
java·开发语言·spring boot·后端·spring·毕业设计·课程设计
wyiyiyi4 小时前
【Web后端】Django、flask及其场景——以构建系统原型为例
前端·数据库·后端·python·django·flask
阿华的代码王国5 小时前
【Android】RecyclerView复用CheckBox的异常状态
android·xml·java·前端·后端
Jimmy5 小时前
AI 代理是什么,其有助于我们实现更智能编程
前端·后端·ai编程
AntBlack6 小时前
不当韭菜V1.1 :增强能力 ,辅助构建自己的交易规则
后端·python·pyqt
bobz9657 小时前
pip install 已经不再安全
后端
寻月隐君7 小时前
硬核实战:从零到一,用 Rust 和 Axum 构建高性能聊天服务后端
后端·rust·github