好香的框架! NestJS Zero to Hero 線上課程學習筆記
簡介
Nest.js 是一個架構、語法都與 Angular 非常相像的後端框架
使用 TypeScript 為開發語言
也是以 Express 框架為底層的 Node.js 框架 (我框架你的框架 !?!?!)
在不認識它之前
可以用 Angular 版的 Node.js
或是 TypeScript 版的 Express
來想像
日前剛好看到社團有人分享 Udemy 上的 Nest.js 課程限時免費中
https://softnshare.com/nestjs-zero-to-hero/
之前就對這個框架很有興趣,趁著有免費的優質課程,就花了兩三天看完了
在學的過程中,我是覺得非常興奮的,因為它真的跟 Angular 太像了
對於已經會 NG 的開發者,我強烈推薦大家可以試試看 Nest.js ,非常好上手
甚至本來就也會用 Node.js ,那真的幾乎沒什麼學習成本
又可以享受新框架的種種優點
Nestjs Framework幾個特點:
- Base On Express 框架和 socket.io 套件。
- 語法風格類似 Angular,也有人覺得類似 Java Spring ,使用了許多裝飾器語法。
- 依賴注入( Dependency Injection ), Nestjs 大量使用依賴注入,建議使用此作法。
- Exception layer ,可以做更多的 exception 處理。
- Guards 作為路由警衛,處理訪問權限。
- Interceptors 攔截器機制。
- Unit Test & E2E Test。
想要看更多關於 Nest.js 的簡介
可以去看這篇 Nestjs framework 30天初探:Day01 攻略行前說明
本文主要是針對線上課程 NestJS Zero to Hero - Modern TypeScript Back-end Development
所作的筆記內容
記錄一些觀念性的東西,實作部分可以到原線上課程學習
截至目前有近十萬名學生,評價也有 4.7 顆星,平時售價也平易近人
可以參考看看
Module
- 每個應用至少有一個模組,也就是根模組 (root module)
- 模組化是很有效組織元件的方式
- 每個模組放在自己獨立的資料夾是一個好習慣
- 模組是一種單例模式 (singleton) 的實踐,因而能夠匯出、匯入多個其他模組
- 定義一個模組使用裝飾器
@Module
來標記 @Module
擁有的屬性:- providers: 依賴注入,註冊服務提供者
- controllers: 實例化 controllers
- exports: 匯出其他 modules
- imports: 匯入其他 modules
- 例如下面的結構可以用這樣的程式碼表示:
Controllers
- 處理請求 (requests) ,並且回應 (response)
- 是一個特定的路徑 (例如:
/tasks
處理 task 的資源) - 包含 handlers,處理 endpoints 以及 request methods (GET, POST, DELETE…)
- 受益於依賴注入 (dependency injection) ,在同一個模組中consume providers within the same module
- 定義一個模組使用裝飾器
@Controller
來標記@Controller
接收字串型別的參數,用來表示要處理的路徑- 例如: @Controller(‘tasks’)
Handler
- Handler 是 controller 內的方法 (method)
- 支援使用這類型裝飾器
- @Get()
- @Post()
- @Delete()
- …
- 處理流程為:
- 接收到 HTTP 請求 (request)
- 請求經由路由 (route) 到 controller,接著呼叫並且傳入參數給 handler
- handler 開始處理請求,例如: 從資料庫取得資料、運算…等等
- handler 回傳結果,回傳結果可以是任何型別,包括
例外
(exception), Nest.JS 會幫我們包裝處理給客戶端
Providers
- 如果有標記為
@Injectable
,就可以被注入 - 可以是純值、類別、同步/非同步的設計
- providers 提供給 module 使用
- 可以被模組匯出,再讓其他模組做匯入、引入
Service
- Service 是一種 providers ,但不是所有 providers 都屬於 services
- 是軟體開發中一種通用的概念,不只用於 NestJS, JavaScirpt 或後端開發
- 當被
@Injectable()
包起來提供給其他模組時,是一種單例模式(singleton),意指相同的實例 (instance) 會在應用程式中被不同的地方使用 - 是主要的商業邏輯來源,例如: controller 會呼叫 service 來驗證資料、對資料庫新增資料、回傳結果
NestJS 的依賴注入
- 任何一個元件都可以注入 provider ,只要它有被標記為可被注入的話 (
@Injectable
) - 我們會在元件的 class 的建構子 (constructor) 裡面定義,Nest.JS 會幫我們處理、注入,使得它變成 class 內的一種屬性 (property),供我們使用。
DTOs
- Data Transfer Objects
- 是軟體開發的通用概念
- 幫助寫出更穩固的程式碼,而且可以用在 TypeScript 中
- DTO 沒有行為,除了 儲存、檢索 (retrieval) 、序列化、反序列化自己的資料
- 增加效能 (在小程式中微乎其微)
- 對資料驗證很有用
- DTO 不是一個 model 定義,他是定義特定情況的資料形狀,例如: 建立一個工作項目
- 可以用 interface 或 class 定義,但是建議用 class ,並且建立清楚的文件
- 原因是因為 interface 是屬於 TypseScript 的,所以在執行階段就不會被保留了。 class 則屬於 JavaScript,會在執行階段被保留。
- NestJS 在執行階段沒辦法參照 interface ,但可以參照到 class
- 範例:
- DTO 可以用在很多地方controllers, services, pipes,在驗證資料時也很實用
- DTO 不是強制的,就算不用也可以正常開發,但它可以使你更好維護與日後重構
Pipes
route handler 會先處理引數 (arguments) 上的 pipes 運算元,之後才呼叫 handler
可以用來做資料轉換或是資料驗證
可以回傳資料給 route handler ,不論是原始資料或是處理過的資料
可以丟出例外處理 (throw exceptions) ,被丟出的例外會由 NestJS 處理並且解析為一個錯誤的回應 (error response)
可以是非同步的
NestJS 裡有一些預設的 Pipes 在
@nestjs/common
module 裡面,
例如:- ValidationPipe 驗證物件是否符合 DTOs
- ParseIntPipe 引數預設型別是 string ,可以轉換成整數
自訂義 Pipe 時的實作:
- 是一個具有
@Injectable()
標記的 class - 必須實踐
PipeTransform
,並包含 transform() 方法,用來給 NestJS 呼叫 - transform() 接受兩個參數:
- value: 引數的值
- metadata (optional): 轉換處理中可能用到的標記
- 不論 transform() 回傳什麼值,都會傳到 route handler。例外處理將會傳給客戶端
- 可以被很多不同的方式消費 (consume)
- 是一個具有
handler-level pipes
所有參數都會經過 pipe 處理parameter-level pipes
只有特定的參數會被 pipe 處理global pipes
應用層的 pipe 會套用在所有請求上流程:
class-validator 提供很多檢查 class 的驗證檢查
裝飾器語法
- @Get()
- @Get(‘/:id’)
- @Post()
- @Patch(‘/:id/propertie’)
- @Query()
- @Body()
- @Body(‘key’)
- @Param(‘id’)
ORM
優點:
- 將資料模型 (data model) 寫在同一個地方,易於維護、減少重工
- 很多工項可以自動化: 資料庫處理、資料型別、資料關聯
- 不用寫 SQL 原生語法(易學難精),用你原本擅長的語言來寫
- 資料庫的抽象化,日後想要換資料庫時,比較方便
- 可以借用很多 OOP 的優點,例如: 繼承 (inheritance) 的架構很好被實踐
缺點
- 需要學習 ORM 的函式庫,不一定很容易
- 效能還行,但容易被忽視
- 容易忘記語法背後到底實際做了些什麼事情,可能造成一些維護上的問題
TypeORM 是用在 Node.js 的 ORM 函式庫,並且支援 TypeScript
兩種常見的 ORM 模式:
- Active Record
- Data Mapper
- https://orkhan.gitbook.io/typeorm/docs/active-record-data-mapper
Auth
- 透過 Validation 設定密碼規則 (例如: 包含大小寫、特殊字元、長度)
- 可以用 Bcrypt 套件來處理密碼加密的問題
- 雜湊 (hash) 函式可以使密碼被單向的加密
- 透過加上 salt 來避免暴力破解、彩虹表攻擊
- 介紹 JWT
- JWT 可以被所有人解碼,所以不應該存放機敏資料,例如: 密碼
- 適合用來做前端頁面的功能判斷,例如: 使用者有沒有權限看到這個按鈕
- JWT 的存活期限該該要設置成很短暫
- 用 裝飾器 @UseGuards,來做路由守衛
- 用 裝飾器 @UseInterceptors(),來做請求攔截、加工