Elpis-core
概述
Elpis-core 是一个基于 Koa.js 的轻量级 Web 框架核心,其 Loader 机制负责应用的模块加载、依赖管理和生命周期控制。整个 Loader 系统由 7 个独立的加载器组成,各司其职,按依赖关系顺序执行。
一、configLoader(配置加载器)
职责
加载并合并应用配置,支持多环境配置管理。
加载逻辑
javascript
// 加载顺序:先加载默认配置,再用环境配置覆盖
config/
├── config.default.js // 基础配置
├── config.local.js // 本地开发环境
├── config.beta.js // 测试环境
└── config.prod.js // 生产环境
核心功能
- 读取
config.default.js作为基础配置 - 根据当前环境变量加载对应的环境配置文件
- 使用
Object.assign进行配置合并(环境配置覆盖默认配置) - 将最终结果挂载到
app.config
依赖关系
被所有其他模块依赖,必须最先加载。
二、extendLoader(扩展加载器)
职责
扩展框架核心能力,为 app 和 ctx 对象挂载自定义方法和属性。
加载逻辑
javascript
extend/
├── helper.js // 辅助工具函数
├── logger.js // 日志方法
└── request.js // 请求扩展
核心功能
- 扫描
extend/目录下的所有模块 - 将模块导出的方法挂载到
app实例 - 通过中间件机制将方法挂载到
ctx对象 - 提供框架级别的扩展能力
依赖关系
依赖 configLoader(扩展方法可能需要读取配置),被 serviceLoader 和 controllerLoader 依赖。
三、serviceLoader(服务加载器)
职责
加载业务逻辑层模块,封装数据操作和第三方服务调用。
加载逻辑
javascript
service/
├── user.js // 用户服务
├── order.js // 订单服务
└── email.js // 邮件服务
核心功能
- 扫描
service/目录下的所有文件 - 实例化服务类或直接导出对象
- 将服务挂载到
app.service和ctx.service - 处理服务之间的依赖注入
依赖关系
依赖 configLoader 和 extendLoader,被 controllerLoader 依赖。
四、controllerLoader(控制器加载器)
职责
加载控制器模块,处理 HTTP 请求和响应。
加载逻辑
javascript
controller/
├── user.js // 用户控制器
└── home.js // 首页控制器
核心功能
- 扫描
controller/目录下的所有文件 - 加载控制器方法
- 将控制器挂载到
app.controller - 为路由注册做准备
依赖关系
依赖 serviceLoader(控制器需要调用服务),被 routerLoader 依赖。
五、middlewareLoader(中间件加载器)
职责
加载应用级中间件,处理请求拦截、预处理和后置处理。
加载逻辑
javascript
middleware/
├── auth.js // 认证中间件
├── logger.js // 日志中间件
├── cors.js // 跨域中间件
└── error.js // 错误处理中间件
核心功能
- 扫描
middleware/目录下的中间件 - 按配置顺序注册中间件到 Koa 应用
- 支持全局中间件和路由级中间件
- 可配置中间件执行顺序
依赖关系
依赖 configLoader(中间件可能需要配置),在 routerLoader 之前注册(部分中间件需要在路由之前执行)。
六、routerSchemaLoader(路由规则加载器)
职责
定义路由的元信息,包括请求方法、路径、参数校验规则等。
加载逻辑
javascript
routerSchema/
├── user.js // 用户路由规则
└── api.js // API 路由规则
核心功能
- 扫描
routerSchema/目录下的路由定义 - 解析路由的 method、path、validate 等元信息
- 为
routerLoader提供路由配置数据 - 支持参数校验、权限声明等扩展配置
依赖关系
被 routerLoader 依赖,无其他依赖。
七、routerLoader(路由加载器)
职责
将路由规则与控制层方法绑定,注册到 Koa 路由实例。
加载逻辑
- 读取
routerSchemaLoader生成的路由配置 - 找到对应的
controller方法 - 注册到 Koa Router 实例
核心功能
javascript
// 伪代码示例
routerSchema.forEach(route => {
const { method, path, controller, action } = route
router[method](path, controller[action])
})
依赖关系
依赖 routerSchemaLoader 和 controllerLoader,必须在两者之后执行。
八、加载顺序总结
javascript
// 标准加载顺序
configLoader(app) // 1. 配置(最基础)
extendLoader(app) // 2. 扩展(工具方法)
serviceLoader(app) // 3. 服务层(业务逻辑)
controllerLoader(app) // 4. 控制器(请求处理)
middlewareLoader(app) // 5. 中间件(拦截处理)
routerSchemaLoader(app) // 6. 路由规则(元信息)
routerLoader(app) // 7. 路由注册(绑定)
设计原则
| 原则 | 说明 |
|---|---|
| 依赖先行 | 被依赖的模块必须先加载 |
| 配置优先 | 配置是所有模块的基础 |
| 路由最后 | 路由注册需要前面所有模块就绪 |
九、模块依赖关系图
arduino
configLoader
↓
extendLoader
↓
serviceLoader
↓
controllerLoader
↓
middlewareLoader ←─── 可独立,也可依赖 config
↓
routerSchemaLoader
↓
routerLoader
十、核心价值
- 自动化装配:无需手动 require 和管理文件依赖
- 顺序保证:确保模块按正确依赖顺序加载
- 约定优于配置:约定目录结构,框架自动扫描
- 扩展性强:支持自定义 Loader 和加载逻辑