Nestjs入门教程【一】基础概念

4,693 阅读9分钟

没有尽头,没有开始,只有对生活无尽的热情。

  • 微信公众号 《JavaScript全栈
  • 掘金 《合一大师
  • 视频讲解:Bilibili 《合一大师

内容持续更新

介绍

为什么学习Nestjs

不知大家可否听说过 Java 语言大名鼎鼎的几个框架——SpringBoot、SpringMVC。不可否认这些框架的设计思想在后端服务领域都是领先的。作为以 Javascript 为主要开发语言的我们,也想有这样一些优秀的、渐进式的服务端框架,虽然在此之前有 ExpressKoaEgg 等基于Nodejs的服务端框架,但都不是我钟爱的,因为我入门编程就是使用Java的三大框架SSHMVC 也许是大多开发者所能接受的开发思想了,这里解释一下,M(Model模型即数据层)、V(View视图,现多为前后端分离项目,后端只提供接口服务)、C(Controller控制器,控制前端请求来的路由分发等)。明白这三点只是基础,随着业务不断复杂,我们需要管理的数据越来越多、数据库操作越来越复杂、关于性能缓存的要求越来越高,我们可能会变得束手无策。如何优雅地管理项目模块,变得尤为重要,我觉得 Nestjs 正是这样一个帮助我们更好开发的框架。我们开始学习吧!

Nestjs的主要思想

Nest (NestJS)是基于Nodejs的服务端框架,建议使用Typescript进行开发(不过也同样支持使用JavaScript开发)。通过这个框架学习,我们不仅能够打通前后端开发任督二脉,还能学到譬如 OOP(面向对象编程)、FP(函数式编程)、FRP(函数响应式编程)思想,助力高薪。

Nestjs默认选择 Express 作为底层服务框架,你也可以通过配置选择 Fastify

安装

相信使用过 VueReactAngular 的同学都熟悉项目初始化的脚手架工具,Nestjs也为大家提供了一个脚手架工具,有了这个工具我们能够更快搭建起Nestjs项目,下面我们来安装它吧。

npm i -g @nestjs/cli

为了版本一致,我们统一制定版本号为:@6.14.0,安装命令就是

npm i -g @nestjs/cli@6.14.0

安装完成以后,我们可以通过帮助命令检测脚手架工具是否安装成功,命令很简单,如下

nest -h

我们如果可以看到类似如下内容,则表示安装成功

Usage: nest <command> [options]

Options:
  -v, --version                                   Output the current version.
  -h, --help                                      Output usage information.

Commands:
  new|n [options] [name]                          Generate Nest application.
  build [options] [app]                           Build Nest application.
  start [options] [app]                           Run Nest application.
  generate|g [options] <schematic> [name] [path]  Generate a Nest element.
    Available schematics:
      ┌───────────────┬─────────────┐
      │ name          │ alias       │
      │ application   │ application │
      │ angular-app   │ ng-app      │
      │ 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           │
      │ service       │ s           │
      │ library       │ lib         │
      │ sub-app       │ app         │
      └───────────────┴─────────────┘
  info|i                                          Display Nest project details.
  update|u [options]                              Update Nest dependencies.
  add [options] <library>                         Adds support for an external library to your project.

到这里,你是不是迫不及待想初始化一个项目练手了呢?那我们就来创建一个项目

nest new nest-demo

现在只需要静静地等待~ 初始化并安装完成以后,启动项目

npm run start

然后打开浏览器,输入 http://localhost:300,就能看到呈现给我们的页面了。我完事了,你呢?

九个核心概念

我看多很多人的演讲和课程以后,发现了一个很有意思的规律,晦涩难懂的概念想讲明白但是听众实在是听不明白,简单明了的概念不想让听众觉得容易故意往复杂了说导致听众一样糊里糊涂。我不想这样,我想我的这套课程能够从实用出发,逐步深入,最后讲解该框架的设计原理与实现,可是就算我想说的很明白,框架本身的很多概念我们也没法躲避开,与其在我们后面的工作和学习中与这些概念纠缠不休,我们长痛不如短痛,先从要害下手。

九个核心概念贯穿Nestjs开发始终,也只有你深刻理解了这些核心概念,你才能构建出优秀的Nestjs项目,就像早些年Java面试必问JSP中九大内置对象

  1. Controllers
  2. Providers
  3. Modules
  4. Middleware
  5. Exception Filters
  6. Pipes
  7. Guards
  8. Interceptors
  9. Custom decorators

Controllers

img

英文直译:控制器,控制?控制什么?

客户端就像一个懵懂的小男生,看到了喜欢的女孩子就会示好表白,是给你这坏男孩好人卡还是倾心相待,控制权在女孩子手中。客户端的请求最终交给那个函数或者模块处理都需要通过预先处理,直接处理客户端请求(路由、方法等)的模块我们称之为控制器@Controller

Providers

img

英文直译:提供者,提供?提供什么?

场景一:

我:亲爱的,我想吃烧烤。

女友:好冷啊,我不想做。

我:刚好我看到楼下开了一家么斯烤肉,去尝尝吧。

场景二:

我:亲爱的,我们房子马上要装修了,你做总设计师可以吗?

老婆:我是UI设计师!不是室内设计,不过我有个朋友公司做设计挺棒,要不?

我:好的,我去学室内设计,然后去你朋友那上班

从以上两个场景,我们能看出什么?女朋友不爱我不管要干嘛,都能找到提供服务的商家。提供者使我们预先定义好的一些服务,为我们后续开发过程服务。@Injectable() 装饰的类。

Modules

img

英文直译:模块,什么时候模块?

君子由什么组成?我们可以想到忠孝仁义,这四个特质拆开来个个都是优秀品质,组合在一起就成了受人尊敬的正人君子。Nestjs个个模块、功能、服务等都是优秀个体,装载到一起便是优秀的服务架构。@Module() 装饰的类来组织应用结构。

Middleware

img

英文直译:中间件,谁的中间?

中间,是客户端和路由处理的中间,我们前面提到路由交给了控制器处理,如果我们想请求在到达控制器之前或者在响应发送给客户端之前对requestresponse做一些处理,就可以使用中间件,在中间件定义的过程中,有一个很重要的函数——next(),他决定了请求-响应的循环系统。提一点,你知道Koa的洋葱模型吗?

一直讲中文有点累,我们粘贴点express官方给的中间件描述

Middleware functions can perform the following tasks:

  • execute any code.
  • make changes to the request and the response objects.
  • end the request-response cycle.
  • call the next middleware function in the stack.
  • if the current middleware function does not end the request-response cycle, it must call next() to pass control to the next middleware function. Otherwise, the request will be left hanging.

Exception filters

img

英文直译:异常过滤器,过滤谁?

当你的项目中出现了异常,而代码中却没有处理,那么这个异常就会到Nestjs内建的异常处理层,我们通过预定义异常处理过滤器,就能将异常更友好地响应给前端。

Pipes

img

英文直译:管道,和水管有区别吗?

有用过Linux系统的同学,可否知道bash命令中那小小的一个竖线,这个命令有印象吗?

ls | grep '*.js'

列举当前目录下的文件及文件夹,然后得到的结果进行过滤,过滤规则为满足文件后缀名为js的文件。我们通过这个操作,能感受到管道的作用,其作用可以归纳为一下两点

  1. 转换:将输入的内容转换为希望得到的结果
  2. 验证:验证输入的内容是否满足预先定义的规则,如果验证通过,则会进入到后续操作;否则将抛出异常

filterPipes 使用的阶段相似,都是在请求处理之前,但是他们的职责却有很大差别,各自职责以列举,详细的使用场景我们后续介绍。管道是用@Injectable()装饰并实现了PipeTransform 接口的类。

Guards

img

英文直译:守卫,守卫谁?

我们的房子为什么需要钥匙?因为我们不允许外人进入我们的房间。应用中有些请求处理不是对所有前来请求的用户完全开放的,只有具有指定身份的人才能请求某些接口,负责这一职责的功能模块称之为守卫。管守卫是用@Injectable()装饰并实现了CanActivate接口的类。提示一点

Guards are executed after each middleware, but before any interceptor or pipe.

Interceptors

img

英文直译:拦截器,拦截谁?为什么要拦截,拦截了做什么?

一个流水线,如果中间临时需要加一道工序,随加随撤,我们发现这一道工序只是目前临时新增的,他并不属于这条流水线上完整环境中的一个步骤,因此这道工序我们可以将它看做外来者,有没有他不影响我们现有的流水线工作,但加入了它,我们现在流水线制造出的产品更趋于定制化。这道工序我们是切入到现有流水线中来的,这种做法我们称之为面向切面,当然在程序界,他就是很有名的一个思想 Aspect Oriented Programming (AOP)思想,即面向切面编程,它有一下几点优势

  1. 在现有某个函数执行前/后新增一个额外逻辑
  2. 转换一个函数返回的值,这点概念上与Pipes相近
  3. 转换一个函数运行时抛出的异常
  4. 可以继承某个基础函数的行为,更优雅的组合功能
  5. 重写某个函数

拦截器是用@Injectable() 装饰并实现了 NestInterceptor 接口的类。

Custom decorators

英文直译:自定义装饰器

在此之前,介绍了很多装饰器,比如:@Injectable()@Module()@Controller 等,还有请求相关的装饰器:@Get()@Post()@Param 等。