Skip to content

phecda-server

一款易于接入、可复用类型的类nestjs服务端框架

TIP

如果熟悉nestjs或者其他依类似框架,并已决心使用这个方案

不用在这里浪费时间,对照后续文档,直接查看案例即可

以下的部分主要为抱着调研心态的游客解惑

intro

我不需要一个玩具

很多开源的服务端框架有很棒的性能和特性,但实际上,社区里的实践多是一些无关轻重的项目,或许未来会成为主流技术,但当下看起来更像是一个花哨有趣的玩具。

但我真正需要的,是一个能让我无后顾之忧地在现有项目中使用的技术

我希望有一款服务端在个人、企业、或大或小的项目...无论在任何时候都能帮上忙

它以实用为第一且唯一的目标,而不是为开发者提供想象空间,坦率地说,相较于其他任何框架,这都是一个极度乏味的方案,

很多优秀的开源方案会强调的部分,比如体积和压测,PS不关心

虽然确实依赖少体积小,但这并不是目的,如果有必要的话,我会毫不犹豫膨胀体积

性能与使用的框架有关,目前从压测看会比原有的框架并发少 20%(这看上去是个很恐怖的数字,但鉴于benchmark的猫腻,实际业务的影响几乎没有), 我会尽力让性能维持在当前的水平上,但不会花时间做一个提高性能百分之 x 的改动

PS更重视维护性、可读性、开发体验、代码量...一些业务中真正能让开发者受益的东西

nestjs的写法

沿用了一部分nestjs的模式:

  1. 以类为核心的写法能提供比较规范的格式和不错的可读性
  2. 利用元数据实现的控制反转能提供很棒的体验,
  3. aop 也能帮助注意力集中在业务本身上

nestjs可能导致代码冗余和理解困难的特性,如过于灵活的依赖注入和兼容,这些部分会移除

总之,只使用了我认为好用的部分

类nestjs只是为了方便理解,体验也有相似之处,但本质大相径庭,如果开发者坚信诸如“模块级+花样繁多的注入”“请求级的生命周期” 有巨大意义,那么PS绝对是来添乱的

易于接入

易于接入和易于移植并不是同一回事

易于移植并不是完全意义的好事,因为真实的项目大部分时候不会无端的移植,

为什么要花时间将一个无比稳定的 express 应用用 hono 重写一遍?即使这样做很容易

真实的情况是,我可能要接着开发这个 express 应用,提供的新接口显然也要是一个express router,新模块要能调用旧模块,甚至旧模块要能调用新模块,很多时候只能捏着鼻子接着用 express 的思路做

最好的情况是,新模块本质是一个 express一部分,那么一切问题都会引刃而解。

ps 就是这么做的,出于这个特点,ps 能支持各种服务端以及微服务

ps 能接入绝大部分底层服务端框架,但对于依赖编译工具的高级框架,如 nextjs/nitro等则不行

我承认至少一部分框架是需要支持的,(好吧其实就只有 nextjs),

但这工作量对我实在是过于残忍,且本人对nextjs有极大恶意,故不打算支持

INFO

这和nestjs也不太一样(虽然其也号称progressive, 但我相信不会真有人这么用的)

nestjs侧重于使不同框架作为其底层的运行时

由于上层设计过重,nestjs很难去“迁就”底层服务框架,结果就是官方无力兼容express以外的东西,甚至连fastfiy的特性都遗失了不少

ps则更像是对原有框架的加强


上述两点足够让内部代码较为糟糕的团队心动, 但如果你是一位技术的狂信徒,可能确实需要一个强而有力的 feature 说服自己,那PS也提供了一些吸引眼球的特性

PS提供了不少实用且独特的功能,但只有这两个功能称得上绝无仅有

代码和类型的复用

好吧,也可以叫端到端类型安全

我不太确定其他开发者对类型复用的理解是什么, 我的理解大概是有两个步骤

  1. 声明类型

  2. 使用特定的请求库,复用这个类型

    可能在此基础上还有一些区别,比如:

如何声明类型的,是通过zod等方式隐式推导类型还是通过单独显式声明?是完全通过类型推导去区分method/query/body/params,如elysia,还是完全不区分,直接写死标准?(全部使用POST请求,并将数据挂到body),如trpc/tsrpc

无论是写死标准还是使用特定请求库,都不一定是好事:

  1. 你真的确定手头的项目可以完全舍弃restful标准吗

  2. 使用大量类型体操可能导致ide 卡顿或对眼睛不友好(可以看一下elysia的类型)


在服务端编写一些代码,生成一些代码,然后想办法让前端请求库在类型上复用代码类型,在调用上利用元数据(对应phecda-client库)

将易接入性延续至客户端,包装axios/alova而非自行制作请求库(phecda-server/express<==>phecda-client/axios

不会影响业务中旧有的任何写法,成本低,过程透明

如果业务原有的请求库不是axios(真是羡慕...)可以自行包装一个,这很简单,代码一百行以内就能搞定

极速的热更新

现在的热更新,多是通过启动一个守护进程,当代码更新时,守护进程杀死原进程并启动一个新进程,并重新建立数据库连接等。

即使使用swc等来编译,进程重启的过程仍然漫长

ps实现文件级别的热更新(如同vite中做的一样),文件更新时替换对应的模块,进程无需重启,再搭配swc,可以实现<0.1s的热更新

我还是要强调:这是小于零点一秒的热更新!开发体验绝对是极致中的极致了

Released the MIT License.