前言
在上一章节中,我们学习了 NestJS CLI
的用法,得到了一套基础的项目工程。最开始做项目对比的时候也提到过,NestJS
作为一款自定义程度较高的框架,CLI
直接提供的基础功能虽然并不完善,但同时也为开发者提供了非常多的内置或配套的功能例如高速缓存、日志拦截、过滤器、微服务等多种模块,方便开发者根据自身的业务需求定制适合当前业务的工程。
本章将根据业务需求或者团队规范,选择对应的模块搭建出一个符合要求的通用性脚手架。
Fastify
对于网关系统来说,无论是资源还是 API
接口数据,它都将承担所有的请求转发,虽然外层可以有 Nginx
做负载均衡策略,但如果框架本身的性能越好,业务实现的效果就会越好,同时对业务代码要求也可以稍微降低一点。
框架或者语言带来的性能提升还是非常重要的。可以给大家举一个明显的例子,Windows 自带的
VBS
脚本可以操作 Excel,Java
或者其他语言框架也可以操作 Excel。但是,其他语言的操作效率会远超VBS
,即使是在操作更为复杂或者文件读写内容更多的情况下。这里我们并不去深究为什么其他语言的速度会更快,但是对于一个快速迭代的业务项目或者小团队来说,选择效率高、性能高的框架作为开发语言无疑是降低整体成本最好的一种方式。
而 Nest
作为一个上层框架,可以通过适配器模式使得底层可以兼容任意 HTTP
类型的 Node
框架,本身内置的框架有两种 Express 与 Fastify。
如上图所示,Fastify
与其他主流 HTTP
框架对比,其在 QPS(并发处理请求)的效率上要远超其他框架,达到了几乎两倍的基准测试结果,所以在网关系统这个对性能要求非常高的项目中使用 Fastify
无疑是一种非常好的选择。
当然具体的性能开销、优化大部分还是依赖业务复杂度以及代码质量,框架能够提供的是只是一层基础架构。能从这层架构上搭建出什么样的产品,取决于开发者自身。同时,我并不是鼓励所有的项目都使用
Fastify
,在业务复杂度以及对性能要求并非十分敏感的项目中,Express
也是一种非常好的选择。作为老牌的框架,它经历了非常多的大型项目实战的考验以及长期的迭代,所以Express
社区生态非常的丰富,遇到任何的问题都可以快速找到解决方案,这也是NestJS
采用Express
作为默认基础框架的原因。
介绍完 Fastify
的优势之后,接下来我们开始着手改造模板项目框架。首先,通过 CLI
默认生成的项目框架中,底层平台使用的是 Express
,代码如下所示:
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() { const app = await NestFactory.create(AppModule);
await app.listen(3000); } bootstrap();
毕竟 Fastify
作为唯二内置的平台,整体的替换过程会非常顺畅。首先,安装对应的适配器依赖 @nestjs/platform-fastify
。其次,使用 FastifyAdapter
替换默认的 Express
。
import { NestFactory } from '@nestjs/core'; import { FastifyAdapter, NestFastifyApplication, } from '@nestjs/platform-fastify'; import { AppModule } from './app.module'; async function bootstrap() { const app = await NestFactory.create<NestFastifyApplication>( AppModule, new FastifyAdapter(), ); await app.listen(3000); } bootstrap();
版本控制
之前学习过 DevOps 小册的同学,应该对 GitLab OpenApi 比较熟悉,肯定也使用过这样的请求 gitlab.example.com/api/v4/proj… ,可以看出链接上面是带 v4 版本的。
因为我们有两种项目分别是物料与用户,这两款系统作为基础应用,后期也会对其他的项目提供类似的 Open Api,同时避免不了升级之后,需要兼容老项目的情况。此时就会存在多种版本的 Api,所以我们也在工程添加版本控制来避免未来升级的时候,造成其他系统崩溃。
单个请求控制
第一步:在 main.ts
启用版本配置:
import { VersioningType } from '@nestjs/common'; import { NestFactory } from '@nestjs/core';
import { FastifyAdapter, NestFastifyApplication, } from '@nestjs/platform-fastify';
import { AppModule } from './app.module';
async function bootstrap() { const app = await NestFactory.create<NestFastifyApplication>( AppModule, new FastifyAdapter(), ); // 接口版本化管理 app.enableVersioning({ type: VersioningType.URI, });
await app.listen(3000); } bootstrap();
第二步:启用版本配置之后再在 Controller
中请求方法添加对应的版本号装饰器:
import { Controller, Version } from '@nestjs/common';
@Get() @Version('1') findAll() { return this.userService.findAll(); }
配置完毕之后从上图可以看到,只有携带了版本号的请求 http://localhost:3000/v1/user 能正常返回数据,而之前未携带版本号的请求 http://localhost:3000/user 返回了 404 错误。
除了针对某一个请求添加版本之外,同样也可以添加全局以及整个 Controller
的版本,具体的版本配置规则可以根据自己的实际需求取舍。
全局配置请求控制
第一步:修改 enableVersioning
配置项:
app.enableVersioning({ + defaultVersion: '1', type: VersioningType.URI, });
第二步:修改 Controller
的配置,在 Controller
装饰器中添加 version
属性:
- @Get() - @Version('1') + @Controller({ + path: 'user', + version: '1', + })
完成上述的操作就可以