概述 - 模块

优质
小牛编辑
130浏览
2023-12-01

模块是具有 @Module() 装饰器的类。 @Module() 装饰器提供了元数据,Nest 用它来组织应用程序结构。

图1

每个 Nest 应用程序至少有一个模块,即根模块。根模块是 Nest 开始安排应用程序树的地方。事实上,根模块可能是应用程序中唯一的模块,特别是当应用程序很小时,但是对于大型程序来说这是没有意义的。在大多数情况下,您将拥有多个模块,每个模块都有一组紧密相关的功能。

所述 @Module() 装饰采用单个对象,其属性描述该模块:

providers由 Nest 注入器实例化的提供者,并且可以至少在整个模块中共享
controllers必须创建的一组控制器
imports导入模块所需的导入模块列表
exports此模块提供的提供者的子集, 并应在其他模块中使用

默认情况下, 模块封装提供者。这意味着无法插入既不是当前模块的直接部分,也不能从导入的模块导出提供者。

CatsModule

CatsControllerCatsService 属于同一个应用程序域。 应该将它们移动到功能模块 CatsModule

cats/cats.module.ts

  1. import { Module } from '@nestjs/common';
  2. import { CatsController } from './cats.controller';
  3. import { CatsService } from './cats.service';
  4. @Module({
  5. controllers: [CatsController],
  6. providers: [CatsService],
  7. })
  8. export class CatsModule {}

我已经创建了 cats.module.ts 文件,并把与这个模块相关的所有东西都移到了 cats 目录下。 我们需要做的最后一件事是将这个模块导入根模块 (ApplicationModule)

app.module.ts

  1. import { Module } from '@nestjs/common';
  2. import { CatsModule } from './cats/cats.module';
  3. @Module({
  4. imports: [CatsModule],
  5. })
  6. export class ApplicationModule {

现在 Nest 知道除了 ApplicationModule 之外,注册 CatsModule 也是非常重要的。 这就是我们现在的目录结构:

  1. src
  2. ├──cats
  3. │ ├──dto
  4. │ │ └──create-cat.dto.ts
  5. │ ├──interfaces
  6. │ │ └──cat.interface.ts
  7. │ ├─cats.service.ts
  8. │ ├─cats.controller.ts
  9. │ └──cats.module.ts
  10. ├──app.module.ts
  11. └──main.ts

共享模块

在 Nest 中,默认情况下,模块是单例,因此您可以毫不费力地在 2..* 模块之间共享同一个组件实例。

图1

实际上,每个模块都是一个共享模块。 一旦创建就被每个模块重复使用。 假设我们将在几个模块之间共享 CatsService 实例。 我们需要把 CatsService 放到 exports 数组中,如下所示:

cats.module.ts

  1. import { Module } from '@nestjs/common';
  2. import { CatsController } from './cats.controller';
  3. import { CatsService } from './cats.service';
  4. @Module({
  5. controllers: [CatsController],
  6. providers: [CatsService],
  7. exports: [CatsService]
  8. })
  9. export class CatsModule {}

现在,每个导入 CatsModule 的模块都可以访问该模块 ,并将CatsService与导入该模块的所有模块共享相同的实例。

模块重新导出

模块可以导出他们的提供者。 而且,他们可以再导出自己导入的模块。

  1. @Module({
  2. imports: [CommonModule],
  3. exports: [CommonModule],
  4. })
  5. export class CoreModule {}

依赖注入

模块类也可以注入提供者(例如,用于配置目的):

cats.module.ts

  1. import { Module } from '@nestjs/common';
  2. import { CatsController } from './cats.controller';
  3. import { CatsService } from './cats.service';
  4. @Module({
  5. controllers: [CatsController],
  6. providers: [CatsService],
  7. })
  8. export class CatsModule {
  9. constructor(private readonly catsService: CatsService) {}
  10. }

但是,由于循环依赖性,模块类不能由提供者注入。

全局模块

如果你不得不在任何地方导入相同的模块,那可能很烦人。在 Angular 中,提供者是在全局范围内注册的。一旦定义,他们到处可用。另一方面,Nest 封装了模块范围内的组件。您无法在其他地方使用模块提供者而不导入他们。但是有时候,你可能只想提供一组随时可用的东西 - 例如:helper,数据库连接等等。这就是为什幺你能够使模块成为全局模块。

  1. import { Module, Global } from '@nestjs/common';
  2. import { CatsController } from './cats.controller';
  3. import { CatsService } from './cats.service';
  4. @Global()
  5. @Module({
  6. controllers: [CatsController],
  7. providers: [CatsService],
  8. exports: [CatsService]
  9. })
  10. export class CatsModule {}

@Global 装饰器使模块成为全局作用域。 全局模块应该只注册一次,最好由根或核心模块注册。 之后,CatsService 组件将无处不在,但 CatsModule 不会被导入。

!> 使一切全局化并不是一个好的解决方案。 全局模块在这里减少了必要的样板数量。 imports 数组仍然是使模块 API 透明的最佳方式。

动态模块

Nest 模块系统带有一个称为动态模块的功能。 它使您能够毫不费力地创建可定制的模块。 让我们来看看 DatabaseModule

  1. import { Module, DynamicModule } from '@nestjs/common';
  2. import { createDatabaseProviders } from './database.providers';
  3. import { Connection } from './connection.provider';
  4. @Module({
  5. providers: [Connection],
  6. })
  7. export class DatabaseModule {
  8. static forRoot(entities = [], options?): DynamicModule {
  9. const providers = createDatabaseProviders(options, entities);
  10. return {
  11. module: DatabaseModule,
  12. providers: providers,
  13. exports: providers,
  14. };
  15. }
  16. }

此模块默认定义了 Connection 提供者,但另外 - 根据传递的 optionsentities - 创建一个提供者集合,例如存储库。 实际上,动态模块扩展了模块元数据。 当您需要动态注册组件时,这个实质特性非常有用。 然后你可以通过以下方式导入 DatabaseModule

  1. import { Module } from '@nestjs/common';
  2. import { DatabaseModule } from './database/database.module';
  3. import { User } from './users/entities/user.entity';
  4. @Module({
  5. imports: [
  6. DatabaseModule.forRoot([User]),
  7. ],
  8. })
  9. export class ApplicationModule {}

为了导出动态模块,可以省略函数调用部分:

  1. import { Module } from '@nestjs/common';
  2. import { DatabaseModule } from './database/database.module';
  3. import { User } from './users/entities/user.entity';
  4. @Module({
  5. imports: [
  6. DatabaseModule.forRoot([User]),
  7. ],
  8. exports: [DatabaseModule]
  9. })
  10. export class ApplicationModule {}

最后更新:

类似资料

  • SOFABoot 从 2.4.0 版本开始支持基于 Spring 上下文隔离的模块化开发能力。为了更好的理解 SOFABoot 模块化开发的概念,我们来区分几个常见的模块化形式: 基于代码组织上的模块化:这是最常见的形式,在开发期,将不同功能的代码放在不同 Java 工程下,在编译期被打进不同 jar 包,在运行期,所有 Java 类都在一个 classpath 下,没做任何隔离; 基于 Spri

  • 4.1.1 模块化设计概述 模块化设计的思想在许多行业中早已有之,并非计算机科学所独创。 例如,建筑行业很早就提出了模块化建筑概念,即在工厂里预制各种房屋模块构件,然 后运到项目现场组装成各种房屋。模块构件在工厂中预制,便于组织生产、提高效率、节省 材料、受环境影响小。模块组装时施工简便快速、灵活多样、清洁环保,盖房子就像儿童搭 建积木玩具一样。① 再如,船舶工业广泛采用模块化造船方法,即对最终产

  • 图表导出模块是指提供了将网页中图表导出为常见的图片格式(PNG、JPG、SVG) 或 PDF 文档的功能模块,另外导出模块还提供了直接在网页中打印图表的功能。 图表的导出默认是提交数据(SVG 字符串或图表配置 JSON 字符串 )到导出服务器上进行生成图片,另外我们提供的纯客户端导出的功能模块 offline-exporting.js 可以不需要导出服务器就可以完成这个操作。 导出功能需要额外的

  • 概述 国际化和本地化的目的就是让一个网站应用能做到根据用户语种和指定格式的不同而提供不同的内容。 Django 对文本翻译, 日期、时间和数字的格式化,以及时区提供了完善的支持。 实际上,Django做了两件事: 由开发者和模板作者指定应用的哪些部分应该翻译,或是根据本地语种和文化进行相应的格式化。 根据用户的偏好设置,使用钩子将web应用本地化。 很显然,翻译取决于用户所选语言,而格式化通常取决

  • 虽然Django 满满的便捷性让Web 开发人员活得轻松一些,但是如果不能轻松地部署你的网站,这些工具还是没有什么用处。Django 起初,易于部署就是一个主要的目标。有许多优秀的方法可以轻松地来部署Django: 如何使用WSGI 部署 部署的检查清单 FastCGI 的支持已经废弃并将在Django 1.9 中删除。 如何使用FastCGI、SCGI 和AJP 部署Django 如果你是部署D

  • 本书概述 进程的概念大家都很熟悉,但你是否能准确说出僵尸进程的含义呢?还有 COW(Copy On Write)、Flock(File Lock)、Epoll 和 Namespace 的概念又是否了解过呢? 本书汇集了进程方方面面的基础知识,加上编程实例,保证阅读后能自如地回答以上问题,在项目开发中对进程的优化也有更深的理解。 本书架构 本书按循序渐进的方式介绍进程的基础概念和拓展知识,主要涵盖以