Nestjs 基礎介紹

janlin002
11 min readDec 6, 2023
Photo by Vignesh Jayaprakash on Unsplash

這篇文章主要會簡單介紹 Nest 這個後端框架,有任何錯誤都歡迎留言給我,那我們話不多說進入今天的文章

適合什麼人閱讀?

想轉後端或是想瞭解基本後端知識,不推薦給已經是後端或是資深後端工程師

什麼是 Nest

參考自官方文件的介紹:

Nest 是一個用於建立高效、可擴展的 Node.js 伺服器端應用程式的框架。可以使用 TypeScript 建構並完全支援 TypeScript(還是可以使用 JavaScript),並結合了 OOP、FP 和 FRP 的元素。

Nest 的底層可以選擇任何 HTTP 伺服器框架,如 Express(預設),當然也可以使用 Fastify

Nest 的基本流程

上圖是基本的 Nest 流程,當使用者(前端)發出一個請求後,會先找到對應的 Module,並在 Module 裡面找到對應的 controller,controller 會找到對應的 service,service 會透過定義的 function 去跟 DB 拿去資料

舉個生活中的例子:

今天有一個活動的案子想找接案公司(Module)幫忙寫畫面做宣傳,他會去找有在接案的公司去做洽談,不會去找銀行(Module)或是博弈公司(Module)做洽談,當接案公司接到任務以後,會去找研發部(controller)做細節的討論,而不會去找人事部(controller),研發部接收到任務以後,主管會去團隊裡面找合適人選(service)做這部分的開發,以上就是一個簡單的流程

是不是感覺沒聽懂?沒關係我們後面會在介紹一次,先有個概念即可

Nest Request LifeCycle

https://slides.com/yariv-gilad/nest-js-request-lifecycle

上圖是基本的 Nest Request LifeCycle,特別要注意的是 如果在 1 2 3 4 階段,就被擋下來的話,requests 就不會進到 controller

Middleware

https://docs.nestjs.com/middleware

Middleware 就是一個在 route handler 之前的 function,他能夠更改 requests 跟 response 的結構,又或是可以做客製化的重導向(redirect)

創立 Middleware

nest g middleware [你的路徑]

// ex. nest g middleware auth/middleware

Nest 會自動幫你在對應的路徑下建立一個 Middleware 的資料夾,並且裡面已經有基本的 Middleware 程式碼,我們在裡面加個 console 試試看

然後回到 app.module.ts 引入我們的 Middleware ,告訴 Nest 在什麼樣的路由或是遇到什麼樣的請求(http method)時,我們需要先執行 Middleware

上方程式碼意思就是:當我們執行路由/時 ,就會先觸發LoggerMiddleware

上圖我們開啟 Postman 對路由 / 發起 Get 請求,會看到 terminal 最下方印出了 Middleware success…

現在測試將 Middleware 監聽的路徑改成 /1

並且在 controller 裡面新增一比 /1 對應的方法

同時測試 //1 會發現只有 /1 會印出 Middleware success…

middleware 官網連結

Guards

https://docs.nestjs.com/guards

Guards 的中文就是 衛兵 的意思,Guards 必須實施(implement) CanActivate interface,當 return 為 true 時,才會跑到下一階段,反之,就會 response error

創立 Guards

nest g guard [你的路徑]

// nest g guard auth/guards

為了方便等一下 Demo 我直接把 return 改成 false

如果要綁定 Guards 會需要使用到 UseGuards() 這個裝飾器(decorator),需要特別注意的是 Guards 是有優先順序的

@UseGuards(Guard1, Guard2)
@Controller('cats')
export class CatsController {
constructor(private catsService: CatsService) {}

@UseGuards(Guard3)
@Get()
getCats(): Cats[] {
return this.catsService.getCats();
}
}

上方程式碼取自官網,執行順序為: Guard1 > Guard2 > Guard3

UseGuards() 加到剛剛的範例中

然後一樣用 Postman 跑一次,會發現因為我們在 AuthGuard 中沒有寫任何判斷,一率回傳 false ,所以我們會得到一個 403 error

Interceptors

待補…

Pipes

PipeNestJS 裡面有兩個比較常見的使用情境, 1. 轉型 2. 驗證。

這邊我們不手寫一個 Pipe,直接下載現有的套件

npm i class-transformer class-validator

class-transformer

class-transformer 可以幫我們做轉型的部分,例如:我可以將一個 Object 直接轉換成 class

https://github.com/typestack/class-transformer#enforcing-type-safe-instance

class-validator

class-validator 使用方法很簡單

透過 IsNotEmpty 可以驗證 titledescription 必須要有值

Pipe 官網連結

Bonus — Exceptions Filter

講完 Pipe 以後,我們需要接著講 Exceptions Filter,原因是因為如果驗證出錯誤時,我們應該要給一個好理解的錯誤訊息,讓前端的同事好去處理

這邊稍微講解一下 HttpException ,先看個原始碼

可以看到 constructor 接收三個參數 response、 status、 options

response 就是回傳的錯誤訊息、status 是狀態碼、options 是客製化的部分

其中 status 需要特別說一下,Nest 其實有寫一套常見的狀態碼,有興趣可以去原始碼裡面看

除了可以自己寫一個 HttpException ,Nest 也把常見的錯誤包裝成 HTTP exceptions,有興趣可以去官網裡面找找看,或是去原始碼裡面看看

實作 CRUD (環境建設)

這次的 CRUD 不會包含任何 DB 相關的東西,之後會再寫一篇介紹如何串接 DB 實作一個登入系統

$ npm install -g @nestjs/cli
$ nest new project-name

這邊的 CRUD 我預設會用到的資料格式為下,模擬一個使用者的資料庫

[
{
name: 'david',
id: '1',
},
{
name: 'bill',
id: '2',
},
];

擁有預設格式以後,我們可以寫一個 DTO 去驗證他

DTO 全名 Data Transfer Object(資料傳輸物件)可以拿來過濾資料格式

src/dto/user.dto.ts

CREATE

步驟如下: 先從用戶端取得新的使用者,然後加入到我們的 user 中

左: controller 右 :service

拿 Postman 測試,會發現多了一個 Amy 的使用者

READ

READ 的部分,分成兩個部分: 1. 取得全部使用者 2. 透過 id 取得唯一使用者

取得全部使用者

左: controller 右 :service

透過 id 取得唯一使用者

左: controller 右 :service

這邊要稍微講一下,user 的 id 可以透過任何方式取得,不一定要透過 param 的方式

UPDATE

左: controller 右 :service

DELETE

左: controller 右 :service

--

--