[NestJS 带你飞!] DAY02 - Hello NestJS

Nest 基本概念

Nest 采用模组化设计,将各个不同的功能区块打包成 模组 (Module),而 Module 必定有 一个以上,并且是以 树状结构 发散出去,最顶部的 Module 称为 根模组 (Root Module),其概念如下:
https://ithelp.ithome.com.tw/upload/images/20210302/20119338Qs3P92SDp6.png

而一个 有路由机制 的 Module 会带有 控制器 (Controller)服务 (Service),它们之间的关系如下:
https://ithelp.ithome.com.tw/upload/images/20210303/20119338k0YJe9Uv2Y.png

从图中可以看出 Controller 与 Service 透过 Module 建立关系後,即可将 Service 注入 (Inject) 到 Controller 中使用,这样的好处是可以职责分离,把处理请求的操作交给 Controller,把处理逻辑的部分交给 Service,这样说明有点太抽象了,那来点实际流程吧:

  1. 使用者向 Nest App 发出 Http 请求。
  2. 由 Controller 接收请求。
  3. 透过注入 Service 来调用里面的方法,进而处理背後的逻辑。
  4. 由 Service 返回值,Controller 将结果回传给使用者。

用现实生活中的例子来说明 Nest 整体概念的话,Nest App 就像一间有多国料理的餐厅,该餐厅规划每种国家的料理即一个区块,每个区块都有负责的外场服务生,而这个区块即为 Module,Controller 就是外场服务生,而 Service 则是内场人员,当客人走进餐厅时,先依照想吃的异国料理来安排座位,外场服务生协助客人点餐并将订单送至内场,内场人员开始针对客人的订单做料理,当餐点做好了之後,再请外场服务生送到客人面前:
https://ithelp.ithome.com.tw/upload/images/20210313/20119338f25enATx2G.png

现在对於 Nest 应该有些概念了,那就来看怎麽建置第一个 Nest App 吧!

安装 NestCLI

Nest 官方设计了一套 CLI 来帮助各位开发者们加速开发,可以透过 NestCLI 自动产生程序码骨架,这样一来便可以大幅降低「相同操作重复做」的次数,非常贴心。那要如何安装呢?只需要透过 npm 进行全域安装即可,在终端机输入下方指令:

$ npm install -g @nestjs/cli

安装完以後就可以透过终端机使用 NestCLI 了,查看有哪些指令可以使用:

$ nest --help

https://ithelp.ithome.com.tw/upload/images/20210226/20119338rBCCIh8c6l.png

建置 App

透过 NestCLI 的 new 指令来快速建立 App:

提醒:注意终端机当前位於资料夹何处,建议透过 cd 指令移动到想要的位置。

$ nest new <APP_NAME>

此时会建立一些 App 的骨架,并询问要使用哪种套件管理程序:
https://ithelp.ithome.com.tw/upload/images/20210226/20119338Iwr5Dtr0il.png

提醒:这里可以根据个人喜好选择,笔者这边选 npm。

等程序跑完後,就来执行看看吧:

$ cd <APP_NAME>
$ npm start

Nest 预设是在 3000 port,从浏览器网址列输入 http://localhost:3000 来看架设结果:
https://ithelp.ithome.com.tw/upload/images/20210226/201193388OtXc1IebQ.png

资料夹结构

透过 NestCLI 建置的专案资料夹结构如下:

.
├─ dist
├─ node_modules
├─ src
|  ├─ app.controller.ts
|  ├─ app.controller.spec.ts
|  ├─ app.module.ts
|  ├─ app.service.ts
|  └─ main.ts
├─ test
|  ├─ app.e2e-spec.ts
|  └─ jest-e2e.json
├─ .eslintrc.js
├─ .gitignore
├─ .prettierrc
├─ nest-cli.json
├─ package.json
├─ package-lock.json
├─ tsconfig.json
├─ tsconfig.build.json
└─ README.md
  • dist:TypeScript 编译完後会产生 JavaScript 档案,而那些 JavaScript 档就是放在这边。
  • node_modules:依赖的套件都会放在这里,也就是执行 npm install <PACKAGE> 所安装的档案。
  • src:专案程序码放置处,也是指定要编译的资料夹。
  • test:测试用的资料夹。
  • .eslintrc.jsESLint 的设定档,主要是用来规范 coding style。
  • .gitignore:用来避免将不必要或是敏感资讯写入 git 中的设定档。
  • .prettierrcPrettier 的设定档,主要是用来格式化程序码。
  • nest-cli.json:NestCLI 的设定档。
  • package.json:记录该专案的资讯,如:依赖的套件版本号、脚本快捷等。
  • package-lock.json:记录依赖套件的依赖套件版本号。
  • tsconfig.json:TypeScript 设定档。
  • tsconfig.build.json:TypeScript 编译设定档,为 tsconfig.json 的延伸。

程序码解析

注意:这边会简单带过,後续会再针对各功能做详细的说明。

src 资料夹中,撇除测试用的 app.controller.spec.ts 外,会看到 main.tsapp.module.tsapp.controller.ts以及app.service.ts

载入点

main.ts 为载入点,程序码如下:

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

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

以非同步的 bootstrap 函式做为载入函式,透过 NestFactory.create(AppModule) 产生一个 Nest App 的实例 (Instance),并透过呼叫该实例的 listen(PORT) 将其架设起来。

提醒:PORT 即为要使用的 port,预设为 3000。

根模组

app.module.ts 为根模组,程序码如下:

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

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

在 Nest 中,大部分的元件都是使用 装饰器 (Decorator) 的方式来提供 元数据 (Metadata),可以看到定义了一个名为 AppModuleclass,透过装饰器将其变成 Nest 的 Module,并在这里定义该模组的 Controller 与 Service。

app.controller.ts是注册於根模组底下的 Controller, 不是必要项目。程序码如下:

import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get()
  getHello(): string {
    return this.appService.getHello();
  }
}

可以看到也是使用带有装饰器的 class,比较特别的是里面的方法 (Method) 也使用了装饰器,来定义该方法是使用哪种方式进行触发等。另外,可以在 constructor 中看见 appService 的参数,这是使用 依赖注入(Dependency Injection) 的方式将 AppService 注入到 AppController 中。

app.service.ts是注册於根模组底下的 Service,不是必要项目。程序码如下:

import { Injectable } from '@nestjs/common';

@Injectable()
export class AppService {
  getHello(): string {
    return 'Hello World!';
  }
}

与 Module、Controller 有些不同,Service 所使用的装饰器为 Injectable,原因是 Service 属於 抽象 的概念,在 Nest 中有许多抽象概念可以使用 Injectable 来实作,他们统一归类为 Provider

小结

Nest 提供高度的模组化设计,只要把 Controller 与 Service 定义好并放入对应的 Module 里,再像拼拼图一样把相关模组各自关联起来,就可以建立起易维护、低耦合、易扩展的 Node.js 後端应用,如果再使用官方设计的 NestCLI,将大幅加速开发时间!


<<:  Flutter体验 Day 9-Button组件

>>:  Day02-Vue.js的实体

[Day12]ISO 27001 标准:验证范围

其实 ISO 系统都是通用的,从 ISO 9001、 ISO 14001、 ISO 50001、IS...

为了转生而点技能-JavaScript,day8(浅笔记-物件之浅层复制与深层复制

物件复制: 浅层复制(shallow copy):仅被复制的一方能保留第一层的物件之值,但是当复制方...

变数命名的善意

这是一小段泡沫排序法的程序码,可是在说什麽呢?你可以试着阅读他,但千万不要勉强自己。 int mai...

[Day 28] - Gatsby feat. EC ( 下 )

昨天我们完成了一个基本的购物流程,但程序码内有着不安全的问题,今天我们要用 .env 的形式来规避这...

Day 08 设置关键字的基本 sense

在设置关键字的时候,有些 NG 行为是不能犯的,今天就想跟大家聊聊,当我们在揣测消费者的心思时,哪些...