在現代API開發中,實現API版本控制是不可或缺的設計模式,特別是當應用逐步擴展且不斷迭代時,良好的版本管理至關重要。本文將介紹如何在NestJS中使用 VersioningType.URI
來實現API的版本控制,並深入分析兩種控制器的版本設定方式,幫助開發者根據實際需求選擇最佳方案。
Step 1: 設定全域前綴詞(setGlobalPrefix)
首先,設定全域前綴詞是必要的。務必先設定 setGlobalPrefix
,再啟用版本控制,否則後續的版本控制將無法正確應用到API路徑。
// 設置全域的API前綴詞
const globalPrefix = 'api';
app.setGlobalPrefix(globalPrefix);
這行代碼會將所有API路徑統一設為/api
開頭,例如/api/v1/test/echo
。這樣可以讓API結構層次分明,並方便後續的維護和版本管理。
Step 2: 啟用版本控制(enableVersioning)
設置完前綴詞後,接下來啟用版本控制。這一步必須在前綴詞設置之後,才能讓版本號正確套用到API路徑。這裡選用 VersioningType.URI
,讓版本資訊直接出現在URL中,讓客戶端可以通過不同的URL訪問不同的API版本。
import { VersioningType } from '@nestjs/common';
// 啟用版本控制,使用URI型別
app.enableVersioning({
type: VersioningType.URI
});
此配置會讓NestJS根據URL中的版本號來自動匹配相應的控制器。例如,當請求/api/v1/...
時,NestJS會將這個請求視為對第一版API的呼叫。
Step 3: 設定控制器的版本
在NestJS中,控制器的版本控制有兩種常用方式,各具優缺點:
方法 1: 在 @Controller
中設置版本
這種方式適合整個控制器都屬於同一個版本的情境。當控制器內的所有路由均屬於相同的API版本時,可以直接在 @Controller
裝飾器中設定 path
和 version
。
import { Controller, Get } from '@nestjs/common';
// 在Controller中設定路徑和版本
@Controller({
path: 'test',
version: '1'
})
export class TestController {
@Get('echo')
async echo() {
return { data: 'echo' };
}
}
優點:
- 簡潔明瞭:一次設定即可讓控制器內的所有路由都自動套用該版本。
- 方便管理:適合整個控制器共用同一版本的情境,不需要重複指定每個路由的版本號。
缺點:
- 缺乏靈活性:無法在控制器內針對單一路由支持多個版本。
- 更新代價高:當其中某些路由需要單獨更新版本時,需要重構控制器或拆分路由,對於快速迭代來說可能不夠靈活。
方法 2: 使用 @Version
裝飾器針對單一路由設置版本
如果需要在同一控制器內支持多個版本,可以使用 @Version
裝飾器來針對特定路由指定版本。這種方式適合某些路由需要更新版本,而其他路由仍保留舊版本的情境。
import { Controller, Get, Version } from '@nestjs/common';
@Controller('test')
export class TestController {
@Version('1')
@Get('echo')
async echo() {
return { data: 'echo' };
}
}
優點:
- 高度靈活:允許在同一控制器中針對不同路由設定不同版本,非常適合逐步更新API版本或同時支持多個版本的情境。
- 便於過渡:在同一控制器中實現多版本共存,不影響整體API的穩定性,適合API過渡階段的需求。
缺點:
- 代碼可讀性降低:當控制器中的路由需要支持多個版本時,代碼的結構清晰度會下降,管理起來較為複雜。
- 維護複雜性增加:由於每個路由可以單獨設定版本,維護時需要仔細檢查每個路由的版本設定,增加了出錯的風險。
Step 4: 模組化 API 路由
隨著應用程式的增長,將不同版本的API分離到獨立的模組中可以提升維護效率,讓架構更具擴展性。以下範例展示了如何建立 RoutesModule
來統籌不同版本的API模組,並引入第一版本的模組 V1Module
。
import { Module } from '@nestjs/common';
import { V1Module } from '../v1/v1.module';
@Module({
imports: [
V1Module, // 引入V1版本模組
],
})
export class RoutesModule {}
在 V1Module
中定義該版本的控制器:
import { Module } from '@nestjs/common';
import { TestController } from './test.controller';
@Module({
controllers: [TestController], // 註冊V1版本控制器
})
export class V1Module {}
這樣的模組結構便於未來新增API版本,每新增一個版本時,只需創建新的模組並註冊相應控制器,而不會影響現有的版本模組。
小結
在NestJS中進行API版本控制的最佳實踐流程是:先設定全域前綴詞,再啟用版本控制,以確保API前綴和版本控制都被正確應用到路徑中。可以選擇在 @Controller
中設置版本以統一管理,也可以透過 @Version
裝飾器指定單一路由的版本,靈活應對多版本需求。
選擇 @Controller
的版本設定:適合全控制器共用一個版本的情境,實現簡單,代碼結構清晰;但對於單路由版本更新不夠靈活。
選擇 @Version
的路由版本設定:適合逐步過渡到新版本或部分路由支持多版本的情境,靈活度高;但維護時更為複雜,需要細緻的版本管理。
選擇適合的方式可以讓API更加靈活、易於維護,並更適應實際需求的變化。
參考資料: