服务粉丝

我们一直在努力
当前位置:首页 > 财经 >

为什么说 Nest.js 提供了 Express 没有的架构能力?

日期: 来源:神光的编程秘籍收集编辑:神说要有光zxg

Nest.js 是当前最流行的 Node.js 框架,现在已经 56k star 了

有的同学说,不是还有 express 么?

其实严格来说 express 并不是一个框架,它只是提供了基于中间件的请求响应处理流程。

但它并没有规定代码应该怎么组织,怎么复用,怎么集成各种方案,所以代码能写成各种样子,这对于大项目开发来说是很难维护的。

所以出现了更上层的 node 框架,比如 egg、midway、nest 这些,它们额外提供了架构能力,这类框架也叫企业级开发框架。

nest 是最优秀的 node 企业级开发框架。

其实 nest 的底层也是 express,但它封装出了 IOC、AOP 等架构特性。

我们分别来看一下它提供的这些架构特性:

nest 最主要的特性就是模块机制了,它类似 es module 但又有很多不一样。

es module 是这样的:

import { a, b } from 'a';

const c = 1;

export { a, c };

而 nest 的 module 机制是这样写:

import { Module } from '@nestjs/common';
import { aaa } from './aa.module';
import { CatsService } from './cats.service';

@Module({
  imports: [aaa]
  providers: [CatsService],
  exports: [CatsService]
})
export class CatsModule {}

可以 import 别的模块,可以 export 内部的值。

这些内部的值是通过 provider 提供的,其实 import、export 导入导出的都是这些 provider。

这和 es module 也差不多呀?为啥要自己搞一套模块机制?

因为这套模块机制是可以实现自动注入依赖的,也就是 DI(Denpendency Injection),我们说的 IOC (Inverse Of Control)容器就是有这种依赖注入机制的容器。

这俩概念可能你不理解,看个例子就懂了。

我们写个 AppService 类,它有个 getHello 方法,通过 @Injectable 装饰器声明它是可以被注入的。

把它放到 module 的 provider 里:

这里还有个 controller,它是用来处理 http 请求的,也可以被注入:

它在构造器里声明了对 appService 的依赖。

然后我们把这个应用跑起来:

打个断点:

可以看到这时候 AppService 是有值的。

明明我们只是在 controller 里声明了对这个 service 的依赖,并没有 new 这个 AppService 的对象,也没有 new contoller 的时候传入 AppService 对象。

那它是怎么创建的对象,又是怎么注入的依赖呢?

这些就是 Nest 的模块机制提供的特性了,也就是 DI 或者说 IOC 的能力。

自动化创建对象,并且根据依赖关系自动注入。

这样就算你的对象之间的关系再错综复杂也不用自己去 new 和组装,就很方便。

我们再来测试个 import 的例子:

我 import 了一个操作数据库的 module。

然后在这个 module 的一个 Service 里就可以直接用数据库 module 内的做 crud 的 repository 对象了:

也就是说 module 内部的 provider 之间可以相互注入,provider 也可以注入 controller 中用。

如果 import 了别的 module,那也可以注入它 export 的 provider 了。

这就是 nest 自己实现的模块机制和 es module 最大的不同:实现了依赖自动注入。

用了 nest,只要按照它的写法来声明 @Module 和 @Injectable,就可以使用这种 IOC 能力。

而 express 呢?

你需要手动 new 一个个对象,手动组装。

这是 Nest 提供的第一个架构能力:IOC。

接下来是 Nest 提供的第二个架构能力:AOP。

AOP 是 Aspect Oriented Programming,面向切面编程。

切面也就是处理流程中的某个点,在这个点来扩展一些逻辑,比如在 controller 之前加入日志、权限、异常处理等逻辑:

nest 里主要有 4 种切面:

第一个是 Guard:

它是用来在 Controller 之前判断权限,返回 true、false 来表示是否继续:

要声明在 Contoller 上:

第二个是 Interceptor:

它用来在请求前后加入一些逻辑:

也是声明在 Controller 上:

第三个是 Pipe:

它用来在参数传入 Controller 之前做一些转换:

声明在 Contoller 的某个路由上:

第四个是 ExceptionFilter:

处理过程中可能会抛不同的异常,而 ExceptionFilter 就是处理这些异常,返回友好的信息给客户端的:

也是声明在某个路由上:

这就是 nest 提供的 4 种切面,可以声明某种功能的切面,然后加入到任意的处理流程中。因为是有统一的规范的,所以复用起来很容易。

而 express 呢?

并没有抽象出这些切面,所以代码没有规范,复用也比较困难。

这就是 nest 提供的第二种架构能力:AOP。

nest 的第三种架构能力是可以任意切换平台。

前面说,nest 的底层是 express,其实并不准确,nest 并没有和 express 耦合。

它所有的上层代码都是基于一个抽象的接口的:

而这个接口有 express 和 fastify 两种实现:

分别放在 @nestjs/platform-express 和 @nestjs/platform-fastify 包里。

默认用的是 express:

可以灵活切换 http 的底层平台。

不只是 http 可以切换具体的底层平台,websocket 也是,可以切换 socket.io 和 ws:

通过这层层抽象,就达到了不依赖任何一个底层平台的效果:

哪怕有一天,有一个新的 http 库取代了 express,那对 nest 有影响么?

没有,只要加一个新平台的适配器就可以了。

这就是 nest 的架构的强大之处。

而且不只是可以灵活切换 http 和 ws 平台这么简单。

你写的一些 Guard、Exception Filter、Interceptor、Pipe 甚至可以用在 websocket 和微服务里:

可以跨多种上下文来复用代码:

它提供了 ArgumentsHost 类,在切面里拿到它之后,可以判断出当前是什么上下文:

然后切换到对应的上下文来写后面的的逻辑:

这样就实现了切面的跨上下文复用。

那 express 呢?

并没有这种跨多种平台复用代码的一些抽象。

这就是 nest 提供的第三种架构能力:可以任意切换底层平台和执行上下文。

有了这三种架构特性,代码自然会变得松散耦合、易于扩展,易于维护,所以这种 node 框架才叫做企业级开发框架。

总结

nest 是在 express 之上封装的一层,提供了很多架构的能力:

  • IOC:自己实现了模块机制,可以导入导出 provider,实现自动依赖注入,简化了对象的创建
  • AOP:抽象了 Guard、Interceptor、Pipe、Exception Filter 这 4 种切面,可以通过切面抽离一些通用逻辑,然后动态添加到某个流程中
  • 任意切换底层平台:nest 基于 ts 的 interface 实现了不和任何底层平台耦合,http 可以切换 express 和 fastify,websocket 可以切换 socket.io 和 ws。而且 4 种切面也实现了可以跨 http、websocket、微服务来复用。

明显能感受到,用了 nest 之后,代码会变得很容易维护:通用逻辑都放在切面里复用、不同的业务模块放到不同的 Module 里,依赖自动注入,上层不改一行代码就可以切换底层平台。

而且 nest 基于这个架构提供了对各种方案的集成,比如 mq、redis 的集成、比如 graphql 和 websocket、比如 jwt 等。

架构优雅、各种解决方案开箱即用,这就是 nest 声称自己是企业级开发框架的原因。它对标的是 java 里的 spring。

相比之下,express 虽然也能实现各种功能,但是在架构方面,在其他方案的集成的简便性方面,还是不够的。

如果你要开发一个相对复杂的 node 服务,还是用 nest 吧。

相关阅读

  • 香港国际影展:我和鬼、悲情城市及其它……

  • 点击收听“评-第47届香港国际电影节”*点击文末“阅读原文”也可收听节目流程1)热点台湾电影新片-《关于我和鬼变成家人的那件事》(无剧透)经典-《悲情城市》《少年吔,安啦》《
  • 食欲旺盛、不饿也想吃?你可能被肠道“控制”了

  • 明知道不该吃了,还是管不住嘴的经历,大家应该都有:晚上刷到美食视频,激情下单;火锅烤肉吃到撑,but还有一个胃装甜品...或者像留言说的,以为先吃菜后吃主食能少吃点,结果骗得了胃,骗不
  • 海大,动起来!

  • 我们共赴赛场青春激昂 生命跃动我们在汗水挥洒中书写拼搏的意志刻画不惧的勇气


    方阵严整 热血难凉海大学子风采尽现
    升旗

    国歌奏起 红旗冉冉起立 注目 敬礼步履铿锵 慷
  • 5月基金备考仅剩30天,复习只看这个一次过!!

  • 今年唯一一次基金从业统考将于5月20日-21日开考 距离考试仅剩30天!!你是不是觉得30天时间很充裕?那你就错了!!在正式考试前,我们要跨越5天的劳动节假期!大多数小伙伴都会有出行的
  • 淮北:多措并举推进第三代社保卡发行应用

  • 淮北市人社局为深入推进居民服务“一卡通”应用,多措并举加快第三代社保卡发行,夯实“一卡通”应用基础。一季度全市发行第三代社保卡14万张,超过年度发行目标序时进度。一创新
  • 魅力女兵,颜值与实力齐飞

  • 在战区陆军部队有这样一群新时代女兵她们有颜值、有实力英姿飒爽、敢打敢拼、霸气十足!今天让我们来听听她们的迷彩故事~报务员:下士 张译丹成长感悟:提起报务这个专业,大家的印

热门文章

  • “复活”半年后 京东拍拍二手杀入公益事业

  • 京东拍拍二手“复活”半年后,杀入公益事业,试图让企业捐的赠品、家庭闲置品变成实实在在的“爱心”。 把“闲置品”变爱心 6月12日,“益心一益·守护梦想每一步”2018年四
  • 美国对华2000亿关税清单,到底影响有多大?

  • 1 今天A股大跌,上证最大跌幅超过2%。直接导火索是美国证实计划对华2000亿美元产品加征25%关税。 听起来,2000亿美元数目巨大,我们来算笔账。 2000亿美元,按现在人民币汇率

最新文章

  • 【第2921期】实践指南-前端性能提升 270%

  • 前言Lighthouse 性能分析实战。今日前端早读课文章由 @凹凸嫚 - 清汤饺子分享,公号:凹凸实验室授权。在这也分享上周看到的一个服务:https://webperformancereport.com/ 通过订
  • He3 开发工具箱 - 400+ 免费的小工具合集

  • 前言昨天介绍了 ChatGPT to Help:从此告别 Copy & Paste,多个 tabs 之间无缝畅聊 工具,今天来一个工具界的 hao123-He3。本文由 @王炜投稿分享。@王炜,软件爱好者,热衷于发现开发
  • E大,孟岩,且慢及我们

  • —— 前言 ——昨天研读时,看到二大的两条微博,觉得怪怪的。除了当年E大因“球球污蔑事件”转移到微博外,已经很久没看到这种情绪了。怀着八卦的心情,大致了解了下,捋了下事情
  • 债券基金投资的四大误区

  • 不要在小河里翻船温馨提示:公众号平台最新的推送规则为算法推荐。非“常读用户”,不能保证系统每次都会将文章推送给用户。经常进行留言、点赞、在看、转发等互动行为,可增加被
  • 偷个懒

  • 今天,有老友从外地回来,一晃几年未见,难得相聚。古有绿窗红烛下,觥筹交错的雅集;今有旋转餐厅里,落地窗边的约会。古有春日渡口边,折一枝杨柳相送;今有雨中的机场外,挥挥手说声“好走