Nest快速上手


Nest

官網:https://nestjs.com/
中文網站:https://docs.nestjs.cn/
評價: https://mp.weixin.qq.com/s/Y67O9ks-qPwVF8UqHaRY-g
Nest 是一個漸進的 Node.js 框架,可以在 TypeScript 和 JavaScript (ES6、ES7、ES8)之上構建高效、可伸縮的企業級服務器端應用程序。
Nest 基於 TypeScript 編寫並且結合了 OOP(面向對象編程),FP(函數式編程)和 FRP (函數式響應編程)的相關理念。在設計上的很多靈感來自於 Angular,Angular 的很多模式又來自於 Java 中的 Spring 框架,依賴注入、面向切面編程等,所以我們也可以認為:Nest 是 Node.js 版的 Spring 框架。
Nest 框架底層 HTTP 平台默認是基於 Express 實現的,所以無需擔心第三方庫的缺失。
Nest 旨在成為一個與平台無關的框架。 通過平台,可以創建可重用的邏輯部件,開發人員可以利用這些部件來跨越多種不同類型的應用程序。
從技術上講,Nest 可以在創建適配器后使用任何 Node HTTP 框架。有兩個支持開箱即用的 HTTP 平台:express 和 fastify。您可以選擇最適合您需求的產品。
NestJs 的核心思想:就是提供了一個層與層直接的耦合度極小,抽象化極高的一個架構體系。

建立項目

//安裝Nest CLI
npm i -g @nestjs/cli .

//使用Nest CLI 創建項目
nest new project-name

// 運行項目
npm run start

src目錄核心文件

app.controller.ts 帶有單個路由的基本控制器示例。
app.module.ts 應用程序的根模塊。
main.ts 應用程序入口文件。它使用 NestFactory 用來創建 Nest 應用實例。

NEST命令行工具

nest --help

可以列出命令行的主要命令以及幫助

創建

  • new(簡寫n)[options] [name] :創建一個NEST應用,例如 nest n hello-world。選項中支持:
    • --directory 指定目標目錄
    • -d或--dry-run  不輸出創建過程中的報告
    • -g或--skip-git  不要初始化git倉庫(默認是會在項目創建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] 調試模式
    • --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 在工作區中創建一個新的應用
class cl 新的類
configuration config 命令行的配置文件
controller co 控制器
decorator d 自定義裝飾器
filter f 過濾器
gateway ga 請求的網關
guard gu 守衛
interceptor in 攔截器
interface interface 接口
middleware mi 中間件
module mo 模塊
pipe pi 管道
provider pr 功能組
resolver r GraphQL處理器
service s 服務
library lib 單獨庫模式下創建一個庫
sub-app app 子應用
resource res 一個數據模型的CRUD

平台

Nest 旨在成為一個與平台無關的框架。 通過平台,可以創建可重用的邏輯部件,開發人員可以利用這些部件來跨越多種不同類型的應用程序

有兩個支持開箱即用的 HTTP 平台:expressfastify
暴露自己的 API分別是 NestExpressApplication 和 NestFastifyApplication

const app = await NestFactory.create<NestExpressApplication>(AppModule);

控制器

控制器負責處理傳入的 請求 和向客戶端返回 響應
創建一個基本的控制器:類和裝飾器
CLI 創建控制器

$ nest g controller cats

路由

Nestjs 中沒有單獨配置路由的地方。定義好控制器后 nestjs 會自動給我們配置對應的路由

  //中控制器內直接用裝飾器匹配路由
  @Get()
  index() {
    //輸出內容
    return '我是article控制器get請求';
  }

兩種不同的操作響應:** 標准(推薦)和 類庫**

關於 nest 的 return: 當請求處理程序返回 JavaScript 對象或數組時,它將自動序列化為JSON。但是,當它返回一個字符串時,Nest 將只發送一個字符串而不是序列化它。這使響應處理變得簡單:只需要返回值,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 標准方法

裝飾器

裝飾器將類與所需的元數據相關聯,並使 Nest 能夠創建路由映射

請求裝飾器

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 提交的數據

@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() {
    //輸出內容
    return '我是article控制器';
  }

  //路由拼接article/add
  @Get('add')
  //獲取url裝飾器(get參數)
  addArticle(@Query() query) {
    console.log(query)
    //輸出內容
    return '我是article/add';
  }

  @Get('edit')
  //request裝飾器獲取請求信息
  editArticle(@Request() req){
    console.log(req.query)
    return "我是article/edit"
  }

  @Post('create')
  //Body裝飾器獲取post內容
  create(@Body() body){
    console.log(body)
    return '我是Post請求'
  }
  
}

狀態碼

@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';
  }
}

動態路由

不常用
注意動態路由要放在下面,不然會先匹配,下面路由匹配不成功

import {Controller, Get, Param, Query} from '@nestjs/common';

@Controller('news')
export class NewsController {

  @Get()
  addDate(@Query('id') id){
    console.log(id)
    return "獲取里面參數"
  }

  //news/123
  @Get(":id")
  index(@Param() param){
    //{id: '123'}
    console.log(param)
    return "我是動態路由"
  }
}

請求負載

使用 TypeScript, POST接受客戶端參數,需要確定 DTO(數據傳輸對象)模式
DTO是一個對象,它定義了如何通過網絡發送數據,通過使用 TypeScript接口或簡單的類實現(推薦使用類)

區別:類是JavaScript ES6標准的一部分,因此它們在編譯后的 JavaScript中保留為實際實體。另一方面,由於 TypeScript接口在轉換過程中被刪除

創建 CreateCatDto 類

create-cat.dto.ts

export class CreateCatDto {
  readonly name: string;
  readonly age: number;
  readonly breed: string;
}

它只有三個基本屬性。 之后,我們可以在 CatsController中使用新創建的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`;
  }
}

最后一步

控制器已經准備就緒,但是 Nest 不知道 CatsController 是否存在

app.module.ts

import { Module } from '@nestjs/common';
import { CatsController } from './cats/cats.controller';

@Module({
  controllers: [CatsController],
})
export class AppModule {}

使用 @Module()裝飾器將元數據附加到模塊類,Nest 現在可以輕松反映必須安裝的控制器

配置靜態資源

nest若要加載靜態資源則需要配置靜態資源目錄
入口文件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');  //配置靜態資源目錄
  app.useStaticAssets(join(__dirname, '..', 'public'), {   //配置虛擬目錄
    prefix: '/static/', //設置虛擬路徑
  });
  await app.listen(3000);
}
bootstrap();


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM