elpis-core ,koa实现的系统底座, 沉淀80% 的通用能力,剩下20% 用于定制化开发

一句话理解elpis-core

elpis-core 就像项目的公共底座:把 80% 会反复出现的事情先做好,再给每个项目留下 20% 的空间去写自己的业务。

先看项目目录

ruby 复制代码
elpis/
├── index.js              # 启动入口
├── config/               # 环境配置
├── elpis-core/           # 应用装配器
│   ├── index.js          # 启动流程
│   ├── env.js            # 环境判断
│   └── loader/           # 各类模块加载器
└── app/                  # 业务代码
        ├── controller/       # 请求处理
        ├── service/          # 业务逻辑
        ├── middleware/       # 可复用中间件
        ├── router/           # 路由定义
        ├── router-schema/    # API 参数规则
        ├── extend/           # app 扩展能力
        └── public/            # 静态资源与模板

读的时候 先看 index.js 怎么启动,再看 loader 怎么把业务文件找出来。

最简单的分工 elpis-core 管项目怎么跑,app 管项目做什么。

读完应该记住配置先准备环境,controller 和 service 处理业务,router 把请求接进来。

它到底帮我们做了什么?

它是一个用 Koa 实现的,用来完成项目启动和模块注册的核心。

80% 通用能力:启动、配置、日志、中间件加载、模块注册、路由接入

20% 定制能力:业务规则、接口、数据源和项目差异

以后新建项目时,少复制一堆老代码,也少担心几个项目慢慢长得不一样。

没有 elpis-core**→** 手动 require**→** 手动实例化**→** 手动挂载**→**启动应用

使用 elpis-core**→** 遵守目录约定**→** loader 自动装配**→**直接写业务

从入口看起

项目入口很薄,薄到基本只剩一句启动:

php 复制代码
const ElpisCore = require('./elpis-core')

ElpisCore.start({
    name: 'elpis',
    homePage: '/'
})

入口只有一次 start() 调用,真正的工作集中在 elpis-core/index.js:

ini 复制代码
const app = new koa()
app.options = options
app.baseDir = process.cwd()
app.bussinessPath = path.resolve(app.baseDir, './app')
app.env = env()

这里的关键是:所有 loader 都围着同一个 app 工作。前面准备好的东西,后面直接拿来用,所以启动顺序不能随便换。

启动顺序就是依赖关系

当前启动顺序大致是:

创建 Koa app**→** 设置路径与环境**→** 加载 config**→** 加载 extend**→** 加载 middleware**→** 加载 service**→** 加载 controller**→** 加载 router schema**→** 加载全局中间件**→** 加载 router**→**监听端口

配置:默认值加环境覆盖

arduino 复制代码
config/
    config.default.js
    config.local.js
    config.beta.js
    config.prod.js

默认配置 公共配置放在 default。

环境覆盖 local / beta / prod 根据 app.env 选择。

最终入口 调用方只需要读取 app.config。

ini 复制代码
app.config = Object.assign({}, defaultConfig, envConfig)

extend:把公共能力挂到 app 上

文件名就是注册名,loader 负责把路径变成运行时对象:

app/extend/logger.js→ app.logger

app/middleware/api-params-verify.js→ app.middlewares.apiParamsVerify

app/service/project.js→ app.service.project

业务少写注册代码,核心集中处理命名、加载和挂载。

service 与 controller:工厂接收 app,再创建实例

service 和 controller 都采用"工厂接收 app,再返回类"的形式:

scala 复制代码
module.exports = app => {
    const BaseService = require('./base')(app)

    return class ProjectService extends BaseService {
        async getList() {
            return []
        }
    }
}

loader 找到文件后,执行工厂,再实例化返回的类,最终得到:

复制代码
app.service.project
app.controller.project

Controller接收 ctx,调用 service,组织响应。

Service承载业务处理,隐藏数据访问细节。

Base 类共享 app、config、返回格式和公共工具。

路由只绑定 controller 方法:

csharp 复制代码
const { project: projectController } = app.controller
router.get('/api/project/list', projectController.getList.bind(projectController))

controller 再调用:

kotlin 复制代码
const projectList = await this.service.project.getList()
this.success(ctx, projectList)

调用链很短:路由 → controller → service → 统一响应。

router-schema 与 API 参数校验

schema 描述参数,router loader 自动把校验中间件插入 API 路由:

arduino 复制代码
app.routerSchema = {
    '/api/project/list': {
        get: { /* headers/query/body/params */ }
    }
}

router loader 创建 koa-router 后,重写了 get、post、put、patch、delete 的注册方法。路径以 /api 开头时,会自动把 app.middlewares.apiParamsVerify 插到 handler 前面;如果没有对应 schema,校验中间件会直接放行。

路由以 /api 开头**→** 自动插入 apiParamsVerify**→** 按 path + method 查 schema**→**校验 query/body/params

业务路由只需要注册 controller;绑定实例是为了保留 controller 里的 this:

csharp 复制代码
const { project: projectController } = app.controller

router.get(
    '/api/project/list',
    projectController.getList.bind(projectController)
)

重点:/api 不只是命名习惯,它还是参数校验的触发条件。

一次 API 请求是怎么走的

以 GET /api/project/list?proj_key=demo 为例:

1.全局中间件:静态资源、模板、body、错误、签名。

2.router 匹配路径,并自动插入参数校验。

3.controller 读取 this.service.project。

4.service 返回业务结果,controller 统一响应。

elpis-core的价值

80%:核心沉淀启动流程环境配置模块扫描路由接入

这些能力跨项目重复出现,适合集中维护、统一升级。

20%:业务定制业务规则接口实现数据访问中间件顺序

这些差异由具体项目自己决定。

相关推荐
acd1200923 分钟前
前端随笔:数据明明变了,Vue 页面就是不更新
前端·javascript·vue.js
传人2 小时前
悬停旋转放大和位移效果如何写
前端·javascript·css
zhangzeyuaaa2 小时前
Ruby 方法参数完全指南:默认值、可变参数与关键字参数
前端·python·ruby
粥里有勺糖2 小时前
视野修炼-技术周刊第135期 | 鼠标跟随宠物
前端·github·aigc
粥里有勺糖2 小时前
拿 Codex 协助清理磁盘,Nice!
前端·后端·github
Highcharts.js3 小时前
可视化商用图表库对比,如何选择?
前端·javascript·学习·信息可视化·highcharts·前端可视化
TheITSea3 小时前
JavaScript Web APIs
开发语言·前端·javascript
恋猫de小郭4 小时前
Android CLI 支持 AI Agent 通过 Device Streaming 调试云真机
android·前端·flutter
Wang's Blog4 小时前
Java 项目实战: 外卖平台优化-前端dist部署与Nginx反向代理rewrite
java·前端·nginx
鬓戈4 小时前
Claude Code frontend-design 插件调研 与 Vue 旧系统风格一致性方案
前端·vue.js·人工智能