学习 elpis 有感 -- 初识 elpis-core (实现简易版 Egg.js)

首先什么是 Egg.js ?

Egg.js 是 阿里 开源的 Node.js 企业级应用框架 ,基于 Koa 封装,提供更强的规范性和扩展性。它的核心理念是 "约定大于配置"(Convention Over Configuration) ,即通过 "预设规则" 减少开发者的决策成本,提升团队协作效率。

为什么要用约定 ?

核心原因分为两种:1. 开发习惯差异 2. 人员更迭风险

我们假设一个场景,开发者A可能将用户模块的数据库操作写在Controller里(MVC习惯),开发者B却独立出Domain Service层(DDD习惯)。比如项目组有10人,开发习惯五花八门。有一天B离职了工作需要A接手,A不得不花费大量时间理解这些个性化风格;再假设项目干上2-3年,恐怕会慢慢变成一个烫手的山芋...没人愿意接手这个烂摊子。于是 "约定大于配置" 的理念诞生了,Egg.js 强制约定 controller 只处理HTTP请求、service 承载业务逻辑... 使得新人加入时能立即定位代码。

elpis-core 登场

elpis-core 是参考 Egg.js "约定大于配置" 理念实现的服务端框架。

核心分为以下7个模块:

  • middleware(中间件)
  • config(配置项)
  • router(路由)
  • router-schema(路由参数校验规范)
  • controller(控制器)
  • service(服务)
  • extend(扩展例如日志)

接下来我用 middleware.js 举例说明 elpis-core 内核内部运作的原理。

ini 复制代码
module.exports = (app) => {
    // 读取 app/middleware/**/**.js 下所有的文件
    const middlewarePath = path.resolve(app.businessPath, `.${sep}middleware`);
    const fileList = glob.sync(path.resolve(middlewarePath, `.${sep}**${sep}**.js`));

    // 遍历所有文件目录,把内容加载到 app.middlewares 下
    const middlewares = {};
    fileList.forEach((file) => {
        // 提取文件名称
        let name = path.resolve(file);

        // 截取路径 app/middleware/custom-module/custom-middleware.js => custom-module/custom-middleware
        name = name.substring(name.lastIndexOf(`middleware${sep}`) + `middleware${sep}`.length, name.lastIndexOf("."));

        // 把 '-' 统一改为驼峰式,custom-module/custom-middleware => customModule.customMiddleware
        name = name.replace(/[_-][a-z]/gi, (s) => s.substring(1).toUpperCase());

        // 挂载 middleware 到内存 app 对象中
        let tempMiddleware = middlewares;
        const names = name.split(sep);
        for (let i = 0, len = names.length; i < len; ++i) {
            if (i === len - 1) {
                // 文件
                tempMiddleware[names[i]] = require(path.resolve(file))(app);
            } else {
                // 文件夹
                if (!tempMiddleware[names[i]]) {
                    tempMiddleware[names[i]] = {};
                }
                tempMiddleware = tempMiddleware[names[i]];
            }
        }
    });
    app.middlewares = middlewares;
};

这段代码实现了一个 自动加载中间件 的机制,它会扫描 app/middleware/ 目录下的所有 .js 文件,并按一定的规则挂载到 app.middlewares 对象上,方便在项目中统一调用。

例如我创建了文件: app/middleware/api-params-verify.js ,那么我可以在任何地方 app.middlewares.apiParamsVerify 使用它。再或者我们进行业务开发时定义了一个 service app/service/project.js 那么我们可以直接在controller中这样去调用 project 的 getList 方法。

ini 复制代码
const { project: projectService } = app.service;
const projectList = projectService.getList();

其余模块的原理也类似,在此不做过多代码说明。

结语

elpis-core 它就像是一个乐高说明书,虽然限制了拼装方式,但能保证所有人拼出来的都是稳固结构,特别适合需要长期维护的企业级应用。

相关推荐
fruge2 分钟前
Canvas/SVG 冷门用法:实现动态背景与简易数据可视化
前端·信息可视化
一 乐7 分钟前
旅游|内蒙古景点旅游|基于Springboot+Vue的内蒙古景点旅游管理系统设计与实现(源码+数据库+文档)
开发语言·前端·数据库·vue.js·spring boot·后端·旅游
驯狼小羊羔18 分钟前
学习随笔-require和import
前端·学习
excel25 分钟前
🚀 从 GPT-5 流式输出看现代前端的流式请求机制(Koa 实现版)
前端
凸头29 分钟前
Spring Boot接收前端参数的注解总结
前端·spring boot·后端
爱吃甜品的糯米团子1 小时前
JavaScript 正则表达式:选择、分组与引用深度解析
前端·javascript·正则表达式
excel1 小时前
Vue SSR 编译器源码深析:ssrTransformShow 的实现原理与设计哲学
前端
excel1 小时前
深入解析 Vue 3 SSR 编译管线:ssrCodegenTransform 源码全解
前端
excel1 小时前
深入解析 Vue SSR 编译器的核心函数:compile
前端
IT_陈寒1 小时前
Vue 3性能优化实战:7个关键技巧让我的应用加载速度提升50%
前端·人工智能·后端