模块是用@Module()装饰器修饰的类,它将相关组件——控制器、提供者/服务——分组到一个内聚的单元中。模块是NestJS将应用程序组织成功能的方式,每个Nest应用都至少有一个根AppModule。
定义一个模块
ts
{ } ;
({
: [],
: [],
: [],
: [],
})
{}
controllers → the controllers (request handlers) in this module
providers → the providers/services defined and instantiated here (for DI)
imports → other modules whose EXPORTED providers this module can use
exports → the subset of THIS module's providers shared with importing modules
模块形成一个DI作用域:提供者在其模块内可用,仅当导出后且其他模块导入它时,才对其他模块可用。
@Module({
imports: [UsersModule, AuthModule, DatabaseModule], // compose feature modules
})
export class AppModule {} // the root — bootstrapped to start the app
每个应用都有一个根AppModule,它导入功能模块,组成整个应用程序。
src/
app.module.ts (root — imports feature modules)
users/
users.module.ts (groups users controller + service)
users.controller.ts
users.service.ts
auth/
auth.module.ts
database/
database.module.ts (shared infrastructure)
惯例是每个功能/域一个模块(用户、认证、产品),将相关代码保持在一起,使依赖关系明确。
// UsersModule exports UsersService...
@Module({ providers: [UsersService], exports: [UsersService] })
export class UsersModule {}
// ...so AuthModule can use it by importing UsersModule
@Module({ imports: [UsersModule] }) // now AuthModule can inject UsersService
export class AuthModule {}
要使用来自另一个模块的提供者,提供该提供者的模块必须导出它,消费模块必须导入该提供模块——使依赖关系明确。
模块是每个NestJS应用程序的组织支柱——它们将相关的控制器和提供者分组为内聚的功能单元,并定义依赖注入的边界。
理解四个属性(controllers、providers、imports、exports),特别是跨模块共享提供者的导入/导出机制至关重要:这是NestJS实现模块化、松耦合架构的方式,其中每个功能都是自包含的,依赖关系是明确的。
基于特性的模块结构(每个域一个模块)是组织Nest应用以实现可扩展性和可维护性的标准方式。
模块与控制器和提供者一起,构成了NestJS的核心架构,使它们成为基础知识——掌握如何将应用程序结构化为模块,以及如何通过导入/导出在模块之间连接提供者,对于构建任何非平凡的NestJS应用程序都是必需的,这是一个值得早期充分理解的常见困惑点。