Nest快速上手
Nest
官網(wǎng):https://nestjs.com/
中文網(wǎng)站:https://docs.nestjs.cn/
評價: https://mp.weixin.qq.com/s/Y67O9ks-qPwVF8UqHaRY-g
Nest 是一個漸進的 Node.js 框架,可以在 TypeScript 和 JavaScript (ES6、ES7、ES8)之上構建高效、可伸縮的企業(yè)級服務器端應用程序。
Nest 基于 TypeScript 編寫并且結合了 OOP(面向對象編程),F(xiàn)P(函數(shù)式編程)和 FRP (函數(shù)式響應編程)的相關理念。在設計上的很多靈感來自于 Angular,Angular 的很多模式又來自于 Java 中的 Spring 框架,依賴注入、面向切面編程等,所以我們也可以認為:Nest 是 Node.js 版的 Spring 框架。
Nest 框架底層 HTTP 平臺默認是基于 Express 實現(xiàn)的,所以無需擔心第三方庫的缺失。
Nest 旨在成為一個與平臺無關的框架。 通過平臺,可以創(chuàng)建可重用的邏輯部件,開發(fā)人員可以利用這些部件來跨越多種不同類型的應用程序。
從技術上講,Nest 可以在創(chuàng)建適配器后使用任何 Node HTTP 框架。有兩個支持開箱即用的 HTTP 平臺:express 和 fastify。您可以選擇最適合您需求的產(chǎn)品。
NestJs 的核心思想:就是提供了一個層與層直接的耦合度極小,抽象化極高的一個架構體系。
建立項目
//安裝Nest CLI
npm i -g @nestjs/cli .
//使用Nest CLI 創(chuàng)建項目
nest new project-name
// 運行項目
npm run start
src目錄核心文件
| app.controller.ts | 帶有單個路由的基本控制器示例。 | 
|---|---|
| app.module.ts | 應用程序的根模塊。 | 
| main.ts | 應用程序入口文件。它使用 NestFactory 用來創(chuàng)建 Nest 應用實例。 | 
NEST命令行工具
nest --help
可以列出命令行的主要命令以及幫助
創(chuàng)建
new(簡寫n)[options] [name] :創(chuàng)建一個NEST應用,例如 nest n hello-world。選項中支持:
--directory 指定目標目錄
-d或--dry-run 不輸出創(chuàng)建過程中的報告
-g或--skip-git 不要初始化git倉庫(默認是會在項目創(chuàng)建git倉庫)
-s或--skip-install 不要安裝依賴哭
-p或--package-manager [name] 指定包管理工具
-l或--language [lang] 指定語言JS或者TS
-c或--collection [name] 用特定的架構生成項目
構建
build [options] [app] : 構建項目,默認會將TS文件構建到項目的dist目錄中;options有:
-c或--config [path] 用cli構建時特定的配置文件
-p或--path [path] tsconfig配置文件
-w或--watch 實時重加載,觀察模式
--watchAssets 觀察非ts文件模式
--webpackPath [path] webpack的配置文件
--tsc 使用tsc編譯
運行
start [options] [app]:運行NEST項目,options有:
-c或--config [path] 用cli構建時特定的配置文件
-p或--path [path] tsconfig配置文件
-w或--watch 實時重加載,觀察模式
--watchAssets 觀察非ts文件模式
-d或--debug [hostport] 調(diào)試模式
--webpack用webpack編譯
--webpackPath [path] webpack的配置文件
--tsc 使用tsc編譯
-e或--exec [binary] 以二進制運行(默認用node)
--preserveWatchOutput tsc的觀察模式
更新
update或u [options]:更新當前項目的依賴組件
-f或--force 強制重新安裝依賴
-t或--tag 升級被打上(latest | beta | rc | next tag)的組件
Nest架構元素
其類型如下表:
| 名稱 | 別名 | 說明 | 
|---|---|---|
| application | application | 在工作區(qū)中創(chuàng)建一個新的應用 | 
| class | cl | 新的類 | 
| configuration | config | 命令行的配置文件 | 
| controller | co | 控制器 | 
| decorator | d | 自定義裝飾器 | 
| filter | f | 過濾器 | 
| gateway | ga | 請求的網(wǎng)關 | 
| guard | gu | 守衛(wèi) | 
| interceptor | in | 攔截器 | 
| interface | interface | 接口 | 
| middleware | mi | 中間件 | 
| module | mo | 模塊 | 
| pipe | pi | 管道 | 
| provider | pr | 功能組 | 
| resolver | r | GraphQL處理器 | 
| service | s | 服務 | 
| library | lib | 單獨庫模式下創(chuàng)建一個庫 | 
| sub-app | app | 子應用 | 
| resource | res | 一個數(shù)據(jù)模型的CRUD | 
平臺
Nest 旨在成為一個與平臺無關的框架。 通過平臺,可以創(chuàng)建可重用的邏輯部件,開發(fā)人員可以利用這些部件來跨越多種不同類型的應用程序
有兩個支持開箱即用的 HTTP 平臺:express 和 fastify
暴露自己的 API分別是 NestExpressApplication 和 NestFastifyApplication
const app = await NestFactory.create<NestExpressApplication>(AppModule);
控制器
控制器負責處理傳入的 請求 和向客戶端返回 響應
創(chuàng)建一個基本的控制器:類和裝飾器
CLI 創(chuàng)建控制器
$ nest g controller cats
路由
Nestjs 中沒有單獨配置路由的地方。定義好控制器后 nestjs 會自動給我們配置對應的路由
  //中控制器內(nèi)直接用裝飾器匹配路由
  @Get()
  index() {
    //輸出內(nèi)容
    return '我是article控制器get請求';
  }
兩種不同的操作響應:** 標準(推薦)和 類庫**
?
關于 nest 的 return: 當請求處理程序返回 JavaScript 對象或數(shù)組時,它將自動序列化為JSON。但是,當它返回一個字符串時,Nest 將只發(fā)送一個字符串而不是序列化它。這使響應處理變得簡單:只需要返回值,Nest 負責其余部分。
類庫響應方式
通過 @Res() 注入類庫特定的 響應對象
import { Controller, Get, Post, Res, HttpStatus } from '@nestjs/common';
import { Response } from 'express';
@Controller('cats')
export class CatsController {
  @Post()
  create(@Res() res: Response) {
    res.status(HttpStatus.CREATED).send();
  }
  @Get()
  findAll(@Res() res: Response) {
     res.status(HttpStatus.OK).json([]);
  }
}
類庫方式失去了與依賴于 Nest 標準響應處理的 Nest 功能的兼容性,例如攔截器和 @HttpCode() 裝飾器。此外,您的代碼可能變得依賴于平臺(因為底層庫可能在響應對象上有不同的 API),并且更難測試(您必須模擬響應對象等)。因此,在可能的情況下,應始終首選 Nest 標準方法
裝飾器
裝飾器將類與所需的元數(shù)據(jù)相關聯(lián),并使 Nest 能夠創(chuàng)建路由映射
請求裝飾器
Nestjs也提供了其他HTTP請求方法的裝飾器 @Put() 、@Delete()、@Patch()、 @Options()、 @Head()和 @All()
用法都差不多
import { Controller, Get } from '@nestjs/common';
@Controller('cats')
export class CatsController {
  @Get()
  findAll(): string {
    return 'This action returns all cats';
  }
}
獲取Get 傳值或者Post 提交的數(shù)據(jù)
| @Request() | req | 
|---|---|
| @Response() | res | 
| @Next() | next | 
| @Session() | req.session | 
| @Param(key?: string) | req.params / req.params[key] | 
| @Body(key?: string) | req.body / req.body[key] | 
| @Query(key?: string) | req.query / req.query[key] | 
| @Headers(name?: string) | req.headers / req.headers[name] | 
import {Body, Controller, Get, Post, Query, Request} from '@nestjs/common';
@Controller('article')
export class ArticleController {
  //get請求
  @Get()
  index() {
    //輸出內(nèi)容
    return '我是article控制器';
  }
  //路由拼接article/add
  @Get('add')
  //獲取url裝飾器(get參數(shù))
  addArticle(@Query() query) {
    console.log(query)
    //輸出內(nèi)容
    return '我是article/add';
  }
  @Get('edit')
  //request裝飾器獲取請求信息
  editArticle(@Request() req){
    console.log(req.query)
    return "我是article/edit"
  }
  @Post('create')
  //Body裝飾器獲取post內(nèi)容
  create(@Body() body){
    console.log(body)
    return '我是Post請求'
  }
  
}
狀態(tài)碼
@HttpCode
@Post()
@HttpCode(204)
create() {
  return 'This action adds a new cat';
}
重定向
@Redirect()
@Get()
@Redirect('https://nestjs.com', 301)
子域路由
@Controller 裝飾器可以接受一個 host 選項,以要求傳入請求的 HTTP 主機匹配某個特定值
@Controller({ host: 'admin.example.com' })
export class AdminController {
  @Get()
  index(): string {
    return 'Admin page';
  }
}
動態(tài)路由
不常用
注意動態(tài)路由要放在下面,不然會先匹配,下面路由匹配不成功
import {Controller, Get, Param, Query} from '@nestjs/common';
@Controller('news')
export class NewsController {
  @Get()
  addDate(@Query('id') id){
    console.log(id)
    return "獲取里面參數(shù)"
  }
  //news/123
  @Get(":id")
  index(@Param() param){
    //{id: '123'}
    console.log(param)
    return "我是動態(tài)路由"
  }
}
請求負載
使用 TypeScript, POST接受客戶端參數(shù),需要確定 DTO(數(shù)據(jù)傳輸對象)模式
DTO是一個對象,它定義了如何通過網(wǎng)絡發(fā)送數(shù)據(jù),通過使用 TypeScript接口或簡單的類實現(xiàn)(推薦使用類)
區(qū)別:類是JavaScript ES6標準的一部分,因此它們在編譯后的 JavaScript中保留為實際實體。另一方面,由于 TypeScript接口在轉換過程中被刪除
創(chuàng)建 CreateCatDto 類
create-cat.dto.ts
export class CreateCatDto {
  readonly name: string;
  readonly age: number;
  readonly breed: string;
}
它只有三個基本屬性。 之后,我們可以在 CatsController中使用新創(chuàng)建的DTO
cats.controller.ts
@Post()
async create(@Body() createCatDto: CreateCatDto) {
  return 'This action adds a new cat';
}
完整示例
import { Controller, Get, Query, Post, Body, Put, Param, Delete } from '@nestjs/common';
import { CreateCatDto, UpdateCatDto, ListAllEntities } from './dto';
@Controller('cats')
export class CatsController {
  @Post()
  create(@Body() createCatDto: CreateCatDto) {
    return 'This action adds a new cat';
  }
  @Get()
  findAll(@Query() query: ListAllEntities) {
    return `This action returns all cats (limit: ${query.limit} items)`;
  }
  @Get(':id')
  findOne(@Param('id') id: string) {
    return `This action returns a #${id} cat`;
  }
  @Put(':id')
  update(@Param('id') id: string, @Body() updateCatDto: UpdateCatDto) {
    return `This action updates a #${id} cat`;
  }
  @Delete(':id')
  remove(@Param('id') id: string) {
    return `This action removes a #${id} cat`;
  }
}
最后一步
控制器已經(jīng)準備就緒,但是 Nest 不知道 CatsController 是否存在
app.module.ts
import { Module } from '@nestjs/common';
import { CatsController } from './cats/cats.controller';
@Module({
  controllers: [CatsController],
})
export class AppModule {}
使用 @Module()裝飾器將元數(shù)據(jù)附加到模塊類,Nest 現(xiàn)在可以輕松反映必須安裝的控制器
配置靜態(tài)資源
nest若要加載靜態(tài)資源則需要配置靜態(tài)資源目錄
入口文件src/main
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
//入口文件引入express平臺HTTP平臺
import { NestExpressApplication } from '@nestjs/platform-express'
//引入path模塊的join方法
import {join} from "path";
async function bootstrap() {
  const app = await NestFactory.create<NestExpressApplication>(AppModule);
  // app.useStaticAssets('public');  //配置靜態(tài)資源目錄
  app.useStaticAssets(join(__dirname, '..', 'public'), {   //配置虛擬目錄
    prefix: '/static/', //設置虛擬路徑
  });
  await app.listen(3000);
}
bootstrap();
總結
 
                            
                        - 上一篇: 橄榄油为什么那么贵?
- 下一篇: 车辆状态更新的时间是什么意思?
