NestJS:我們一直在等待的精美的Node.js框架
NestJS:我們一直在等待的精美的Node.js框架
NestJS是一個(gè)精心制作的服務(wù)器端(后端)應(yīng)用程序框架,以支持開發(fā)人員的生產(chǎn)力并讓他們的生活更加快樂。
那么,它不僅是一個(gè)框架,它還是進(jìn)入領(lǐng)域驅(qū)動(dòng)設(shè)計(jì),事件采購(gòu),微服務(wù)架構(gòu)等先進(jìn)工程概念領(lǐng)域的推動(dòng)者。 所有軟件包都以簡(jiǎn)單輕量級(jí)的形式打包,以便您可以選擇 - 無論您決定使用整個(gè)框架還是僅重新使用其組件。
我是一個(gè) PHP 編寫的 Symfony 框架的粉絲。 在我的職業(yè)生涯中,我花了好幾年的時(shí)間開發(fā)大型應(yīng)用程序,它并沒有讓我失望。 它寫得很好,作為一個(gè)客觀的,具有良好文檔的模塊化 Web 框架,提供了良好的開發(fā)者體驗(yàn)。 與我描述 NestJS 完全一樣。
Node.js 和包管理器 NPM 提供了功能全面的服務(wù)器端環(huán)境,靈活性強(qiáng),運(yùn)行速度極快,對(duì)開發(fā)人員來說具有巨大的靈活性,從而將開發(fā)到生產(chǎn)的時(shí)間縮短到幾小時(shí),而不是幾天。
然而,盡管 Node.js 的優(yōu)點(diǎn)很多,但它并不能解決最常見的問題,在我看來,這是***的問題,所有的 NodeJS 現(xiàn)代框架似乎都沒有受到熏陶 - 架構(gòu)的靈活性。
有人可能會(huì)說 - 這不是決定項(xiàng)目架構(gòu)的框架問題。 那么,我完全同意這一點(diǎn),但是我們幾乎在每個(gè)項(xiàng)目中都會(huì)看到一些眾所周知的概念和模式。 在我看來,如果一個(gè)框架將開發(fā)人員推向了良好的架構(gòu)決策,這是一件好事。
NestJS 到底是什么?
根據(jù)該項(xiàng)目的網(wǎng)站:
NEST 是構(gòu)建高效,可擴(kuò)展的 NodeJS 服務(wù)器端應(yīng)用程序的框架。
這與 Node.js 語言相同,所以區(qū)別在哪里? 那么,重點(diǎn)是在細(xì)節(jié):
它使用現(xiàn)代JavaScript,使用Typescript(保留與純 JavaScript 的兼容性)構(gòu)建,并結(jié)合了OOP,F(xiàn)P 和 FRP 的元素。
就是這樣。 Nest 框架以一種非?;钴S的方式鼓勵(lì)開發(fā)人員嘗試,學(xué)習(xí)和使用一些著名的軟件工程范例。這不僅是介紹性的口號(hào) - 在項(xiàng)目文檔中我們找到了很多示例,指導(dǎo)和代碼源,以便我們可以在幾分鐘內(nèi)在項(xiàng)目中使用它們。
此外,所有這些新詞匯的 NestJS 給我們參考它背后的知識(shí)。 所以如果你不知道一些模式 - 不用擔(dān)心,你將會(huì)順利地完成整個(gè)過程。
一些特性
NestJS 是一個(gè)完全用 TypeScript 編寫的框架(它也支持 JS),它很容易測(cè)試,并且?guī)砹怂斜匾臇|西,你總是但您不知道該選什么。
- 依賴注入容器 - NestJS 帶有自己的DiC,這是一個(gè)在 JavaScript 世界中似乎被遺忘的實(shí)用工具,但我真的不能沒有它。 有一些解決方案像 Inversify 或 Bottle,但 NestJS 有自己的解決方案。 它也支持工廠注入。
- 模塊化 - 在NestJS中,處于相同域邊界內(nèi)的應(yīng)用程序的每個(gè)邏輯部分都是一個(gè)模塊,它鼓勵(lì)封裝。
- 可測(cè)試性 - 由于引入了 DiC 和 Modularisation,您可以根據(jù)服務(wù)構(gòu)建應(yīng)用程序, 使控制器的工作更容易進(jìn)行測(cè)試。
- 使用 TypeScript中 - 類型很好。 你可以給一個(gè)變量分配類型,減少可能出現(xiàn)的錯(cuò)誤。
入門:構(gòu)建一個(gè)簡(jiǎn)單的天氣應(yīng)用程序
在這篇文章中,我們將使用 Nest 框架和 OpenWeatherMap API 編寫一個(gè)簡(jiǎn)單的天氣應(yīng)用程序。
準(zhǔn)備項(xiàng)目
首先,讓我們確保你已經(jīng)安裝了支持的 Node.js 版本:
node -v
需要高于 6.11.0 。 如果您沒有安裝Node.js或版本不正確,請(qǐng)安裝或更新。
第二步是從 OpenWeatherMap 網(wǎng)站檢索API密鑰。 為了實(shí)現(xiàn)我們需要注冊(cè)的功能,成功注冊(cè)后,我們將能夠從 API密鑰標(biāo)簽中檢索我們的API密鑰 。
準(zhǔn)備就緒了。 讓我們來設(shè)置這個(gè)項(xiàng)目。 為此,我將使用 Nest 的 TypeScript 初學(xué)者存儲(chǔ)庫(kù)(還有一種方法可以從頭開始構(gòu)建項(xiàng)目,但我很懶)。 它提供了良好的初學(xué)者體驗(yàn),并擁有開始編寫代碼所需的一切。
$ git clone https://github.com/nestjs/typescript-starter.git project
$ cd weather-app /
安裝依賴關(guān)系并啟動(dòng):
$ npm i
$ npm run start
當(dāng)安裝了項(xiàng)目依賴關(guān)系并且應(yīng)用程序成功啟動(dòng)后,您應(yīng)該在控制臺(tái)中看到以下輸出,并在瀏覽器中指向 http://localhost:3000/ 的url,應(yīng)該會(huì)給您熱情而歡迎的Hello World! 文本。
> nest-typescript-starter@1.0.0 start /Users/mat/Development/weather-app> node index.js
[Nest] 31827 - 2018-1-13 11:39:32 [NestFactory] Starting Nest application...
[Nest] 31827 - 2018-1-13 11:39:32 [InstanceLoader] ApplicationModule dependencies initialized +7ms
[Nest] 31827 - 2018-1-13 11:39:32 [RoutesResolver] AppController {/}: +34ms
[Nest] 31827 - 2018-1-13 11:39:32 [RouterExplorer] Mapped {/, GET} route +2ms
[Nest] 31827 - 2018-1-13 11:39:32 [NestApplication] Nest application successfully started +1ms
安裝 HTTP 客戶端
我們已經(jīng)建立了項(xiàng)目,獲取天氣數(shù)據(jù)的 API密鑰和開發(fā)服務(wù)器,隨時(shí)準(zhǔn)備交付。
我們現(xiàn)在安裝一個(gè)HTTP客戶端,在這個(gè)區(qū)域我的個(gè)人偏好是 axios 。 為什么選擇axios? 這是一個(gè)基于Promise 的客戶端,它支持服務(wù)器端和客戶端,并提供許多有用的功能,如:對(duì)JSON轉(zhuǎn)換的自動(dòng)響應(yīng)和專用的工具 - moxios--使測(cè)試變得順暢和輕松。
$ npm i --save axios
建立***個(gè)服務(wù)
現(xiàn)在我們可以開始構(gòu)建我們的***個(gè)服務(wù)
為了做到這一點(diǎn),讓我們?cè)谖覀兊?src/ 文件夾中創(chuàng)建一個(gè)名為 weather.service.t s的文件:
import { Component } from '@nestjs/common';
import axios, { AxiosInstance } from 'axios';
@Component()
export class WeatherService {
private client: AxiosInstance;
constructor() {
this.client = axios.create({
baseURL: 'https://api.openweathermap.org/data/2.5/',
params: {
APPID: 'CHANGE_ME'
}
});
}
async ofCity(city: string): object {
const response = await this.client.get('weather', {
params: { q: city }
});
return response.data;
}
}
我們正在創(chuàng)建一個(gè)封裝 HTTP 客戶端的類,以實(shí)現(xiàn)實(shí)際的 API 調(diào)用。 有一點(diǎn)需要注意的是類裝飾器 @Component(),多虧了它,框架才會(huì)知道這是我們想要在 DiC 中注冊(cè)的組件。 它有一種方法,這是異步的 - 它會(huì)返回一個(gè)Promise - 返回到控制器將由 Nest 處理。
HTTP通信層
接下來我們需要建立的是控制器。 在src /文件夾中創(chuàng)建一個(gè)名為 weather.controller.ts 的文件:
import { Get, Controller } from '@nestjs/common';
import { WeatherService } from './weather.service';
@Controller('weather')
export class WeatherController {
constructor(private readonly weatherService: WeatherService) {}
@Get()
async root(): Promise< object > {
const response = await this.weatherService.forCity('New York');
return response;
}
裝飾器 @Controller('weather')告訴框架我們期望這個(gè)控制器在 / weather 路由上作出響應(yīng)。
然后,我們?cè)陬悩?gòu)造函數(shù)中注入了我們的 WeatherService ,并將其設(shè)置為名為weatherService 的私有屬性。
***是一個(gè)稱為 root 的異步操作,它返回一個(gè)Promise,最終解析為一個(gè)對(duì)象。 它內(nèi)部調(diào)用我們的 weatherService 并獲得紐約的實(shí)際天氣預(yù)報(bào)。
連接點(diǎn)
為了使我們的應(yīng)用程序正常工作,我們需要做的***一件事是將應(yīng)用程序模塊中的所有部分連接在一起:
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { WeatherController } from './weather.controller';
import { WeatherService } from './weather.service';
@Module({
imports: [],
controllers: [AppController, WeatherController],
components: [WeatherService],
})export class ApplicationModule {}
保存文件,重啟你的開發(fā)服務(wù)器,當(dāng)你在瀏覽器中導(dǎo)航到url http://127.0.0.1:3000/weather 時(shí),你會(huì)看到天氣服務(wù)的響應(yīng)。
上面的代碼是為了顯示我們?nèi)绾慰焖俚卦?NestJS 中構(gòu)建一個(gè)好的東西。然而, 我看到一些改進(jìn), 這還沒有做, 因?yàn)槲蚁氡3趾?jiǎn)單:
- 返回類型的接口。 我們可以充分利用 TypeScript 和強(qiáng)類型所有的東西
- 錯(cuò)誤處理。 當(dāng) promise 不是 resolve 時(shí),我們的控制器很可能會(huì)中斷
- 測(cè)試套件。 我們還沒有寫任何測(cè)試
- 我們要返回整個(gè)數(shù)據(jù) blob。我們只能去掉我們關(guān)心的值
概要
我們從理論上討論了NestJS并做了一個(gè)實(shí)際的例子。 欲了解更多信息,請(qǐng)參閱框架的官方文檔,其中包含大量隨時(shí)可用的指導(dǎo)和代碼片段。
Node.js 是為了擴(kuò)展和實(shí)現(xiàn)實(shí)時(shí)網(wǎng)絡(luò)應(yīng)用程序的高效開發(fā)而創(chuàng)建的,它非常好。
現(xiàn)在我們已經(jīng)有了 NestJS 框架來解決架構(gòu)問題。
中文文檔: https://docs.nestjs.cn
英文官方文檔:https://docs.nestjs.com