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();
原文地址:https://www.cnblogs.com/zzghk/p/15225775.html