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 后,重写了 getpostputpatchdelete 的注册方法。路径以 /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%:业务定制业务规则接口实现数据访问中间件顺序

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

相关推荐
CappuccinoRose2 小时前
模块化体系
前端·import·export·es modules
AIDANHANG2 小时前
放开靠时间戳对日志前先核请求ID跨服务传播与采样关联
前端·人工智能
半生过往4 小时前
前端学 Java 课程笔记
java·前端·笔记
广州华水科技4 小时前
2026年单北斗GNSS变形监测系统推荐,破解水库安全监测难题
前端
独爱香菜5 小时前
Next.js 15 + Cloudflare Workers 实战:零中间件多语言 SEO 站点架构
前端
计算机魔术师5 小时前
DeepSeek、Qwen3比肩GPT-5,本地跑大模型的时代来了
前端
xcyxiner5 小时前
flutter wsl2安装记录(使用宿主机虚拟机)
前端·flutter
前端炒粉5 小时前
长会话虚拟滚动与渲染优化
前端·javascript·vue.js
花归去6 小时前
ant的a-table更改表格的高度
前端·javascript·html