大厂技术 高级前端 Node进阶
点击上方 程序员成长指北,关注公众号
回复1,加入高级Node交流群
前言
最近一直比较忙, 而且自己工作中做的事也不适合写文章,所以一直没有更文..
最近接到一个小需求,需要自己全干(前端+后端),看到群里大家对Nest.js
热情都很高,自己也心痒痒,所以就走上了Nest.js的不归路~
我会将自己做这个小项目过程记录下来,同时也分享一些踩坑的经验,给想学的小伙伴一点参考吧。文章是循序渐进的, 并不是一上来就是深入Nest.js
难点, 但是每一章都有一些开发注意点和自己的思考, 欢迎大佬们指点一二。
为什么选择Nest.js
前面也说了, 大家都说香啊~
其次,我之前也使用过Egg.js
,19年使用的时候,感觉egg约束性比较强,但是对于内部统一规范还是有好处的,但现在2021了, 已经习惯了TS,但Egg.js
没有原生提供的TypeScript支持, 开发时可使用egg-ts-helper 来帮助自动生成 d.ts
文件,这样第三方库的支持完全不受控制, 风险还是很大, 所有选择放弃了
说了这么多,接下来开始吧!文章主要包含以下内容:

初识 Nest.js
Nest.js官网介绍:
Nest (NestJS) 是一个用于构建高效、可扩展的
Node.js
服务器端应用程序的开发框架。它利用JavaScript
的渐进增强的能力,使用并完全支持TypeScript
(仍然允许开发者使用纯 JavaScript 进行开发),并结合了 OOP (面向对象编程)、FP (函数式编程)和 FRP (函数响应式编程)。在底层,Nest 构建在强大的 HTTP 服务器框架上,例如 Express (默认),并且还可以通过配置从而使用 Fastify !
Nest 在这些常见的 Node.js 框架 (Express/Fastify) 之上提高了一个抽象级别,但仍然向开发者直接暴露了底层框架的 API。这使得开发者可以自由地使用适用于底层平台的无数的第三方模块。
上面这段话刚开始并不能完全理解, 但是简单可以解读出来Nest.js的几个特点:
原生支持TypeScript的框架
可以基于
Express
也可以选择fastify
, 如果你对Express
非常熟练, 直接用它的API也是没问题的
至于其他看不懂,就暂时放一边, 因为不影响我们入门,后面深入学习后会再来分析。
项目创建
首先确定你已经安装了Node.js
, Node.js
安装会附带npx
和一个npm
包运行程序。要创建新的Next.js
应用程序,请在终端上运行以下命令:
npm i -g @nestjs/cli // 全局安装Nest
nest new project-name // 创建项目
执行完创建项目, 会初始化下面这些文件, 并且询问你要是有什么方式来管理依赖包:

如果你有安装yarn
,可以选择yarn
,能更快一些,npm
在国内安装速度会慢一些,我这里就用npm
下载了。这里省略一个漫长的等待过程~, 终于看到了它成功了(然后我又删除了,使用yarn,确实速度快了很多)

接下来按照提示运行项目:

这里说一下我安装的环境,Next.js版本不同有些API会有差异
包 | 版本 |
---|---|
Node.js | v12.16.1 |
npm | 6.13.4 |
nest.js | 8.1.4 |
typescript | 4.3.5 |
注意:
Nest.js
要求Node.js
(>= 10.13.0,v13 除外), 如果你的Node.js
版本不满足要求,可以通过nvm
包管理工具安装符合要求的Node.js
版本
项目结构
进入项目,看到的目录结构应该是这样的:

这里简单说明一下这些核心文件:
src
├── app.controller.spec.ts
├── app.controller.ts
├── app.module.ts
├── app.service.ts
├── main.ts
app.controller.ts |
单个路由的基本控制器(Controller) |
app.controller.spec.ts |
针对控制器的单元测试 |
app.module.ts |
应用程序的根模块(Module) |
app.service.ts |
具有单一方法的基本服务(Service) |
main.ts |
应用程序的入口文件,它使用核心函数 NestFactory 来创建 Nest 应用程序的实例。 |
第一个接口
前面我们已经启动了服务, 那我们怎么查看呢, 首先就是找到入口文件main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
await app.listen(3000);
}
bootstrap();
内容比较简单, 使用Nest.js
的工厂函数NestFactory
来创建了一个AppModule
实例,启动了 HTTP 侦听器,以侦听main.ts
中所定义的端口。
监听的端口号可以自定义, 如果3000端口被其他项目使用,可以更改为其他的端口号 因为我的3000端口有别的项目在用, 所以修改成:9080,重新启动项目
我们打开浏览器访问http://localhost:9080
地址:

这里看到的Hello World
就是接口地址http://localhost:9080
返回的内容, 不信我们也可以使用常用 Postman看看:

说明Nest.js
创建项目默认就给写了一个接口例子,那就通过这个接口例子来看,我们应该怎么实现一个接口。
前边看到mian.ts
中也没有别的文件引入, 只有AppModule
, 打开src/app.module.ts
:
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
@Module({
imports: [],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
AppModule
是应用程序的根模块,根模块提供了用来启动应用的引导机制,可以包含很多功能模块。
.mudule
文件需要使用一个@Module()
装饰器的类,装饰器可以理解成一个封装好的函数,其实是一个语法糖(对装饰器不了解的,可以看走近MidwayJS:初识TS装饰器与IoC机制)。@Module()
装饰器接收四个属性:providers
、controllers
、imports
、exports
。
providers:
Nest.js
注入器实例化的提供者(服务提供者),处理具体的业务逻辑,各个模块之间可以共享(注入器的概念后面依赖注入部分会讲解);controllers:处理http请求,包括路由控制,向客户端返回响应,将具体业务逻辑委托给providers处理;
imports:导入模块的列表,如果需要使用其他模块的服务,需要通过这里导入;
exports:导出服务的列表,供其他模块导入使用。如果希望当前模块下的服务可以被其他模块共享,需要在这里配置导出;
如果你是Vue或者React技术栈,初次接触Nest.js
,可能会觉得很面生啊, 其实很正常,Nest.js
的思维方式一开始确实不容易理解,但假如你接触过AngularJS
,就会感到熟悉,如果你用过 Java 和 Spring 的话,就可能会想,这不是抄的 Spring boot嘛!
确实AngularJS
、Spring
和Nest.js
都是基于控制反转
原则设计的,而且都使用了依赖注入的方式来解决解耦问题。如果你觉得一头雾水, 别急,这些问题后面深入学习都会一一讲解的。这里我们还是照葫芦画瓢,学一下Nest究竟怎么使用的。
在app.module.ts
中,看到它引入了app.controller.ts
和app.service.ts
,分别看一下这两个文件:
// app.controller.ts
import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
@Get()
getHello(): string {
return this.appService.getHello();
}
}
使用@Controller
装饰器来定义控制器, @Get
是请求方法的装饰器,对getHello
方法进行修饰, 表示这个方法会被GET请求调用。
// app.service.ts
import { Injectable } from '@nestjs/common';
@Injectable()
export class AppService {
getHello(): string {
return 'Hello World!';
}
}
从上面,我们可以看出使用@Injectable
修饰后的 AppService
, 在AppModule
中注册之后,在app.controller.ts
中使用,我们就不需要使用new AppService()
去实例化,直接引入过来就可以用。
至此,对于http://localhost:9080/
接口返回的Hello World
逻辑就算理清楚了, 在这基础上我们再详细的学习一下Nest.js
中的路由使用。
路由装饰器
Nest.js
中没有单独配置路由的地方,而是使用装饰器。Nest.js