iT邦幫忙

2021 iThome 鐵人賽

DAY 2
0
Modern Web

NestJS 帶你飛!系列 第 2

[NestJS 帶你飛!] DAY02 - Hello NestJS

本系列文已出版成書「NestJS 基礎必學實務指南:使用強大且易擴展的 Node.js 框架打造網頁應用程式」,感謝 iT 邦幫忙與博碩文化的協助。如果對 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,將大幅加速開發時間!


上一篇
[NestJS 帶你飛!] DAY01 - 簡介
下一篇
[NestJS 帶你飛!] DAY03 - Controller (上)
系列文
NestJS 帶你飛!32
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言