【Nest系列】4.Nest 核心概念:模块

简介: 本文介绍了经典的 MVC 分层架构,以及各层和 Nest 应用的对照。然后讲解了 Nest 模块的具体定义,使用 @Module 装饰器声明的类,就是模块。@Module() 接收一些信息来描述此模块的构成,主要是声明此模块所依赖的其他模块,控制器,提供者,和要导出的供其他模块所使用的部分。

前言

上篇文章《NestJS 扫盲篇:TypeScript 类和装饰器》中,我们介绍了 TS 中类和装饰器的用法。Nest 应用基于面向对象和面向切面开发,大量应用了类和装饰器。所以掌握这两个语法,再去学习 Nest,是一个很有必要的基础。

MVC 分层架构

在本系列更文的第一篇,较为细致的分析了 Hello World 的示例代码。它只有一个根模块,也就是 App 模块,然后使用控制器接收请求,再调用服务完成具体业务的处理,最后将结果响应给客户端,如下图所示:

nest 应用逻辑流程

这其实就是一个经典的 MVC 分层架构:

  • Model:业务模型层或者数据模型层,用来处理业务,是整个分层架构中最复杂的部分
  • View:视图层,就是用户界面
  • Controller:控制器层,解耦视图层和模型层,职责也很明确和简单,在 Web 应用中就是接收用户请求,调用 Model 层处理后将结果响应给视图层

image-20230118164928460

在 Nest 示例代码中,主要涉及到的概念有:

  • app.controller.ts:App 控制器,对应的 MVC 中的 C 层。
  • app.service.ts:App 服务,对应 MVC 中的 M 层。
  • app.module.ts:App 模块,它负责将控制器和服务组织到一起。

你会发现,为啥没看到 View 呢?因为在 MVC 盛行的年代,前后端都是耦合在一起的,拿 Java 来说,View 层就是 JSP 。对于现在前后端分离的项目来说,View 层就是 React,Vue 等框架写的可以独立部署的页面应用。

写一个 Nest 应用,最基本的就是写模块,控制器和服务。下面就是对这三个概念的介绍。

模块

如何理解模块

首先要区分 Nest 模块和平时前端开发中经常提及的“前端模块化”中的模块。后者是属于 JS 语言层面的概念,是一种语法,比如标准的ES Module 规范中的模块就是使用 export 导出,使用 import 导入,还有 CommonJS 规范使用 module.exports 导出,使用 require 导入。

而前者是 Nest 应用层面上的概念,跟它对应的应该是前端组件化中的组件,比如 Vue 开发就是用组件组成一个完整的页面。Nest 使用模块来组织应用的结构,比如一个博客系统中,可以分为用户模块,文章模块等。

每个 Nest 应用都有一个根模块,按照约定大于配置的思想,都会定义在 app.module.ts 文件中,是一个名为 AppModule 的类。其他的模块都是它的子模块,都会被它引入,组成一个完整的应用。

模块的代码表示

Nest 模块在定义上是使用装饰器 @Module() 装饰的类,使用元数据描述一些模块的属性,用以组织该模块。

所谓元数据,就是描述数据的数据。简单理解的话,装饰器工厂接受的参数就是元数据,它们不直接参与到你的编码中,它们用来描述这个模块的组成。@Module() 装饰器接受一个描述模块属性的对象,有四个属性:

属性 描述
providers 声明一组提供者,由 Nest 容器负责实例化,在当前模块中共享
controllers 声明一组控制器,模块必选的属性
imports 导入模块的列表,这些模块导出了此模块中所需提供者
exports 由本模块提供并应在其他模块中可用的提供者的子集

看下示例,AppModule 类使用 @Module() 装饰,所以它就是一个 Nest 模块了。看下装饰器的类型声明,按住 Ctrl 键,点击 @Moudle 就可以跳转:

export declare function Module(metadata: ModuleMetadata): ClassDecorator;

可以看到,装饰器其实一个函数。而@Module是一个装饰器工厂,接收的参数就是模块元数据对象,装饰器工厂返回一个类装饰器。

import {
   
    Module } from '@nestjs/common';
import {
   
    AppController } from './app.controller';
import {
   
    AppService } from './app.service';
import {
   
    UserModule } from './user/user.module';

@Module({
   
   
  // 该模块所需的其他模块。根模块需要将所有模块都导入,才能让应用正常运行。
  // 有的子模块可能依赖另一个子模块,也要通过此选项导入。
  // 一个更直观的例子,后面要用到ORM框架比如 TypeOrm,Mongoose,它们就要在此导入再使用。
  imports: [UserModule],

  // 模块装饰器的必填项。因为要用它处理请求,没有它,应用接收不到请求也就没有存在的意义了。
  controllers: [AppController],

  // 模块的提供者,就是能提供能力,供模块的其他部分使用。服务就是最常用的一种提供者.它可以写核心逻辑,操作数据库等等,然后在控制器中被使用。
  providers: [AppService],
})
export class AppModule {
   
   }

模块的组织

模块在使用装饰器声明时,需要传入一些元数据信息,比如它的控制器和提供者。

在模块的目录组织上,一个良好的风格是将该模块相关的资源放到同一个文件夹中管理,比如用户模块有控制器,服务,还有数据层的 dto 文件等等,就可以放到 user 目录下:

src
├──user
│    ├──dto
│    │   └──create-user.dto.ts
│    ├──interfaces
│    │     └──user.interface.ts 
│    ├─user.service.ts
│    ├─user.controller.ts
│    └──user.module.ts
├──app.module.ts
└──main.ts

然后,新建的目录一定要在 app.module.ts 中引入:

import {
   
    Module } from '@nestjs/common';
import {
   
    AppController } from './app.controller';
import {
   
    AppService } from './app.service';
import {
   
    UserModule } from './user/user.module';

@Module({
   
   
  imports: [UserModule],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {
   
   }

在《Nest 应用目录结构和脚手架命令》中介绍了常用的脚手架命令,要新建一个模块,可以直接使用 nest g module

$ nest g module user

CLI 会自动在 src 目录下新建 user 目录和对应的模块文件,之后再使用命名创建对应的控制器和服务等内容。

使用脚手架命令创建的好处是省时省力,能自动在根模块 AppModule 中注册,能自动处理控制器和服务之间的关系。

总结

本文介绍了经典的 MVC 分层架构,以及各层和 Nest 应用的对照。然后讲解了 Nest 模块的具体定义,使用 @Module 装饰器声明的类,就是模块。@Module() 接收一些信息来描述此模块的构成,主要是声明此模块所依赖的其他模块,控制器,提供者,和要导出的供其他模块所使用的部分。

下篇文章会继续讲解 Nest 控制器,它主要使用若干个装饰器用来处理请求,调用服务,最后响应数据。

感谢阅读,再会!

目录
相关文章
|
存储 资源调度 数据库
Vercel 部署 NestJS应用
Vercel 部署 NestJS应用
879 0
|
3月前
|
前端开发 NoSQL JavaScript
基于 React + Nest 全栈开发的后台系统
这篇文章介绍了一个基于React+Nest全栈开发的后台系统XmwAdmin。项目包括前端和后端技术栈,线上预览地址和登录信息。作者推荐使用pnpm包管理工具和特定的环境依赖。文章提供了项目的运行和编译代码,以及各个功能模块的介绍。还包括演示图和项目活动以及总结部分。数据库下载链接也提供了,该项目已完成后台的核心功能。
基于 React + Nest 全栈开发的后台系统
|
2月前
|
JavaScript Shell 开发者
怎样使用Nest.js快速构建高效Node.js应用?
这篇博客介绍了Nest.js,一个基于TypeScript的Node.js框架,适用于构建可维护和可扩展的服务器端应用。文章引导读者快速入门,包括安装Node.js和Nest.js CLI,创建新项目,安装依赖以及启动开发服务器。通过访问`http://localhost:3000`,可以看到"Hello World!",证明应用已成功运行。Nest.js因其模块化架构和强大的功能,成为现代Web开发的热门选择。
|
3月前
|
前端开发
10_nest.js 提供者
10_nest.js 提供者
43 3
|
3月前
|
存储 SQL 前端开发
React&Nest.js社区平台(四)——✏️文章发布与管理实战
React&Nest.js社区平台(四)——✏️文章发布与管理实战
|
3月前
11_nest.js模块
11_nest.js模块
35 0
|
12月前
|
SQL JavaScript 关系型数据库
号称下一代Node.js,Typescript以及go的orm的prisma 浅谈如何在nest.js中使用
号称下一代Node.js,Typescript以及go的orm的prisma 浅谈如何在nest.js中使用
号称下一代Node.js,Typescript以及go的orm的prisma 浅谈如何在nest.js中使用
|
12月前
|
JSON 前端开发 JavaScript
【Nest系列】5. Nest 核心概念:控制器
上篇文章《Nest 核心概念:模块》中,我们介绍了 Nest 的模块,它是组织 Nest 应用的基本结构。Nest 应用接收请求,交给控制器处理请求,控制器中又调用服务,完成具体的业务逻辑,最后将结果响应给客户端。 本文会详细介绍控制器的用法,其实就是通过各类装饰器处理不同的请求和传参。
176 0
【Nest系列】5. Nest 核心概念:控制器
|
12月前
|
SQL JavaScript 关系型数据库
保姆级教程——号称下一代Node.js,Typescript的orm的prisma 如何在nest.js中使用
保姆级教程——号称下一代Node.js,Typescript的orm的prisma 如何在nest.js中使用
|
存储 缓存 中间件
快速入门nest.js(8/10)--其他更多模块
嵌套构建块可以是: 全局范围 控制器范围 方法范围 参数范围<仅适用于管道>
122 0