
目錄前言一、NestJS 概念二、一個請求在 NestJS 中怎么走請求流程??????三、NestJS 運行架構圖簡圖四、NestJS 的核心機制必須記住??????????五、NestJS 核心成員全量速覽表建議收藏六、重點核心成員「逐個突破」1、Module結構與邊界??????????2、Provider一切可注入的對象1、Service最核心3、Controller只做“協(xié)議層”4、請求增強類約束和治理1、Middleware請求最外層2、Guard訪問控制層?3、Pipe參數(shù)治理層?4、Interceptor橫切增強核心?5、Exception Filter異常兜底層?5、IoC / DI 依賴注入NestJS 的靈魂??????????1、認識 IoC / DI2、NestJS 中的 IoC / DI①、定義 Provider能力②、消費 Provider不再 new③、用 Module 把能力“聲明”給容器七、傳統(tǒng) MVC vs NestJS核心差異總覽表重點版??八、標準企業(yè)級 NestJS 分層建議規(guī)范版九、「企業(yè)業(yè)務」架構圖十、NestJS、Fastify 和 Express 全方位對比十一、NestJS 默認使用 Express做了什么工作十二、如何將 NestJS 的運行時適配器由 Express 替換為 Fastify??1、為什么 NestJS 可以“隨便換” Express / Fastify2、替換為 Fastify標準做法1、安裝依賴必須2、修改 main.ts3、Fastify 專屬能力可選但常用前言NestJS Node.js 世界里的 Spring 框架。一、NestJS 概念NestJS 是一個基于 TypeScript 的、強約束、架構優(yōu)先的 Node.js 服務端框架。它的核心目標不是“寫得快”而是寫得穩(wěn)可擴展可維護可測試可演進NestJS 解決的是 Node.js 的「工程失控」問題傳統(tǒng) Node / Express 痛點NestJS 對應解決方案目錄結構隨意Module 強約束依賴注入缺失內(nèi)置 IoC 容器中間件混亂Middleware / Guard / Interceptor / Pipe 分層業(yè)務代碼和框架代碼混在一起Controller / Service / Provider測試困難天然可 Mock、可單測大型項目難以協(xié)作清晰邊界 依賴反轉NestJS 是把 Java / Spring 的工程思想 引入到了 Node.js 世界。二、一個請求在 NestJS 中怎么走請求流程??????你會發(fā)現(xiàn)Controller 不重要它只是一個“轉發(fā)器”真正干活的是 Provider三、NestJS 運行架構圖簡圖四、NestJS 的核心機制必須記住??????????如果你只記住了這個那就記住這個吧。NestJS 的核心機制包括模塊化架構Module → 結構邊界依賴管理依賴注入IoC / DI Container → NestJS 的靈魂管理 Provider 生命周期解耦、復用、測試友好ProviderService / Repository / Infra 等 → 一切能力的載體承載業(yè)務邏輯、數(shù)據(jù)訪問、基礎設施請求攔截體系Interceptor / Guard / Pipe / Filter → 請求增強橫切邏輯企業(yè)級必備生命周期鉤子 異步機制 → 支撐啟動初始化、關閉清理、異步外部資源五、NestJS 核心成員全量速覽表建議收藏分類類型 / 名稱是否官方重要性作用推薦場景Provider 類Service?約定俗成?????核心業(yè)務邏輯業(yè)務處理、狀態(tài)流轉、任務編排Repository?架構約定????數(shù)據(jù)訪問抽象DB 操作、ORM 封裝Infra?架構約定????外部依賴封裝MQ / Redis / SDK / OSSFactory?????動態(tài)創(chuàng)建 Provider 實例Redis / MQ / 多租戶 DB / SDK 初始化Value????常量 / 配置注入feature flag、常量、枚舉Class?????多實現(xiàn)替換支付渠道、多通道消息、存儲服務Async?????異步初始化 Provider異步連接、遠程配置加載Token?????抽象解耦多實現(xiàn)注入、接口替換、架構解耦Controller 類HTTP Controller??????接收 REST 請求CRUD、業(yè)務接口WebSocket Gateway????實時雙向通信聊天系統(tǒng)、實時通知Microservice Controller?????消息通信分布式任務、事件總線RPC Controller????遠程調(diào)用內(nèi)部服務 RPCGraphQL Resolver????GraphQL 請求處理查詢/變更/訂閱請求增強類Middleware????請求預處理日志、requestId、簡單 authGuard?????權限控制登錄校驗、RBAC、數(shù)據(jù)權限Pipe?????參數(shù)校驗 / 轉換DTO 校驗、類型轉換、臟數(shù)據(jù)防護Interceptor??????橫切增強日志、性能監(jiān)控、統(tǒng)一響應、緩存、事務Exception Filter?????異常捕獲全局異常處理、日志、監(jiān)控上報模塊與應用Module??????架構邊界、依賴管理拆分業(yè)務模塊、管理 ProviderApp / Application??????系統(tǒng)啟動與關閉啟動模塊、全局 Provider 管理核心系統(tǒng)級成員IoC Container??????Provider 依賴管理Singleton / Request / Transient 管理Reflect Metadata?????裝飾器元數(shù)據(jù)路由、驗證、權限、AOPPlatform Adapter????平臺適配Express / Fastify / Microservice重點關注 5 顆 ? 和 4 顆 ? 的。下面我們分別研究下這里面的重要成員。六、重點核心成員「逐個突破」1、Module結構與邊界??????????為什么需要 Module系統(tǒng)會越來越大不分模塊 一團亂麻作用聲明「這個模塊有哪些能力」支持分層架構Controller → Service → Repository → Infra控制依賴可見性支持模塊復用、懶加載定義業(yè)務邊界保證系統(tǒng)清晰邊界和高可維護性特性imports引入其他模塊providers聲明模塊內(nèi)部 Providercontrollers聲明 Controllerexports輸出可被其他模塊使用的 Provider示例Module({imports:[],controllers:[],providers:[],exports:[]})exportclassUserModule{}2、Provider一切可注入的對象定義凡是能被 Nest IoC 注入的對象都是 Provider。重要性一切業(yè)務 和 基礎設施 都寫在 Provider 中。作用承載業(yè)務邏輯數(shù)據(jù)訪問基礎設施封裝原則單一職責精簡 Controller → Provider 專注業(yè)務可替換、多實現(xiàn)Token / Class ProviderProvider 生命周期三種作用域Scope生命周期特點Singleton應用啟動實例化 → 全局共享 → 應用關閉銷毀Request每次請求生成實例 → 請求結束銷毀Transient每次注入生成實例 → 使用完銷毀Provider 主要包括以下成員ServiceRepositoryCache / MQSDK 封裝工具類企業(yè)級應用Service 調(diào)用 Repository Infra → 保證 Controller 薄Factory / Async Provider → 異步初始化外部資源Token / Class Provider → 支持支付渠道、消息通道替換1、Service最核心NestJS 的 Service是 IoC 容器中的“業(yè)務能力單元”它負責表達業(yè)務規(guī)則、編排業(yè)務流程業(yè)務正確性而不是處理技術細節(jié)。Service 的本質(zhì)非常重要維度本質(zhì)架構層面Application / Domain 層的載體IoC 角度被容器托管的可注入對象職責角度業(yè)務規(guī)則 業(yè)務流程編排可測試性可 Mock、可獨立測試的純邏輯單元? Service 應該做的事類型舉例業(yè)務規(guī)則狀態(tài)流轉、校驗業(yè)務流程下單 → 鎖庫存 → 支付 → 發(fā)通知事務控制DB 事務 / 分布式事務資源協(xié)調(diào)DB Redis MQ業(yè)務抽象統(tǒng)一業(yè)務接口? Service 不應該做的事禁止原因解析 HTTP 請求屬于 Controller操作 Request / Response破壞分層寫 SQLRepository 的職責寫 Redis Key 細節(jié)Infra 關注點關心 UI 展示Presentation 關注點示例Injectable()exportclassUserService{}3、Controller只做“協(xié)議層”Controller 是 NestJS 的“傳輸適配層Transport Adapter”而不是業(yè)務層。Controller 的職責必須克制接收請求參數(shù)提取返回響應? 不寫業(yè)務邏輯Controller 的本質(zhì)非常重要維度本質(zhì)架構層Presentation Layer表現(xiàn)層職責協(xié)議適配 請求入口復雜度應該極低生命周期被 IoC 管理可替換性可以被 GraphQL / RPC / MQ 替代Controller 不是核心邏輯所在而是“可被替換的一層殼”。與 MVC 架構的 Controller 過于肥大不同NestJS 刻意對 Controller 做了瘦身業(yè)務邏輯全部下沉到 ServiceController 只負責“接、轉、發(fā)調(diào)”。Controller 越薄系統(tǒng)越健康。? Controller 能干什么明確邊界職責說明路由聲明Controller / Get協(xié)議綁定HTTP / GraphQL / RPC參數(shù)獲取Body / Query / ParamDTO 校驗Pipe class-validator調(diào)用 Service只調(diào)用、不實現(xiàn)返回結果統(tǒng)一響應結構? Controller 禁止做的事紅線禁止項為什么寫業(yè)務規(guī)則破壞分層操作數(shù)據(jù)庫嚴重越權寫 Redis / MQInfra 泄漏try/catch 業(yè)務異常應交給 Filter拼裝復雜對象應在 ServiceController 的典型結構標準范式Controller(orders)exportclassOrderController{constructor(privatereadonlyorderService:OrderService,){}Post()create(Body()dto:CreateOrderDto){returnthis.orderService.create(dto);}}Controller 的分類企業(yè)級常見REST Controller最常見RPC / 微服務 ControllerGraphQL ResolverController 的另一種形態(tài)BFF Controller前端友好好 Controller 的 5 條鐵律設計原則每個方法 ≤ 5 行只做參數(shù)映射不寫 if / for只依賴 Service / Facade返回 DTO / ViewModel4、請求增強類約束和治理定義請求增強類 不處理業(yè)務本身而是對“請求/響應生命周期”進行增強、約束、治理的組件。它們的共同特點是關心 請求什么時候來、是否允許進入、如何變形、如何返回、如何兜底是 AOP面向切面編程思想的具體落地? 不關心具體業(yè)務作用在請求進入 Controller 前、響應返回前進行增強保證 Controller 只處理請求入口業(yè)務邏輯在 ProviderNestJS 的五大請求增強類官方類型執(zhí)行位置核心職責Middleware最外層原始請求預處理GuardController 之前是否允許進入Pipe參數(shù)進入 Controller 之前校驗 / 轉換InterceptorController 前后橫切增強Exception Filter異常拋出后統(tǒng)一異常處理1、Middleware請求最外層定位對原始 Request / Response 做最早處理特點基于 Express / Fastify無法使用 DI或能力有限更偏“框架級”典型用途requestId 注入原始日志CORS簡單鑒權不推薦復雜? 不適合復雜權限業(yè)務邏輯依賴 Service 的場景2、Guard訪問控制層?定位決定“這個請求有沒有資格進入 Controller”特點返回 boolean / Promise可以使用 DI強語義是否放行典型用途登錄校驗RBAC / ABAC 權限數(shù)據(jù)級權限是否能訪問某資源canActivate(context:ExecutionContext):boolean{constreqcontext.switchToHttp().getRequest()return!!req.user}Guard 是權限體系的唯一正解3、Pipe參數(shù)治理層?定位參數(shù)進入 Controller 前的“質(zhì)量控制器”特點在參數(shù)級別執(zhí)行可轉換 / 可拋錯強配合 DTO class-validator典型用途參數(shù)校驗類型轉換默認值填充防臟數(shù)據(jù)Body(newValidationPipe())create(Body()dto:CreateUserDto){}Pipe 參數(shù)防火墻4、Interceptor橫切增強核心?定位Controller 前后包裹執(zhí)行特點可拿到返回值可修改響應可做 AOP典型用途非常關鍵統(tǒng)一響應格式日志 性能統(tǒng)計緩存事務控制冪等控制returnnext.handle().pipe(tap(()console.log(after)),)Interceptor 是 NestJS 的靈魂5、Exception Filter異常兜底層?定位異常統(tǒng)一收口特點捕獲 throw 出來的異常可分類處理可上報監(jiān)控典型用途HTTP 異常統(tǒng)一格式錯誤碼規(guī)范Sentry / 日志系統(tǒng)Catch(HttpException)exportclassHttpFilter{}Filter 系統(tǒng)穩(wěn)定器5、IoC / DI 依賴注入NestJS 的靈魂??????????1、認識 IoC / DIIoC控制反轉是一種新的設計思想——提供了另一種創(chuàng)建對象的方式不用 new。DI依賴注入是 IoC 最主流、最工程化的實現(xiàn)方式DI 容器在運行時把對象所需的依賴“注入”進去。IoC 的核心反轉點維度傳統(tǒng)方式IoC創(chuàng)建對象自己 new容器創(chuàng)建管理依賴對象自己容器統(tǒng)一管理生命周期不可控可配置替換實現(xiàn)困難極其容易從“對象控制一切” → “容器控制一切”常見 DI 方式方式示例構造函數(shù)注入NestJS / Spring屬性注入Angular方法注入少見NestJS 使用的是 構造函數(shù)注入最安全。2、NestJS 中的 IoC / DI不理解 IoC / DI就永遠只是在“用 NestJS 寫接口”而不是“用 NestJS 構建系統(tǒng)”。NestJS 的核心能力本質(zhì)上是一個“強約束、強治理的 IoC 容器”。IoC 是“控制權反轉”DI 是“反轉的具體實現(xiàn)方式”。作用管理 Provider 生命周期Singleton / Request / Transient支撐模塊間解耦、可替換實現(xiàn)、可 Mock 測試核心價值解耦 → Controller / Service / Repository 不直接創(chuàng)建依賴復用 → 同一 Provider 可被多個模塊注入測試友好 → Mock / 替換 Provider 容易「沒有 IoC」會發(fā)生什么對照組classPaymentService{pay(){returnpay success}}classOrderService{privatepaymentServicenewPaymentService()createOrder(){returnthis.paymentService.pay()}}? 問題OrderService 強依賴 PaymentService無法替換實現(xiàn)難測試、難擴展使用 NestJS IoC 的最小示例推薦記?、佟⒍x Provider能力Injectable()exportclassPaymentService{pay(){returnpay success}}②、消費 Provider不再 newInjectable()exportclassOrderService{constructor(privatereadonlypaymentService:PaymentService,){}createOrder(){returnthis.paymentService.pay()}}OrderService 不關心 PaymentService 怎么來的③、用 Module 把能力“聲明”給容器Module({providers:[PaymentService,OrderService],})exportclassOrderModule{}到這里為止OrderService 的依賴關系已經(jīng)“聲明完畢”實例創(chuàng)建權完全交給 Nest根據(jù)上述“①、②、③”整個典例來看當 Nest 啟動時發(fā)生了什么IoC 真正生效的地方掃描 OrderModul發(fā)現(xiàn) PaymentService、OrderService解析 OrderService 構造函數(shù)參數(shù)自動創(chuàng)建 PaymentService注入進 OrderService??OrderService 從來沒 new 過任何東西。七、傳統(tǒng) MVC vs NestJS核心差異總覽表重點版??維度傳統(tǒng) MVCNestJS架構中心ControllerModule Provider設計核心請求 → 響應能力組合 依賴注入依賴管理手動 new / 引入IoC 容器統(tǒng)一管理業(yè)務組織Controller 膨脹Service 解耦、可組合擴展機制Hook / 中間件有限Guard / Pipe / Interceptor / Filter面向?qū)ο笃^程式強 OOP DDD 友好測試友好度較弱極強天然 Mock企業(yè)級能力中小項目為主天然支持大型系統(tǒng)八、標準企業(yè)級 NestJS 分層建議規(guī)范版src/├── modules/│ └── business/│ ├── business.controller.ts │ ├── business.service.ts ← 業(yè)務 │ ├── business.repository.ts ← 數(shù)據(jù) │ ├── clients/│ │ └── aliyun.client.ts ← Infra │ ├── dto/│ └── business.module.ts ├── infra/│ ├── redis/│ ├── logger/│ └── queue/九、「企業(yè)業(yè)務」架構圖十、NestJS、Fastify 和 Express 全方位對比維度ExpressFastifyNestJS定位輕量級 HTTP 框架高性能 HTTP 框架企業(yè)級應用框架抽象層級低接近原生 HTTP中HTTP Schema高平臺級是否是應用框架???默認 HTTP 內(nèi)核自身自身Express可換 Fastify是否可替換 HTTP 內(nèi)核???核心設計思想Middleware 鏈Plugin SchemaModule Provider IoC架構中心app / routerserver / pluginModule / Provider依賴注入DI???核心能力IoC 容器???模塊化能力???AOP / 攔截體系???Guard / Pipe / Interceptor / Filter請求生命周期治理手寫部分完整、標準化Controller 概念???Service 層約定約定一等公民DTO / 參數(shù)校驗手寫Schema 原生支持Pipe class-validator權限體系手寫手寫Guard官方模式異常處理Error MiddlewareError HandlerException Filter統(tǒng)一響應手寫手寫Interceptor事務 / 冪等 / 緩存手寫手寫Interceptor / Provider中間件機制MiddlewarePlugin更強Middleware最外層插件生態(tài)?????????????基于 Adapter類型支持TS???????????性能????????????取決于底層高并發(fā)能力一般非常強強Fastify 模式測試友好度一般一般極強天然 Mock微服務支持???官方GraphQL 支持???WebSocket 支持手動插件官方支持學習成本低中高代碼規(guī)范約束極低低高強約束項目規(guī)模適配小中中 → 超大典型項目簡單 API / Demo高性能 API企業(yè)后臺 / 中臺 / BFF架構演進成本高中低可維護性易失控中等非常強是否適合大型團隊????十一、NestJS 默認使用 Express做了什么工作在 NestJS 中Express 只是“HTTP 運行時適配器Runtime Adapter”。其他所有“應用級能力”幾乎全部由 NestJS 自己接管。NestJS應用框架 ↓ ExpressHTTP適配器/執(zhí)行器 ↓ Node.js運行時Express 不再是“框架”而是“運行時引擎”層級負責者HTTP 協(xié)議Express路由注冊NestJS請求生命周期NestJS權限 / 校驗NestJS業(yè)務邏輯NestJS異常治理NestJS響應格式NestJS90% 的“應用邏輯”已經(jīng)不在 Express 里了十二、如何將 NestJS 的運行時適配器由 Express 替換為 Fastify??既然 Fastify 比 Express 性能更強大那么如何快速將 NestJS 的運行時適配器由 Express 替換為 Fastify 呢NestJS 默認使用 Express 時通過 Platform Adapter 抽象了 Web 層這就給了你替換的機會你只需要在 bootstrap 階段替換 Adapter就可以無痛切換到 Fastify。1、為什么 NestJS 可以“隨便換” Express / FastifyNestJS 的核心不直接依賴 Express而是依賴 nestjs/platform-* 適配層Nest Core ↓ Platform AdapterExpress/Fastify ↓HTTPServer這正是 NestJS IoC 適配器模式 的體現(xiàn)。2、替換為 Fastify標準做法1、安裝依賴必須npm installnestjs/platform-fastify fastify?? 不需要再裝 express2、修改 main.tsimport{NestFactory}fromnestjs/coreimport{AppModule}from./app.moduleimport{FastifyAdapter,NestFastifyApplication,}fromnestjs/platform-fastifyasyncfunctionbootstrap(){constappawaitNestFactory.createNestFastifyApplication(AppModule,newFastifyAdapter(),)awaitapp.listen(3000,0.0.0.0)}bootstrap()? 到這里Express 已被徹底替換為 Fastify3、Fastify 專屬能力可選但常用注冊 Fastify 插件constappawaitNestFactory.create(AppModule,newFastifyAdapter(),)app.register(require(fastify/cors))注意Fastify 插件 ≠ Nest Middleware使用 Fastify Request / Replyimport{FastifyRequest,FastifyReply}fromfastifyGet()get(Req()req:FastifyRequest,Res()reply:FastifyReply){reply.send({ok:true})}一旦使用 Res()Nest 的響應攔截器將失效和 Express 一樣