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
class
(cl)controller
(co)decorator
(d)exception
(e)filter
(f)gateway
(ga)guard
(gu)interceptor
(i)middleware
(mi)module
(mo)pipe
(pi)provider
(pr)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
複製代碼
依賴注入是一種技術,它提供一個依賴對象,如一個模塊或者一個組件,而後依賴的對象就像服務同樣,能夠把它注入到組件的構造函數中。 舉個例子,在這裏咱們將 UserRespository 服務注入到 UserService 的構造函數中, 從而提供從 UserService 組件內部訪問User Database存儲庫的權限。編程
@Injectable()
export class UserService implements IUserService {
constructor(@Inject('UserRepository') private readonly UserRepository: typeof User) { }
...
}
複製代碼
而後,這個 UsersService 將被注入到 UsersController,將提供控制器的路由對 UsersService 訪問。後續章節中會介紹路由和依賴注入的更多信息。api
身份驗證是開發過程當中最重要的方面之一。 做爲開發人員,咱們始終但願確保用戶只能訪問他們有權訪問的資源。 近年來,身份驗證方法已經擴展到變得更加複雜,但咱們仍然須要相同的服務器端邏輯,以確保這些通過身份驗證的用戶始終是合法用戶,並將這種身份驗證持久化,這樣就不須要爲每個 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。
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 ,並提供經過查詢鏈查詢數據庫的能力。
REST是建立API的主要設計範例之一。它表明表明狀態轉移傳輸,並使用JSON做爲傳輸格式,這與Nest存儲對象的方式一致,所以它適合使用和返回 HTTP 調用。
客戶端對服務器進行HTTP請求,服務器將根據URL和HTTP動詞將調用路由到正確的Controller,可選擇在到達Controller以前將其傳遞給一個或多箇中間件。 而後,Controller將其交給service進行處理,其中可能包括經過ORM與數據庫進行通訊。
若是客戶端請求資源(GET請求),則返回一個可選主體; 若是是 POST/PUT/DELETE,則返回一個200 / 201 HTTP OK,若是沒有響應主體。
Websocket 是從服務器鏈接和發送 / 接收數據的另外一種方式。
使用 websocket,客戶端鏈接到服務器,而後訂閱特定的通道。 而後,客戶端能夠將數據推送到訂閱的通道。 服務器將接收此數據,而後將其廣播到訂閱該特定通道的每一個客戶端。 這使得多個客戶端均可以接收實時更新,而無需手動進行 API 調用。 大多數聊天應用程序使用WebSockets進行實時通訊,一旦其中一個成員發送消息,組消息中的每一個人都將收到消息。 與傳統的請求-響應 API 相比,Websockets 容許更多的流式數據傳輸方法,由於 Websockets 能夠在接收到數據時廣播數據。
微服務容許將Nest將應用程序結構化爲鬆散耦合服務的集合。 在Nest中,微服務略有不一樣,由於它們是一個使用不一樣於 HTTP 的傳輸層的應用程序。該層能夠是TCP或Redis pub / sub等。
Nest支持TCP和Redis,但若是您與另外一個傳輸層結合,則可使用 CustomTransportStrategy 接口實現它。 微服務很棒,由於它們容許團隊在全局項目中處理本身的服務,而且在不影響項目其他部分的狀況下對服務進行更改,由於它是鬆散耦合的。 這使得持續交付和持續集成獨立於其餘團隊的微服務。
正如咱們在上面看到的,REST 是設計 api 時的一種範例, 可是有一種新的方式來考慮建立和使用 api:GraphQL。
使用GraphQL,URL將接受帶有JSON對象的查詢參數,而不是每一個資源都有本身的URL指向。 此JSON對象定義要返回的數據的類型和格式。 Nest經過 @nestjs/graphql 包提供了這方面的功能。
這將包括項目中GraphQLModule, 它是Apollo服務器的包裝器。
在討論Web框架時,路由是核心之一。當客戶端須要訪問服務器的端點時, 這些端點中的每個都描述瞭如何檢索/建立/操做存儲在服務器上的數據。 描述API端點的每一個Component必須具備@Controller() 裝飾器,用於描述該組件的端點集的 API 前綴。
@Controller('hello')
export class HelloWorldController {
@Get(‘world’)
printHelloWorld() {
return ‘Hello World’;
}
}
複製代碼
@Module:項目中此可重用代碼包的定義,它接受如下參數來定義其行爲。
⋅⋅Imports:包含此模塊中使用的組件。
⋅⋅Exports:導出模塊。
⋅⋅Components:經過 Nest 注入的組件在這個模塊上共享。
⋅⋅Controllers:在此模塊中建立的控制器,這些控制器將根據定義的路由定義API端點。
複製代碼
@Injectable:Nest中幾乎全部東西都是能夠經過構造函數注入的提供者。提供者用@Injectable()裝飾。
..Middleware:在將請求傳遞給路由處理程序以前運行的函數。
..Interceptor:相似於中間件,它們在執行方法以前和以後綁定額外的邏輯,它們能夠轉換或徹底覆蓋函數。攔截器的靈感來自面向方面編程(AOP)。
..Pipe:與攔截器功能的一部分相似,管道將輸入數據轉換爲所需的輸出。
..Guard:一個更聰明,更小衆的中間件,Guards的惟一目的是肯定路由器處理程序是否應該處理請求。
..* Catch:告訴ExceptionFilter要查找的異常,而後將數據綁定到它。
複製代碼
@Catch:將元數據綁定到異常過濾器,並告訴Nest過濾器只查找@Catch中列出的異常。
複製代碼
在編寫 Nest 服務器時,api文檔是很是重要的,不然使用該 API 開發客戶端的開發人員不知道發送什麼或將獲得什麼。
最流行的文檔引擎之一是 Swagger。 像其餘模塊同樣,Nest 爲 OpenAPI (Swagger) spec,提供了一個專用模塊 @nestjs/swagger。
這個模塊提供了裝飾器來幫助描述 API 的輸入 / 輸出和端點。 而後能夠經過服務器上的一個端點訪問該文檔。
命令查詢責任分離(Command Query Responsibility Segregation,CQRS)的思想是,每一個方法要麼是執行操做(Command)的方法,要麼是執行請求數據(Query)的方法。
在咱們的示例應用程序的上下文中,不會在控制器中直接爲一個端點建立數據庫訪問代碼,而是建立一個組件(數據庫服務) ,該組件具備getAllUsers()這樣的方法,它將返回控制器服務能夠調用的全部用戶,從而將問題和答案分離到不一樣的組件中。
測試你的 Nest 服務器將是必要的,確保部署時沒有不可預見的安全性問題。
有兩種不一樣類型的測試: 單元測試和 E2E 測試(端到端測試)。 單元測試是測試小代碼片斷或代碼塊,它能夠像測試單個函數或 Controller、 Interceptor 或任何其餘Injectable測試同樣精細。
如今有不少流行的單元測試框架,Jasmine 和 Jest 是兩個流行的框架。 Nest 提供了特殊的包,@nestjs/testing,用於在 *.spec.ts 及 *.test.ts 類中編寫單元測試。
E2E 測試是另外一種經常使用的測試形式,它不一樣於單元測試,它測試整個功能,而不是測試單個功能或組件,而這正是端到端測試這個名稱的來源。
當應用程序變得很是龐大,以致於很難絕對地測試每一段代碼和端點。 在這種狀況下,您可使用 E2E 測試從頭至尾測試應用程序,以確保一切順利進行。
對於 E2E 測試,Nest 應用程序能夠再次使用 Jest 庫來模擬組件。 除了 Jest 以外,還可使用 supertest 庫來模擬 HTTP 請求。