這篇文章主要會簡單介紹 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
上圖是基本的 Nest Request LifeCycle,特別要注意的是 如果在 1 2 3 4 階段,就被擋下來的話,requests
就不會進到 controller
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…
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
Pipe
在 NestJS
裡面有兩個比較常見的使用情境, 1. 轉型 2. 驗證。
這邊我們不手寫一個 Pipe,直接下載現有的套件
npm i class-transformer class-validator
class-transformer
class-transformer 可以幫我們做轉型的部分,例如:我可以將一個 Object 直接轉換成 class
class-validator
class-validator 使用方法很簡單
透過 IsNotEmpty
可以驗證 title
跟 description
必須要有值
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(資料傳輸物件)可以拿來過濾資料格式
CREATE
步驟如下: 先從用戶端取得新的使用者,然後加入到我們的 user 中
拿 Postman 測試,會發現多了一個 Amy 的使用者
READ
READ 的部分,分成兩個部分: 1. 取得全部使用者 2. 透過 id 取得唯一使用者
取得全部使用者
透過 id 取得唯一使用者
這邊要稍微講一下,user 的 id 可以透過任何方式取得,不一定要透過 param
的方式
UPDATE
DELETE
總結
因為有寫過前端的關係,所以在寫 Nest 時,覺得還算好上手,畢竟都是 JavaScript ,下一篇應該會寫使用 Nest 建立一個登入系統(吧?
參考文章
https://blog.errorbaker.tw/posts/minw/nest-js-intro/
https://wdk-docs.github.io/nest-docs/fundamentals/lifecycle-events/#_2
https://www.kancloud.cn/juukee/nestjs/2671121
https://slides.com/yariv-gilad/nest-js-request-lifecycle
https://docs.nestjs.com/middleware
https://ithelp.ithome.com.tw/articles/10272385
https://blog.kevinyang.net/2019/05/07/nestjs-pipe/