# 前言
公司里近期在尝试部署一些业务到阿里云的函数计算上, 受之前迁移已有的 Spring Boot 应用到 FC 上的体验影响, 因此尝试使用 NodeJS 来作为新服务的主要运行环境. 几番尝试后得出了一些感悟, 在此记录一下, 以供大家参考.
# 正文
# 开发体验
受 NodeJS 生态圈的影响, 基于 NestJS 框架开发的工程也无处不体现着 NodeJS 生态的繁荣与杂乱... 你的工程文件夹下散落着各式各样的配置文件, 例如:
.eslintrc.js
,.nvmrc
,.prettierrc
,jest.setup.ts
,nest-cli.json
,tsconfig.json
... ...基于 Gradle 或 Maven 构建的 Spring Boot 工程与之相比, 则基本上不需要考虑 lint 与转义等问题. (当然, 与 C/C++ 工程相比还是好很多了... 毕竟人家大把的源文件都列在根目录下呢.
开发语言方面使用 TypeScript 来弥补 JavaScript 在类型定义方面的不足, 但即便如此, IDE 提供的类型推断与自动补全功能依然十分有限, 按
Ctrl + Space
后等待 IDE 反馈的时间基本上够你打完需要补全的内容了...DI/IoC 能力有限, 需要你自己使用各式各样的
@Module()
去构建依赖图, 各个模块之间需要主动暴露组件, 并主动声明需要注入哪些组件才能运行.约定大于配置的理念基本不存在.
- 想加载配置文件? 你得自己定义配置文件的位置和加载顺序.
- 想连接数据库? 你得自己定义从配置文件里加载哪几项配置.
NestJS 社区首推 Passport.js (opens new window) 来实现用户的身份认证相关的功能, 但这个包的主体目前是 一个由个人维护的项目, 主要维护人员除了基础的接口定义外, 还同时维护着基于这个接口的大量功能实现, 例如基于 Basic , JWT, Token 等实现的认证功能. 由于人力的缺失与长跨度的开发/维护周期, 导致其部分功能实现由于时间先后的差异, 出现风格不统一, PR 长时间无人受理等问题. 同时 NestJS 对 Passport.js 进行了包装 (opens new window), 导致部分 Passport.js 的功能实现不能直接适用于 NestJS 工程.
更让开发体验直线下降的是这一部分的代码没有提供 TypeScript 编写的源文件, 而是基于各式各样的
index.d.ts
+index.js
来提供的, 这导致开发团队在学习/调试相关功能时, IDE 的Ctrl + B (查看接口实现)
功能完全失效, 需要手动定位到指定的 js 文件才能了解其内部的工作流程. NestJS 对 Passport.js 的封装更让这一部分陷入难以理解的回调地狱:请简述 PassportStrategy 的功能 不得不说, NestJS 还是很良心的给了开发者一个做单元测试的包.
TestingModule
里能直接拿到运行环境中的对象, 可以直接对 service 进行测试, 也可以利用 Jest 的spyOn()
方法对 service 对象的方法进行拦截, 然后通过 SuperTest 对 NestJS 的控制器进行端到端测试. 另外, Jest 是基于文件进行单元测试的, 而不是基于类进行的, 导致有一部分通用的测试用例setUp()
与tearDown()
需要写在单独的文件里, 然后再在需要的测试文件的setUp()
和tearDown()
里去调用这个公用的辅助函数. 这一点我觉得 OOP 做的更好一些, JUnit 就可以通过继承抽象类的方式来自动加载公共的setUp()
和tearDown()
.
# 运行体验
- NestJs 在运行时解析依赖图, 构建上下文真的要花很长时间 (
await NestFactory.create(AppModule, config)
)... 下一个服务我们决定尝试一下 Quarkus 了. - 本来想着 NodeJS 项目打包后体积小一点, 函数的冷启动时间能更短一些, 结果开发完打包一看也有 127Mb ... 我有这个产物体积为什么不直接用 Spring Boot ...
# 总结
只能说, 体验不如 Spring Boot, 硬要说的话, 与 Spring Framework 相当.
# 相关内容
# 推广
欢迎大家领取 阿里云优惠券 (opens new window), 新购续费更优惠, 更有最高 10 % 返现,详询 钉钉 (opens new window): (opens new window)