使用Nest和Typescript創建Node.js REST API
在Twitter上關注我,很高興聽取您關於主題或改進的建議/ Chris
用於構建高效,可靠和可擴展的伺服器端應用程序的漸進式Node.js框架。
在本文中,我們將介紹Nest庫。一個使創作API成為非常好的體驗的庫。如果你來自Angular世界,你一定會認識到自己使用的概念,一個很棒的CLI,當然還有很好的用法。
注意,它雖然不是Angular,但是以儘可能最好的方式非常接近。
本文是關於Nest的一系列文章的一部分,因為我們無法在一篇文章中涵蓋所有內容。
我們將介紹以下內容:
- 為什麼選擇Nest,讓我們來看看銷售情況,並提及使Nest成為您下一個API的絕佳選擇的功能
- 你的第一個CRUD項目 – 涵蓋基礎知識,讓我們構建一個項目並重溫基本結構
為何選擇Nest
我們來看看主頁上的銷售情況
- 可擴展,藉助模塊化架構,允許使用任何其他庫
- 多功能,適應性強的生態系統,適用於各種伺服器端應用
- Progressive,利用最新的JavaScript功能,設計模式和成熟的解決方案
好吧,這一切聽起來都不錯,但給我一些我可以和同事一起玩的東西
它完全支持TypeScript,但如果您願意,可以使用純JavaScript。
它使用庫 表達
和 Fastify
引擎蓋下,但如果需要也可以暴露他們的API。
聽起來很有意思,告訴我更多
它附帶一個CLI,因此您可以構建一個項目以及添加工件。
真好
最重要的是,您可以使用Jest輕鬆編寫單元測試以及E2E測試,並且可以使用它輕鬆構建GraphQL API
停下來,你正在努力
不是,請查看Nest和GraphQL
資源
我們將在本文中提到一些很好的資源。如果你錯過我們提到的鏈接,這裡就是。
- 官方文檔頁面官方文檔頁面是一個很好的頁面。它涵蓋了從基礎知識到食譜的所有內容
- 概述部分whol概述部分是一個很好的閱讀,試圖理解核心概念,你也可以使用CLI來支撐項目
- 食譜那裡有很多很好的食譜。從如何使用不同的ORM到設置Swagger(這是超級簡單順便說一句)的一切
您的第一個項目 – 涵蓋基礎知識
那好吧。我們開工吧。在我們開始創建第一個項目之前,我們需要CLI來創建和運行我們的項目以及更多的東西。我們可以使用以下命令輕鬆安裝CLI:
npm i -g @ nestjs / cli
接下來我們需要建立一個項目。接下來讓我們這樣做:
嵌套新的你好世界
你可以替換 你好,世界
使用您選擇的項目名稱。
好的,我們得到了很多文件。從上面的圖像判斷,我們似乎得到了一個Node.js項目 的package.json
並且使用Jest設置了一些測試,當然還有一些看似Nest特有的工件,如控制器,模塊和服務。讓我們仔細看看腳手架項目:
它是如何工作的?
在我們運行項目之前,我們只是搭建腳手架,讓我們先仔細看看,以便了解生命周期。首先讓我們來看看 main.ts
。這是我們的應用程序的切入點。更具體地說,它是 引導()
通過運行代碼啟動所有內容的方法:
// main.ts 常量 應用 = 等待 NestFactory。創建(的AppModule); 等待 應用。聽(3000);
好的,所以 NestFactory
電話 創建()
實例化 的AppModule
我們得到一個 應用
似乎在埠上偵聽的實例 3000
。讓我們去 的AppModule
看看那裡發生了什麼:
//app.module.ts @模({ 進口: (), 控制器: (AppController的) 供應商: (AppService服務) }) 出口 類 的AppModule {}
好吧,我們似乎有一堂課 的AppModule
正在裝飾的 @Module
裝飾者,具體的控制器 AppController的
以及被歸類為提供者的東西 AppService服務
。
這一切如何運作?
好吧,控制器 AppController的
響應路由請求,讓我們看看如何設置:
// app.controller.ts @調節器() 出口 類 AppController的 { 構造函數(私人的 只讀 AppService服務: AppService服務) {} @得到() getHello(): 串 { 返回 這個。AppService服務。getHello(); } }
裝飾者 @得到()
確保我們將某個GET請求映射到我們班級的某個方法。在這種情況下,默認路由 /
將採用該方法回應 getHello()
而這又調用了 appService.getHello()
。我們來看看吧 app.service.ts
:
// app.service.ts 進口 { 注射 } 從 '@ nestjs /共同'; @注射() 出口 類 AppService服務 { getHello(): 串 { 返回 '你好,世界'; } }
這似乎是一個非常簡單的類方法 getHello()
返回一個字元串。
現在,讓我們回過頭來 app.controller.ts
。
從我們所看到的 AppService服務
正在注入構造函數 AppController的
像這樣:
//摘自app.controller.ts 構造函數(私人的 只讀 AppService服務: AppService服務) {}
它是如何知道如何做到的?
這裡有兩個答案:
- 如果添加
注射()
裝飾器到任何服務,這意味著它可以注入其他工件,如控制器或服務。 - 這將我們帶到第二步。我們需要將所述服務添加到
供應商
用於使DI機器工作的模塊的陣列。
哦?
是的,讓我們嘗試通過添加新路線的動作來鞏固這種理解。但在我們這樣做之前,讓我們開始這個項目並證明它的工作原理就像我們說的那樣:
npm開始
現在,讓我們前往瀏覽器:
添加路線
我們剛剛學會了支撐一個項目,並學會了運行同樣的東西。我們認為我們對概念模塊,控制器和服務有一個很好的把握,但沒有任何東西可以鞏固這些知識,就像添加新路徑並添加我們需要的所有工件一樣。我們將執行以下操作:
我們將創建一條新路線 /產品
為此,我們需要執行以下步驟
- 添加新服務
- 添加一個新控制器並注入我們的服務
- 連接DI機制
- 運行我們的應用程序,確保一切正常
我們要做的第一件事是學習如何正確使用Nest項目。現在我們跑了 npm開始
編譯我們的TypeScript代碼並在埠託管我們的應用程序 3000
但在開發過程中,我們可能想要一些能夠自動監聽變化和編譯的東西。為此,請改為運行命令 npm run start:dev
,在需要時監聽更改並重新編譯。
npm run start:dev
注意,在我們開始使用上面的命令之前,讓我們支持所有需要的文件,然後我們可以運行上面的內容,以便我們在特定的代碼文件中查看並且我們希望我們的更改能夠反映出來。
創建服務
讓我們創造我們的產品服務。現在,將數據設為靜態,我們可以稍後再查看添加HTTP調用。讓我們以Nest方式做事並使用CLI
nest生成服務產品
或者更短的版本
nest g s產品
好的,打開文件 產品/ products.service.ts
。它應該是這樣的:
進口 { 注射 } 從 '@ nestjs /共同'; @注射() 出口 類 ProductsService {}
現在添加方法 的getProducts()
所以它現在看起來像這樣:
進口 { 注射 } 從 '@ nestjs /共同'; @注射() 出口 類 ProductsService { 的getProducts() { 返回 ({ ID: 1, 名稱: 'SPA應用' }, { ID: 2, 名稱: 'Nest API' }) } }
添加控制器
現在是創建我們的控制器的時候了,所以讓我們接下來做。我們再一次只是CLI,如下所示:
nest生成控制器產品
或者,更短的版本
nest g co products
打開 產品/ products.controller
:
進口 { 調節器 } 從 '@ nestjs /共同'; @調節器(「產品」) 出口 類 的ProductsController {}
下一步是添加方法 的getProducts()
並確保我們稱之為我們的服務,當然我們不會忘記用它來裝飾它 @得到()
裝飾。
您的代碼現在應該如下所示:
進口 { 調節器, 得到 } 從 '@ nestjs /共同'; 進口 { ProductsService } 從 './products.service'; @調節器(「產品」) 出口 類 的ProductsController { 構造函數(私人的 productsService: ProductsService) {} @得到() 的getProducts() { 返回 這個。productsService。的getProducts(); } }
我們來試試吧:
npm run start:dev
上面我們可以看到我們的 /產品
似乎已添加了路線 的ProductsController
將響應該路線上的任何請求。但是怎麼可能,我們沒有做任何事情 app.module.ts
連接DI,還是我們?
我們來看看吧 app.module.ts
:
我們可以在上面看到 的ProductsController
和 ProductsService
已添加到 控制器
和 供應商
分別。當我們生成控制器和服務時,CLI為我們添加了它。
我們幾乎忘記了在瀏覽器中運行我們的應用程序的東西,所以讓我們這樣做:
注意,CLI功能強大,它不僅會創建必要的文件,還會進行一些連接,但是如果您不使用CLI,則需要知道需要做什麼。
添加剩餘的CRUD路由
好的,所以我們添加了一條支持路線 /產品
路線。眾所周知,雖然我們需要更多的路線 POST
, 放
, 刪除
和通配路線等
我們如何添加這些?
很簡單,我們只需為每個人創建方法,並添加裝飾器來支持它,如下所示:
// products.controller.ts 進口 { 調節器, 得到, 帕拉姆, 崗位, 身體, 放, 刪除 } 從 '@ nestjs /共同'; 進口 { ProductsService } 從 './products.service'; 介面 ProductDto { ID: 串; 名稱: 串; } @調節器(「產品」) 出口 類 的ProductsController { 構造函數(私人的 productsService: ProductsService) {} @得到() 的getProducts() { 返回 這個。productsService。的getProducts(); } @得到(':ID') getProduct(@帕拉姆() PARAMS) { 安慰。日誌('獲得單一產品', PARAMS。ID); 返回 這個。productsService。的getProducts()。過濾(p => p。ID == PARAMS。ID); } @崗位() createProduct(@身體() 產品: ProductDto) { 安慰。日誌('創造產品', 產品); 這個。productsService。createProduct(產品); } @放() 的UpdateProduct(@身體() 產品: ProductDto) { 安慰。日誌('更新產品', 產品); 這個。productsService。的UpdateProduct(產品); } @刪除() deleteProduct(@身體() 產品: ProductDto) { 安慰。日誌('刪除產品', 產品。ID); 這個。productsService。deleteProduct(產品。ID); } }
和 products.service.ts
現在看起來像這樣:
進口 { 注射 } 從 '@ nestjs /共同'; @注射() 出口 類 ProductsService { 製品 = ({ ID: 1, 名稱: 'SPA應用' }, { ID: 2, 名稱: 'Nest API' }); 的getProducts() { 返回 這個。製品; } createProduct(產品) { 這個。製品 = (...這個。製品, {...產品}); } 的UpdateProduct(產品) { 這個。製品 = 這個。製品。地圖(p => { 如果 (p。ID == 產品。ID) { 返回 { ...產品}; } 返回 p; }); } deleteProduct(ID) { 這個。製品 = 這個。製品。過濾(p => p。ID = ID); } }
摘要
希望您現在已經意識到Nest的結構是否良好以及創建API和讀取查詢參數以及支持完整CRUD API的主體是多麼容易。我們還介紹了CLI,它真正是您生成所需代碼的最佳朋友,並確保您不需要考慮如何連接。
在下一部分中,我們將看看如何測試我們的代碼,這是一個真正的幸福體驗。所以請繼續關注。