TS NodeService

内部轮子 TS Node 服务端上层框架2021-06-12

最近在做一个创新的移动端项目的服务端支持,于是总结了过往项目的坑坑洼洼,写了一个全新的内部 TS NodeService 服务端框架。

其实业界开源还挺多类似的,例如 midwayjsnestjs,都是功能大而全的框架,甚至可以说是站在巨人的肩膀上,避免了一些(例如多线程日志读写锁等)比较常见的问题。

如果考虑复杂繁多的业务场景,上述框架确实是一个不错的选择,但自研的根本出发点是轻量化、贴合部署环境、快速响应 bug 修复。当然也不能全然抛开社区模块支持,所以也是由基于 Koa 作为下沉框架封装做功能上的扩展。

大体上达成了一些 Features:

  • 最低依赖 engines node >= 14,基于 ESM 模块规范、使用 Top-Level-Await 初始化 DB、Redis 等资源连接管理、OptionalChaining 等大量原生 ESNext 语法,简化逻辑处理
  • Controller、Model、Service、Util 等扩展模块,依赖的类型声明注入 KoaContext
  • SWC 编译 TS(tsc 实在太慢了),梳理触发类型检查时机。SWC 对比 esbuild 来说,性能没有太大差距,从项目适应性方面选择,考虑只编译单体的 TS 文件,而不是捆绑打包的话,SWC 更能满足需求。需要留意的是 vscode 无法从源码层 debug 断点问题,原因是 @swc/cli 工具生成的 sourceMaps 内写入的是源文件代码内容,所以改用 @swc/core 追加逻辑处理编译文件,同时把 sourceMaps 指向到 src 源文件路径即可,此外编译过程还可以实现转换 TS Paths 物理路径等功能
  • 微服务 NodeServiceMesh 自协议,通常可用 gRPC,但对于内聚的同服务群可基于 udp 自研简化协议,优化解析通讯数据结构

_12
// controller.ts
_12
export Test1 = createController(async ctx => {
_12
ctx.body = await ctx.models.User.findOne()
_12
})
_12
export Test2 = createUDPController(async (ctx, params, resolve, reject) => {
_12
resolve(1 + 1)
_12
})
_12
_12
// router.ts
_12
const router = createRouter()
_12
router.get('/hello', Controller.Test1)
_12
router.udp('/hello', Controller.Test2)