背景:作为一个写了8年多的前端,一个一直在写CRUD功能的前端,一个想脱离这种模式的前端,在偶然间的刷抖音的时候发现了哲玄,他是我之前就有关注的抖音博主,之前关注他是因为他直播一直是面试别人,在他的直播间我能学到很多我不知道东西来补充我的知识体系,直到有一天他提出了一个概念《全栈领域模型框架 elpis》,经过了解我发现很适合我,就跟着学了,此文章就是记录我所学习的东西。
elpis 框架模块化设计详解
elpis 框架的模块化设计是其核心优势之一,通过将应用拆分为独立且可复用的模块,结合「约定优于配置」的理念,实现了代码的高内聚低耦合。以下从模块划分、加载机制、核心特性三个维度展开说明:
一、模块划分与目录结构
elpis 框架通过预定义目录结构实现模块隔离,每个目录对应特定功能模块,具体如下:
目录路径 | 模块功能描述 |
---|---|
config/ |
存放环境配置模块,包含默认配置(config.default.js)、开发环境(config.local.js)、生产环境(config.prod.js)等,支持环境差异化配置。 |
app/controller/ |
控制器模块,处理 HTTP 请求并返回响应,调用 service 层完成业务逻辑,例如用户登录接口、数据查询接口等。 |
app/service/ |
服务模块,封装核心业务逻辑(如数据处理、第三方 API 调用),供多个控制器复用,避免代码冗余。 |
app/middleware/ |
中间件模块,基于 Koa 洋葱圈模型实现请求预处理(如身份验证、参数校验)、异常捕获等,支持全局(middleware.js)和局部中间件。 |
app/extend/ |
扩展模块,为 Koa 实例添加额外功能(如日志工具、工具函数),直接挂载到 app 实例供全局使用。 |
app/router/ |
路由模块,定义 URL 与控制器的映射关系,支持多级路由配置,例如将/api/user 映射到userController 的相关方法。 |
app/router-schema/ |
接口校验模块,使用 JSON Schema 描述接口参数规则(如必填项、数据类型),配合 AJV 库实现自动校验。 |
二、模块加载机制
elpis 通过专属 Loader 实现模块的自动化加载,每个模块对应独立的 Loader,加载流程遵循「依赖优先」原则,具体如下:
1. 加载顺序与依赖关系
加载顺序为:config
→ extend
→ service
→ middleware
→ routerSchema
→ controller
→ router
,核心逻辑是:
- 前置依赖模块优先加载 :如
config
作为全局配置,被所有模块依赖,因此最先加载; - 业务层模块后置加载 :如
router
依赖controller
的方法映射,因此最后加载。
2. 核心 Loader 实现逻辑
- configLoader :读取
config
目录下的环境配置文件,通过Object.assign
合并默认配置与环境配置,最终挂载到app.config
。 - controllerLoader :递归扫描
app/controller
下的所有 JS 文件,将文件名转为驼峰式命名(如user-info.js
→userInfo
),以层级结构挂载到app.controller
,支持通过app.controller.userInfo.getUser
调用控制器方法。 - middlewareLoader :加载中间件文件并挂载到
app.middlewares
,与 controller 不同的是,中间件以函数形式直接挂载(无需实例化),便于 Koa 框架直接调用。 - routerSchemaLoader :合并所有 JSON Schema 文件,形成全局接口规则映射,挂载到
app.routerSchema
,供中间件或控制器进行参数校验。
三、模块化设计的核心特性
-
职责单一性
每个模块专注于单一功能,例如
service
层仅处理业务逻辑,controller
层仅处理请求响应,避免功能混杂。例如:- 当需要修改用户数据校验规则时,只需修改
router-schema
中的对应 Schema 文件; - 当需要优化数据查询逻辑时,仅需调整
service
层的查询方法。
- 当需要修改用户数据校验规则时,只需修改
-
可扩展性
支持通过
extend
目录扩展框架功能,例如添加日志工具:javascript
javascript// app/extend/log.js module.exports = (app) => ({ info: (message) => console.log(`[INFO] ${message}`) }); // 使用时直接调用 app.log.info('请求成功')
-
环境适配性
通过
config
模块的多环境配置,可在开发、测试、生产环境中自动加载对应配置,例如数据库连接地址:javascript
java// config.prod.js(生产环境) module.exports = { db: { host: 'prod-db.example.com' } }; // config.local.js(开发环境) module.exports = { db: { host: 'localhost' } };
-
低侵入性
开发者无需手动配置模块加载规则,只需遵循目录约定即可,框架自动完成加载与挂载,减少重复工作。例如新增控制器时,只需在
app/controller
下创建文件,elpis 会自动识别并挂载。
四、模块化设计的优势
-
降低学习成本:固定的目录结构和加载规则让开发者快速上手,无需关注底层实现;
-
提升开发效率:自动化加载减少配置代码,开发者可专注业务逻辑;
-
便于团队协作:统一的模块划分让团队成员遵循一致的开发规范,减少沟通成本;
-
增强可维护性:模块间低耦合,修改某一模块不会影响其他功能,便于后期迭代。
通过这种模块化设计,elpis 框架实现了「约定即配置」的开发体验,特别适合中小型全栈项目快速开发,同时为复杂业务场景提供了灵活的扩展能力。