Nest.js 實踐總結(jié)分享
大廠技術(shù) 高級前端 Node進階
點擊上方 程序員成長指北,關(guān)注公眾號
回復1,加入高級Node交流群
Nest.js 是一個現(xiàn)代的企業(yè)級 Node.js Web 框架,最近在使用 Nest.js 實踐一些項目的總結(jié)了一些使用心得,也從中學到了很多東西,在這里總結(jié)下來和大家分享。
1. API 設(shè)置全局前綴
為 API 設(shè)置一個全局前綴可以區(qū)分接口版本,如通常會用 /api/v1 作為的 API 端點的前綴。為什么我們需要前綴?好的 API 在設(shè)計時要考慮到向后的兼容性。當增強或增加一個 API 時,我們應(yīng)該確保已經(jīng)線上使用到該 API 的業(yè)務(wù)不受影響。簡而言之,API 前綴是為了向后兼容。

2. 模塊劃分
Nest.js 是以模塊化結(jié)構(gòu)為基礎(chǔ)的,服務(wù)端應(yīng)用應(yīng)該按功能職責被劃分為幾個部分,通常情況下,將你的目錄結(jié)構(gòu)應(yīng)該按模塊劃分而不是按類型分成文件夾。以下是按類型劃分文件夾(不推薦):

以下是按模塊劃分文件夾(推薦):
對于 Nest.js,模塊是一個包含 .module.ts 文件的文件夾,其中包含一個 @Module({}) 裝飾器。但并非每個文件夾都需要有一個 .module.ts 文件。例如,你可以創(chuàng)建一個文件夾名為 utils 來存儲你的工具函數(shù)或 JSON 文件。通過將文件組織到模塊文件夾中,會變得清晰,并且可以避免很多錯誤。此外,如果你不遵守此原則,Nest.js 可能會在構(gòu)建過程中崩潰。
3. 使用 DTOs
DTO = 數(shù)據(jù)傳輸對象。Dtos 就像接口,目標是傳輸數(shù)據(jù)并驗證它,主要用于路由器 / 控制器。你可以通過使用它們來簡化 API 主體和查詢驗證邏輯。例如,下面的 AuthDto 自動將用戶電子郵件和密碼映射到對象 DTO 以強制驗證。

上面的例子是期望密碼超過 5 個字符,你可以將 dtos 與 class-validator 包配對以自動拋出錯誤。
4. 應(yīng)該使用 Data Mapper/Repository 模式,而不是 Active Record
如果你正在使用 PostgreSQL 或 MySQL 等關(guān)系數(shù)據(jù)庫,那么請使用 TypeOrm,它是 Typescript 最強大的 ORM 之一。TypeOrm 可以使用兩種模式,一種是由 ruby on rails 推廣的活動記錄模式,另一種是使用存儲庫的數(shù)據(jù)映射器模式。
使用 Active Record 方法,可以在模型本身內(nèi)定義所有查詢方法,并使用模型方法保存、刪除和加載對象。下面是使用 Active Record 模式的樣子:
const user = new UserEntity();
user.name = "Vladimir";
user.job = "programmer";
await user.save();
使用 Data Mapper 方法,你可以在稱為 “存儲庫” 的單獨類中定義所有查詢方法,并使用存儲庫保存、刪除和加載對象:
const user = this.userRepository.create();
user.name = "Vladimir";
user.job = "programmer";
await this.userRepository.save(user);
雖然活動記錄乍一看似乎更好,但它違背了 Nest.js 提供的模塊化,因為活動記錄與全局實體一起工作,而數(shù)據(jù)映射器需要在使用它們之前將實體注入每個模塊。數(shù)據(jù)映射器可能看起來有點冗長,但它是中 / 大型項目的更好解決方案。它也非常適合測試,因為它適用于依賴注入!
5. 應(yīng)該使用相對路徑,而不是絕對路徑
你可以使用絕對路徑或相對路徑導入 es6 模塊。但在 Nest.js 在開發(fā)中使用絕對路徑,再構(gòu)建應(yīng)用時它會崩潰。
// relative imports
import { SecurityService } from '../security/security.service';
import { CommentService } from '../comment/comment.service';
// absolute imports
import { SecurityService } from 'src/security/security.service';
import { CommentService } from 'src/comment/comment.service';
6. 使用 Exclude 來隱藏不必要的數(shù)據(jù)
使用過濾器從數(shù)據(jù)庫中獲取的數(shù)據(jù)是很常見的。過濾器的整個目標是刪除或格式化來自數(shù)據(jù)庫的數(shù)據(jù)。這會導致很多垃圾邏輯,使代碼變得更冗余。如果是需要隱藏某些字段,可以使用 @Exclude () 裝飾器。
import { Exclude } from 'class-transformer';
export class UserEntity {
id: number;
firstName: string;
lastName: string;
@Exclude()
password: string;
constructor(partial: Partial<UserEntity>) {
Object.assign(this, partial);
}
}
7. 使用實體的 getter 方法
一些通用的邏輯可以作為屬性直接添加到你的實體邏輯里。最常見的用例與密碼散列和獲取全名有關(guān),這時可以使用 getter 方法,但是要注意不要過度使用,避免給實體承擔大量的業(yè)務(wù)邏輯。
import { Exclude } from 'class-transformer';
export class UserEntity {
id: number;
firstName: string;
lastName: string;
get fullName() {
return this.firstName + " " + this.lastName;
}
}8. 使用集中命名導出你可以從同一個文件夾中導入所有類,而不是從不同的文件中導入你的類。如有以下目錄:

// index.ts
export * from './createPost.dto';
export * from './editPost.dto';
export * from './editPostCategory.dto';
export * from './editPostStatus.dto';
// 推薦
import { CreatePostDto, EditPostDto } from './dto';
// 不推薦
import { CreatePostDto } from './dto/createPost.dto';
import { EditPostDto } from './dto/editPost.dto';我組建了一個氛圍特別好的 Node.js 社群,里面有很多 Node.js小伙伴,如果你對Node.js學習感興趣的話(后續(xù)有計劃也可以),我們可以一起進行Node.js相關(guān)的交流、學習、共建。下方加 考拉 好友回復「Node」即可。

“分享、點贊、在看” 支持一波 
