基于koa2的elpis-core设计实现

99 阅读4分钟

elpis-core是什么

elpis-core是基于koa实现的服务端框架,可以理解为一个简易版egg,它的核心思想是约定大于配置,减少开发者手动引入的心智负担,提供更高效的团队开发体验。

elpis服务端框架设计理念源自抖音哲玄 - 大前端全栈实践课

设计思路

我们知道koa2已经实现了洋葱圈模型,其本身就是一个服务端框架,我们的思路则是基于koa2封装middlewareLoader, extendLoader, routerLoader, serviceLoader, routerSchemaLoader, controllerLoader, configLoader。 这些loader的本质都是寻找约定目录下的文件,并挂载到app上

下面依次介绍每个loader的设计思路

入口文件

我们将入口文件进行一个封装,暴露一个start方法,并提供一个options选项,用户使用时只需调用start方法即可启动服务,而无需关注服务的内部实现。

入口文件的另一个作用是加载不同的loader,这样用户就能在app获取不同的属性

config

config的作用主要是读取不同环境下用户设置的config对象,并挂载到app上,方便用户使用,为了判断不同的环境,我们需要引入一个env.js文件来判断,env的作用就是读取process.env._ENV环境变量,并返回对应的字符串。

为了遵从约定大于配置的思想,我们规定对外提供一个config目录,用户在目录里配置不同环境下的config文件,elpis-core负责读取这些文件并挂载到app上,规定的config文件包括

  • config.default.js config 默认配置,配置不同环境中共同的属性
  • config.local.js 本地配置,配置本地属性
  • config.beta.js 测试环境配置
  • config.prod.js 生产环境配置

已经规定好配置文件,那么剩下的步骤便是让configLoader读取这些文件,并挂载到app上。

具体实现是获取config目录下的约定好的上述四个config文件,并挂载到app.config上

middleware

我们规定用户在middleware目录下定义中间件,每个文件都会暴露一个方法,elpis-core负责将这些方法挂载到app.middlewares上,用户将来就可以在全局middleware.js里通过app.middlewares.xxx来定义中间件的顺序,也就是洋葱圈模型的思想

因此在设计时我们的目的是读取middlewares下的所有文件,要注意middlewares下可以存在文件夹,且我们采用驼峰命名,middleware下的文件名如果是error-handler,要变成errorHandler来调用

controller

controller用来读取app/controller/**/*.js 所有文件。 用户在controller定义一个对象,对象会提供若干方法,最后通过app.controller.xxx来调用

设计思路跟middleware的大同小异

service

用户在service/**/*.js定义的对象方法会被service挂载到app.service.xxx上,设计思路同middleware

controller和service区别

  • controller的主要作用是处理请求,并传递给service层
  • service的作用是将请求传递给数据库or后端,提供单一的原子化能力

router

router用来注册app/controller/*.js路由:app.use(router.routes())

router-schema

读取app/router-schema/**/*.js 所有的文件,挂载到app.routerSchema上,后续通过中间件来处理,设计实现同middleware

extend

用户可以自定义插件,并放在app/extend/*.js里,最后调用插件通过app.xxx读取即可,设计思路同middleware,但要注意存在同名插件的边缘case

加载顺序

定义好的loader按config -> middleware -> extend -> service -> controller -> router的顺序加载,被依赖的始终靠前,依赖项靠后,如controller最后肯定依赖service,因此service在controller前加载

不足

虽然这是一个简易版的egg实现,但我认为还是存在以下几点不足:

  1. 没有使用ts,经常出现少写、多写名字导致中间件挂载失败的情况
  2. 和egg对比,elpis-core少了business层,大多数时候我们需要在business处理后端返回的数据
  3. router-schema可以省略,可以通过zod4定义一个插件,在controller层调用该插件实现参数校验

收获

了解了egg里的核心思想:约定大于配置,并掌握了洋葱圈模型的原理和排查问题的一些常用方法