熟悉 NestJS (文末附视频)

news2024/9/23 0:33:50

前言

经过了需求分析以及技术选型之后,我们正式步入了第三个环节:脚手架搭建

工欲善其事,必先利其器NestJS 为开发者提供了很多开箱即用的功能,我们可以根据团队的需求搭建一套适配所有业务开发的基础脚手架。所以接下来的 2 章是基础篇的教学,将带领大家逐步的学习与搭建一套基础业务脚手架,便于后期快速开发业务。

本章的内容比较基础,如果使用过 NestJs 的同学或者对 IoC 模式熟悉的同学可以快速略过。

控制反转 IoC

在之前的介绍中有提到,NestJS 作为开发体验上最接近于传统后端的开发框架,其中最大的相同点就是 IoC,也就是 JAVA 中经常提到的控制反转

在接下去使用 NestJS 的开发过程中会大量接触到 IoC 模式,所以先对 IoC 做一个简单概念解析,了解一下什么是 IoC,以及为什么要使用 IoC

控制反转(Inversion of Control,缩写为 IoC)是面向对象编程中的一种设计原则,可以用来降低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。

如果学过 JAVA 的同学应该会比较熟悉,但如果是前端同学刚刚接触的话,可能会比较陌生,一时间难以上手。纯文字版本的解释难免晦涩,接下来我们用一个简单的小例子来解释 IoC 容器的使用:

class A {
  constructor(params) {
    this.params = params
  }
}

class B extends A {
  constructor(params) {
    super(params)
  }
  run() {
    console.log(this.params);
  }
}

new B('hello').run();

我们可以看到,B 中代码的实现是需要依赖 A 的,两者的代码耦合度非常高。当两者之间的业务逻辑复杂程度增加的情况下,维护成本与代码可读性都会随着增加,并且很难再多引入额外的模块进行功能拓展

为了解决这个情况,我们可以引入一个 IoC 容器:

class A {
  constructor(params) {
    this.params = params
  }
}

class C {
  constructor(params) {
    this.params = params
  }
}

class Container {
  constructor() { this.modules = {} }

  provide(key, object) { this.modules[key] = object }

  get(key) { return this.modules[key] }
}

const mo = new Container();

mo.provide('a', new A('hello'))
mo.provide('c', new C('world'))

class B {
  constructor(container) {
    this.a = container.get('a');
    this.c = container.get('c');
  }
  run() {
    console.log(this.a.params + ' ' + this.c.params)
  }
}

new B(mo).run();

如上述代码所示,在引入 IoC 容器 container 之后,B 与 A 的代码逻辑已经解耦,可以单独拓展其他功能,也可以方便地加入其他模块 C。所以在面对复杂的后端业务逻辑中,引入 IoC可以降低组件之间的耦合度,实现系统各层之间的解耦,减少维护与理解成本。

当然,上述的 Demo 只是一个非常简单的例子,实际开发过程中场景远比 Demo 更加复杂。

Nest CLI

与所有的主流框架一样,NestJs 也有自己的 Nest CLI 工具,除了提供创建基础模板的功能之外,额外提供了很多方便的功能。

与前端项目的开发模式不同,在后端业务开发中存在着大量可复用或者有规则的模块,善于使用 CLI 可以帮助我们节约大量的重复工作,现在我们来一起学一下 CLI 的运用。首先看下 CLI 提供了多少的功能:

$ nest --help

如上图所示,运行完 help 命令之后,可以使用 generate 便捷地生成常用文件,例如超频使用的 Controller 以及 Service 的文件等。

使用规则

除了 nest --help 查看全局命令之外,运行nest <command> --help 可以查看特定于命令的选项。

命令别名描述
newn搭建一个新的标准模式应用程序,包含所有需要运行的样板文件。
generateg根据原理图生成或修改文件。

通用的命令选项

选项描述
--dry-run报告将要进行的更改,但不更改文件系统,别名: -d。
--skip-git跳过 git 存储库初始化,别名: -g。
--skip-install跳过软件包安装,别名:-s。
--package-manager [package-manager]指定包管理器,使用 npm 或 yarn,必须全局安装包管理器,别名: -p。
--language [language]指定编程语言(TS 或 JS),别名: -l。
--collection [collectionName]指定逻辑示意图集合,使用已安装的包含原理的 npm 软件包的软件包名称,别名:-c。

在常规项目中,使用创建模板和文件这两个命令最多,所以小册只列举了这两个功能,如果你想了解更多的 CLI 功能可以直接查看源文档。

配置规则

直接通过 CLI 创建的项目根路径下会自动生成一个 nest-cli.json 配置文件:

{
  "$schema": "https://json.schemastore.org/nest-cli",
  "collection": "@nestjs/schematics",
  "root": "src"
}

默认生成的配置文件有如上一些属性:

配置属性属性描述
collection用于配置生成部件的 schematics 组合的点,一般无需修改
sourceRoot默认项目根目录
------
compilerOptions编译选项与设置
generateOptions全局生成的选项和选项的设置
monorepo启用 monorepo
projectmonorepo 模式结构项目配置
------
assets额外文件类型资源处理,非 TS 与 JS 类型
watchAssets是否使用 watch 模式来监控指定资源文件

monorepo 模式开发有它的优点,如果是个人维护或者是关联性比较高的项目可以尝试使用 monorepo 来开发项目,但是小册选择的网关项目拆出的三个模块虽然有一定的关系,但物料以及用户系统同时还会与 DevOps 等其他系统有关联,所以会使用 multirepo 维护三个不同的项目,以微服务的模式关联各个模块功能。

创建项目工程模板

在查看完 Nest CLI 的常用命令之后,可以使用以下命令快速创建一个简单的工程模板:

$ npm i -g @nestjs/cli
$ nest new gateway

项目文件介绍

除去配置常见的配置文件之外,在 src 目录下有一些 Nestjs 标准的文件规范:

src
 ├── app.controller.spec.ts
 ├── app.controller.ts
 ├── app.module.ts
 ├── app.service.ts
 └── main.ts
文件名文件描述
app.controller.ts常见功能是用来处理 http 请求以及调用 service 层的处理方法
app.module.ts根模块用于处理其他类的引用与共享。
app.service.ts封装通用的业务逻辑、与数据层的交互(例如数据库)、其他额外的一些三方请求
main.ts应用程序入口文件。它使用 NestFactory 用来创建 Nest 应用实例。

在后续开发项目的过程中,使用约定俗成的 name.[type] 规则来创建对应的类型文件,便于查找对应的模块。

第一个 http 请求

再依赖安装完毕之后,可以使用如下命令启动 NestJS 应用,然后浏览器即可访问 http://localhost:3000/ :出现如下界面即代表项目已经正常启动了。

$ npm run start

服务正常启动之后,接下来我们要开始写下第一个功能【用户模块】。

首先运行如下命令,CLI 会快速帮助我们自动生成一个用户的 UserController

$ nest g co user

不过此命令同时也会生成后缀为 spec 的测试文件,虽然有测试功能非常好,但在快速开发过程中,并非每一个功能都需要自动化测试覆盖,只要保证主要的功能有用例覆盖即可。

如果不需要每一次生成 spec 文件,可以在根目录下的 nest-cli.json 添加如下配置,禁用测试用例生成,后续再使用 CLI 创建 Controller 或者 Service 类型文件的时候,将不会继续生成:

  "generateOptions": {
    "spec": false
  }

回归正题,再创建 UserController 的同时 CLI 也会自动在 app.module.ts 里面帮我们注册好 Controller。整个过程非常简便,只要在 UserController 写下第一个 http 请求即可。

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

@Controller('user')
export class UserController {
  @Get()
  getHello(): string {
    return 'hello, world!';
  }
}

等待程序重新编译运行完毕之后,在浏览器输入 http://localhost:3000/user 访问即可看到:【你好,世界!

第一个 CURD

在小试牛刀之后,下面我们要开始借助 CLI 的能力快速生成 CURD 模块:

  • 生成一个模块 (nest g mo) 来组织代码,使其保持清晰的界限(Module)。
  • 生成一个控制器 (nest g co) 来定义CRUD路径(Controller)。
  • 生成一个服务 (nest g s) 来表示/隔离业务逻辑(Service)。
  • 生成一个实体类/接口来代表资源数据类型(Entity)。

可以看出一个最简单的 CURD 涉及的模块也会非常多(至少需要以上四个模块才能完成一个基础的 CURD 功能),并且要运行多个命令才能得到想要的结果,所幸 Nest CLI 已经集成了这样的功能来帮助我们减少重复的工作量:

$ nest g resource user 

之前我们已经生成 user 的 controller 文件,所以在使用此条命令之前需要将之前生成的 user 目录全部删除,同时删除 app.module.ts 中的 UserController 引入。

第一次使用这个命令的时候,除了生成文件之外还会自动使用 npm 帮我们更新资源,安装一些额外的插件,后续再次使用就不会更新了。

安装依赖之后可以看到,我们借助了 Nest CLI 快速的生成了一套标准的 CURD 模块甚至 dto 文件也一并生成了,后续只需要更新用户模块的业务逻辑即可。

写在最后

本章主要是介绍了 IoC 设计模式以及如何借助 CLI 创建了简单的工程模板与 CURD 模块。可以看到 Nest CLI 对比其他一些 CLI 工具,在针对开发功能优化这块做得非常不错,特别是模块生成跟自动注册这块逻辑。不过,也是基于后端有一套规则可循,这些功能才能实现,这也正是前后端项目不太一样的地方。

虽然 NestJs 提供了一个简单的工程模板,但这个模板离实际可用的工程差距还有点大,接下来将与大家一起逐步添加对应的功能,使之达到一个符合实际项目开发要求的模板。

基础篇的内容大部分都是围绕着 NestJS 提供的功能模块开发,所以有一些细节的部分可以参考 NestJS 的英文文档一起阅读,小册中使用到的部分会尽可能讲解得详细一点。

本章的 Demo 地址放在 demo/v1,需要的同学自取。

如果你有什么疑问,欢迎在评论区提出或者加群沟通。 👏

NestJS 项目实战 - CookieBoty - 掘金小册从 0 搭建网关系统,玩转 NestJS 开发。「NestJS 项目实战」由CookieBoty撰写,2309人购买https://s.juejin.cn/ds/kb86fX9/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/171703.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

帮助有一定计算机基础的人 快速复习并重新拾起C语言基础

这里写目录标题1.C语言程序举例2.详解C语言程序结构1&#xff09;#include2&#xff09;main 函数&#xff1a;3&#xff09;{} 括号&#xff0c;程序体和代码块4&#xff09;注释5&#xff09;print 函数6&#xff09;return 语句3 C程序的编译步骤是怎样&#xff1f;4.数据的…

【Go基础】面向对象和反射机制

文章目录一、面向对象1. 面向对象的概念2. 构造函数3. 继承与重写4. 泛型二、反射1. 反射介绍2. 反射的基础数据类型3. 反射API3.1 reflect.Type①如何得到Type②指针Type转为非指针Type③获取struct成员变量的信息④获取struct成员方法的信息⑤获取函数的信息⑥判断类型是否实…

『 MySQL篇 』:MySQL表的CURD操作

&#x1f4e2; MySQL 系列专栏持续更新中 … MySQL专栏 ​ 目录 目录一、SQL语句- SQL通用语法- 注释- SQL语句分类二、 基础表操作- 创建表- 查看库中的表- 查看表结构- 删除表- 重命名表三、MySQL 中的增删查改操作- 增加&#xff08;insert语句&#xff09;- 查询(select语…

CSS 使用 @font-face 引入外部字体

CSS 使用 font-face 引入外部字体下载所需字体到本地把下载字体文件放入font文件夹里定义字体引用字体结果&#x1f62c;没有退路时&#xff0c;潜能就发挥出来了 CSS 中使用开源字体 得意黑 得意黑的字体是真的好看 ✨推荐使用 下载所需字体到本地 这里介绍一款不错的中文字…

Shiro:核心组件、配置类、多Realm场景、自定义拦截器、实战场景

目录Shiro 的核心组件Shiro 认证流程Shiro 授权流程单 RealmShiro 登陆认证 SimpleAuthenticationInfo 对象多 RealmShiroConfigShiro过滤器配置 ShiroFilterFactoryBeanShiro自定义过滤器Shiro 过滤器执行链路梳理代码自取层级结构Login.javaBearerTokenRealm.javaShiroRealm.…

桶排序详细说明及实现-python

前言&#xff1a; 说到桶排序&#xff0c;那必定要有桶&#xff0c;那么桶的作用是什么呢&#xff1f;桶的作用就是将序列分为若干份放到桶中&#xff0c;每个桶中能装入的数量范围是一定的&#xff0c;只有最后一个桶可以设置装入很多。这是因为当分的桶一定时&#xff0c;前面…

SpringMVC-基础入门

文章目录SpringMVC1&#xff0c;SpringMVC概述2&#xff0c;SpringMVC入门案例2.1 需求分析2.2 案例制作步骤1:创建Maven项目步骤2:补全目录结构步骤3:导入jar包步骤4:创建配置类步骤5:创建Controller类步骤6:使用配置类替换web.xml步骤7:配置Tomcat环境步骤8:启动运行项目步骤…

【软考】系统集成项目管理工程师(十五)项目采购管理

一、项目采购管理概述二、项目采购管理子过程1. 编制采购管理计划2. 实施采购3. 控制采购4. 结束采购三、招投标1. 招标人的权利和义务2. 招标代理机构的权利和义务3. 招标方式和招投标程序4. 相关的法律责任一、项目采购管理概述 采购意味着从外界来源获得商品或服务,采购一…

Vue3组件初始化流程分析

本文主要来分析 vue3 组件的初始化(基于runtime-core(核心运行时)包)&#xff0c;将从createApp、mount 等常用 API 入手来分析组件的挂载、普通元素的挂载流程。 createApp 1、创建一个应用实例。使用方式如下: import { createApp } from vue import App from ./App.vueco…

进制转换(二进制、八进制、十进制、十六进制)超详细版

今天来总结一下各种进制转换问题&#xff0c;详细齐全易于理解&#xff0c;希望对你有帮助哦&#xff01; 各种进制之间的相互转换 先从我们最熟悉的十进制入手吧&#xff0c;其他进制与十进制的转换方法都是一样的。 整型有4种进制形式&#xff1a; 1.十进制&#xff1a; …

[ChatGPT]

最近hatGPT火爆全宇宙&#xff0c;几乎所有圈内人都在谈论这个美国人工智能公司OpenAI发布免费机器人对话模型ChatGPT&#xff08;GPT-3.5系列&#xff09;&#xff0c;模型中首次采用RLHF&#xff08;从人类反馈中强化学习&#xff09;方式。模型目前处于测试阶段&#xff0c;…

Windows 服务器刷题(2)(带答案)

作者简介&#xff1a;一名云计算网络运维人员、每天分享网络与运维的技术与干货。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​​ 目录 前言 一.刷题 前言 本章将会讲解Windows服务器刷题&#xff08;2&#xff09; 一…

新年礼物已收到!2022 Apache IoTDB Commits 数量排名 3/351!

社区喜报&#xff01;据 The Apache Software Foundation 官方 Projects Statistics&#xff08;项目信息统计网站&#xff09;的实时数据显示&#xff0c;Apache IoTDB 在过去 12 个月&#xff08;即 2022 年度&#xff09;共发表 6829 Commits&#xff0c;排名 2022 年度 Apa…

C++ Primer笔记——默认移动操作、移动迭代器、左右值引用成员函数、标准库仿函数、function包装器

目录 一.P476 合成的移动操作 二.P480 移动迭代器 三.P483 右值和左值引用成员函数 四.P510 标准库定义的仿函数 五.P512 标准库function类型&#xff08;包装器&#xff09; 一.P476 合成的移动操作 什么时候会有默认的移动构造和移动赋值函数&#xff0c;需满足以下几点…

Java设计模式-中介者模式Mediator

介绍 中介者模式&#xff08;Mediator Pattern&#xff09;&#xff0c;用一个中介对象来封装一系列的对象交互。中介者使各个对象不需要显式地相互引用&#xff0c;从而使其耦合松散&#xff0c;而且可以独立地改变它们之间的交互。中介者模式属于行为型模式&#xff0c;使代…

linux搭建webapp实战

首先介绍下linux&#xff0c;linux因其开源&#xff0c;定制化高&#xff0c;安全等原因&#xff0c;成为了目前web应用部署首选的操作系统&#xff0c;linux操作系统有很多版本&#xff0c;常见的有centos&#xff0c;debian&#xff0c;RHLE&#xff0c;redhat&#xff0c;乌…

【Linux】gcc/g++编译器、make/Makefile自动化构建工具

作者&#xff1a;小卢 专栏&#xff1a;《Linux》 喜欢的话&#xff1a;世间因为少年的挺身而出&#xff0c;而更加瑰丽。 ——《人民日报》 目录 1.gcc/c的概念&#xff1a; 2.程序编译过程详解&#xff1a; 2.1程序编译过程&#xff1a; 2.…

微电网(风、光、储能、需求响应)【Simulink 仿真实现】

目录 1 展现 2 典型几个介绍 2.1 采用PR的三相逆变器电压控制 2.2 太阳能直流微电网系统 2.3 主电网故障时的交流微电网性能 2.4 混合光伏、双馈发电和电池能源的微电网集成 3 写在后面 4 完整资源 1 展现 随便打开一个&#xff0c;就以第一个&#xff08;采用PID的三…

【GD32F427开发板试用】macOS/Linux系统开发环境搭建(开发、编译、烧录、调试)

本篇文章来自极术社区与兆易创新组织的GD32F427开发板评测活动&#xff0c;更多开发板试用活动请关注极术社区网站。作者&#xff1a;HonestQiao 我日常的工作环境使用的是macOS系统或者Linux系统&#xff0c;万不得已才使用Windows。 GD32官方提供了Keil MDK-ARM和IAR两款工具…

如何使用Dx命令将jar打包成Dex,需要使用D8命令

使用dx打包的完整命令&#xff0c;将D:\ssh1.0.jar打包成MyClass.dex&#xff0c;MyClass.dex将会输出在当前CMD命令窗口的目录下。dx --dex --no-strict --min-sdk-version26 --outputMyClass.dex D:\ssh1.0.jar运行结果&#xff1a;不要使用dx命令&#xff0c;打出来的dex可以…