(一) 《Nest.js:漸進式node.js框架》 介紹

Nestjs 是一個構建在Node.js Express服務器之上的現代Web框架。利用現代ES6 JavaScript提供的強大靈活性和TypeScript在編譯期間強制實現類型安全,將可擴展的Node.js服務器提高到一個全新的水平。Nest將三種不一樣的技術結合爲一個成功的組合,使應用程序高度可測試,可擴展,鬆散耦合和可維護:

  • 面向對象編程(OOP):圍繞對象而不是行爲和可重用性構建的模型。
  • 函數編程(FP):設計的函數不依賴於全局狀態,即對於一些不改變的設置參數,函數f(x)每次都返回相同的結果。
  • 函數式響應型編程(FRP):擴展上面的FP和響應型編程。函數式響應型編程是其核心功能編程,它考慮了跨時間的流程。它在UI,模擬,機器人和其餘應用程序中很是有用,其中特定時間段的結果可能與另外一個時間段的結果不一樣。

主題討論

1. Nest CLI

Nest的第5版中新增了一個CLI命令,容許經過命令行生成項目和文件。 全局安裝CLI:javascript

npm install -g @nestjs/cli
複製代碼

或者經過Docker:java

docker pull nestjs/cli:[version]
複製代碼

可使用如下命令生成新的Nest項目:node

nest new [project-name]
複製代碼

此過程將詢問 name, description, version (defaults to 0.0.0), and author (你的名字)。 完成此過程後,您將擁有一個設置好的Nest項目,其中依賴項安裝在 node_modules 文件夾。 new 命令還會詢問你想用什麼包管理器,以一樣的方式,有 yarn 或 npm 能夠用。web

CLI中最經常使用的命令是 generate (g) 命令, 容許你建立新的 controllers, modules, servies 或Nest支持的任何其它組件:docker

  1. class (cl)
  2. controller (co)
  3. decorator (d)
  4. exception (e)
  5. filter (f)
  6. gateway (ga)
  7. guard (gu)
  8. interceptor (i)
  9. middleware (mi)
  10. module (mo)
  11. pipe (pi)
  12. provider (pr)
  13. service (s)

括號中的字符串是該特定命令的別名 typescript

nest generate service [service-name]
複製代碼

在控制檯中,您能夠輸入:數據庫

nest g s [service-name]
複製代碼

最後,Nest CLI提供 info (i) 命令以顯示項目的有關信息。這個命令將輸出以下信息:npm

[System Information]
OS Version     : macOS High Sierra
NodeJS Version : v8.9.0
YARN Version    : 1.5.1
[Nest Information]
microservices version : 5.0.0
websockets version    : 5.0.0
testing version       : 5.0.0
common version        : 5.0.0
core version          : 5.0.0
複製代碼

2.依賴注入

依賴注入是一種技術,它提供一個依賴對象,如一個模塊或者一個組件,而後依賴的對象就像服務同樣,能夠把它注入到組件的構造函數中。 舉個例子,在這裏咱們將 UserRespository 服務注入到 UserService 的構造函數中, 從而提供從 UserService 組件內部訪問User Database存儲庫的權限。編程

@Injectable()
export class UserService implements IUserService {
    constructor(@Inject('UserRepository') private readonly UserRepository: typeof User) { }
    ...
}
複製代碼

而後,這個 UsersService 將被注入到 UsersController,將提供控制器的路由對 UsersService 訪問。後續章節中會介紹路由和依賴注入的更多信息。api

3.認證

身份驗證是開發過程當中最重要的方面之一。 做爲開發人員,咱們始終但願確保用戶只能訪問他們有權訪問的資源。 近年來,身份驗證方法已經擴展到變得更加複雜,但咱們仍然須要相同的服務器端邏輯,以確保這些通過身份驗證的用戶始終是合法用戶,並將這種身份驗證持久化,這樣就不須要爲每個 REST API 或 Websocket 的調用者從新進行身份驗證,由於那將提供很是糟糕的用戶體驗。

Nest 選擇集成Node.js生態系統中很是有名的認證庫 Passport,同時使用JWT(JSON Web Token)策略。 Passport是在調用控制器上的端點以前傳遞HTTP調用的中間件。下面是爲示例項目編寫的 AuthenticationMiddleware ,它擴展了 NestMiddleware,根據請求有效負載中的電子郵件對每一個用戶進行身份驗證。

@Injectable()  
export class AuthenticationMiddleware implements NestMiddleware {  
   constructor(private userService: UserService) { }  

   async resolve(strategy: string): Promise<ExpressMiddleware> {  
       return async (req, res, next) => {  
           return passport.authenticate(strategy, async (/*...*/args: any[]) => {  
               const [, payload, err] = args;  
                if (err) {  
                    return res.status(HttpStatus.BAD_REQUEST).send('Unable to authenticate the user.');  
                }  

               const user = await this.userService.findOne({
                    where: { email: payload.email }
               });  
                req.user = user;  
                return next();  
            })(req, res, next);  
        };  
    }  
}
複製代碼

Nest還實現了Guards,與其餘提供程序同樣,使用@Injectable()裝飾器進行裝飾。 Guards 能夠控制用戶能夠訪問的內容端點。 將在後續「身份驗證」章節中更詳細地討論 Guards。

4.ORM

ORM是服務器和數據庫之間通訊時最重要的概念之一:對象關係映射。 ORM提供內存中對象(諸如定義的 User 或 Comment 類) 和數據庫中的關係表之間的映射。 容許您建立一個數據傳輸對象,該對象知道如何將存儲在內存中的對象寫入數據庫,並將結果從SQL或其餘查詢語言讀回內存。在這,咱們將討論三種不一樣的ORM: 兩種關係型 orm 和一種針對 NoSQL 數據庫的 orm。

TypeORM是Node.js中最成熟和最流行的ORM之一, Nest爲其提供本身的包: @nestjs/typeorm,TypeORM很是強大,而且支持許多數據庫,如MySQL,PostgreSQL,MariaDB,SQLite,MS SQL Server,Oracle和WebSQL。同時,Sequelize也是關係數據庫的另外一個ORM。

若是TypeORM是最流行的ORM之一,那麼Sequelize則是Node.js世界中最受歡迎的ORM之一。 它是用純JavaScript編寫的, 可是經過 sequelize-typescript 和 @types/sequelize 包進行了 TypeScript 綁定。Sequelize擁有強大的事務支持,關係,讀取複製和更多功能。

最後一個ORM是處理非關係數據庫或NoSQL數據庫的ORM。mongoose 包處理MongoDB和JavaScript之間的對象關係。 與關係數據庫相比,二者之間的實際映射關係要密切得多,由於MongoDB以JSON格式存儲其數據,JSON格式表明JavaScript Object Notation。 Mongoose也有 @nestjs/mongoose ,並提供經過查詢鏈查詢數據庫的能力。

5.REST API

REST是建立API的主要設計範例之一。它表明表明狀態轉移傳輸,並使用JSON做爲傳輸格式,這與Nest存儲對象的方式一致,所以它適合使用和返回 HTTP 調用。

客戶端對服務器進行HTTP請求,服務器將根據URL和HTTP動詞將調用路由到正確的Controller,可選擇在到達Controller以前將其傳遞給一個或多箇中間件。 而後,Controller將其交給service進行處理,其中可能包括經過ORM與數據庫進行通訊。

若是客戶端請求資源(GET請求),則返回一個可選主體; 若是是 POST/PUT/DELETE,則返回一個200 / 201 HTTP OK,若是沒有響應主體。

6.WebSockets

Websocket 是從服務器鏈接和發送 / 接收數據的另外一種方式。

使用 websocket,客戶端鏈接到服務器,而後訂閱特定的通道。 而後,客戶端能夠將數據推送到訂閱的通道。 服務器將接收此數據,而後將其廣播到訂閱該特定通道的每一個客戶端。 這使得多個客戶端均可以接收實時更新,而無需手動進行 API 調用。 大多數聊天應用程序使用WebSockets進行實時通訊,一旦其中一個成員發送消息,組消息中的每一個人都將收到消息。 與傳統的請求-響應 API 相比,Websockets 容許更多的流式數據傳輸方法,由於 Websockets 能夠在接收到數據時廣播數據。

7.微服務

微服務容許將Nest將應用程序結構化爲鬆散耦合服務的集合。 在Nest中,微服務略有不一樣,由於它們是一個使用不一樣於 HTTP 的傳輸層的應用程序。該層能夠是TCP或Redis pub / sub等。

Nest支持TCP和Redis,但若是您與另外一個傳輸層結合,則可使用 CustomTransportStrategy 接口實現它。 微服務很棒,由於它們容許團隊在全局項目中處理本身的服務,而且在不影響項目其他部分的狀況下對服務進行更改,由於它是鬆散耦合的。 這使得持續交付和持續集成獨立於其餘團隊的微服務。

8.GraphQL

正如咱們在上面看到的,REST 是設計 api 時的一種範例, 可是有一種新的方式來考慮建立和使用 api:GraphQL。

使用GraphQL,URL將接受帶有JSON對象的查詢參數,而不是每一個資源都有本身的URL指向。 此JSON對象定義要返回的數據的類型和格式。 Nest經過 @nestjs/graphql 包提供了這方面的功能。

這將包括項目中GraphQLModule, 它是Apollo服務器的包裝器。

9.路由

在討論Web框架時,路由是核心之一。當客戶端須要訪問服務器的端點時, 這些端點中的每個都描述瞭如何檢索/建立/操做存儲在服務器上的數據。 描述API端點的每一個Component必須具備@Controller() 裝飾器,用於描述該組件的端點集的 API 前綴。

@Controller('hello')
export class HelloWorldController {
  @Get(‘world’)
  printHelloWorld() {
    return ‘Hello World’;
  }
}
複製代碼

10.Nestg工具裝飾器

@Module:項目中此可重用代碼包的定義,它接受如下參數來定義其行爲。
  ⋅⋅Imports:包含此模塊中使用的組件。
  ⋅⋅Exports:導出模塊。
  ⋅⋅Components:經過 Nest 注入的組件在這個模塊上共享。
  ⋅⋅Controllers:在此模塊中建立的控制器,這些控制器將根據定義的路由定義API端點。
複製代碼
@Injectable:Nest中幾乎全部東西都是能夠經過構造函數注入的提供者。提供者用@Injectable()裝飾。
  ..Middleware:在將請求傳遞給路由處理程序以前運行的函數。
  ..Interceptor:相似於中間件,它們在執行方法以前和以後綁定額外的邏輯,它們能夠轉換或徹底覆蓋函數。攔截器的靈感來自面向方面編程(AOP)。
  ..Pipe:與攔截器功能的一部分相似,管道將輸入數據轉換爲所需的輸出。
  ..Guard:一個更聰明,更小衆的中間件,Guards的惟一目的是肯定路由器處理程序是否應該處理請求。
  ..* Catch:告訴ExceptionFilter要查找的異常,而後將數據綁定到它。
複製代碼
@Catch:將元數據綁定到異常過濾器,並告訴Nest過濾器只查找@Catch中列出的異常。
複製代碼

11.OpenAPI (Swagger)

在編寫 Nest 服務器時,api文檔是很是重要的,不然使用該 API 開發客戶端的開發人員不知道發送什麼或將獲得什麼。

最流行的文檔引擎之一是 Swagger。 像其餘模塊同樣,Nest 爲 OpenAPI (Swagger) spec,提供了一個專用模塊 @nestjs/swagger。

這個模塊提供了裝飾器來幫助描述 API 的輸入 / 輸出和端點。 而後能夠經過服務器上的一個端點訪問該文檔。

12.命令查詢責任分離(CQRS)

命令查詢責任分離(Command Query Responsibility Segregation,CQRS)的思想是,每一個方法要麼是執行操做(Command)的方法,要麼是執行請求數據(Query)的方法。

在咱們的示例應用程序的上下文中,不會在控制器中直接爲一個端點建立數據庫訪問代碼,而是建立一個組件(數據庫服務) ,該組件具備getAllUsers()這樣的方法,它將返回控制器服務能夠調用的全部用戶,從而將問題和答案分離到不一樣的組件中。

13.測試

測試你的 Nest 服務器將是必要的,確保部署時沒有不可預見的安全性問題。

有兩種不一樣類型的測試: 單元測試和 E2E 測試(端到端測試)。 單元測試是測試小代碼片斷或代碼塊,它能夠像測試單個函數或 Controller、 Interceptor 或任何其餘Injectable測試同樣精細。

如今有不少流行的單元測試框架,Jasmine 和 Jest 是兩個流行的框架。 Nest 提供了特殊的包,@nestjs/testing,用於在 *.spec.ts 及 *.test.ts 類中編寫單元測試。

E2E 測試是另外一種經常使用的測試形式,它不一樣於單元測試,它測試整個功能,而不是測試單個功能或組件,而這正是端到端測試這個名稱的來源。

當應用程序變得很是龐大,以致於很難絕對地測試每一段代碼和端點。 在這種狀況下,您可使用 E2E 測試從頭至尾測試應用程序,以確保一切順利進行。

對於 E2E 測試,Nest 應用程序能夠再次使用 Jest 庫來模擬組件。 除了 Jest 以外,還可使用 supertest 庫來模擬 HTTP 請求。

相關文章
相關標籤/搜索