基于nodejs实现服务端内核引擎

Elpis-Core 深度理解:企业级 Node.js 框架架构解析

什么是 Elpis-Core?

Elpis-Core 是一个基于 Koa 的 Node.js 内核实现。

分层架构

三层设计

markdown 复制代码
┌─────────────────────────────────────┐
│  Controller 层(业务逻辑入口)        │
│  - 接收请求                          │
│  - 参数校验                          │
│  - 调用 Service                      │
│  - 返回响应                          │
└─────────────────────────────────────┘
           ↓
┌─────────────────────────────────────┐
│  Service 层(数据处理)               │
│  - 业务逻辑处理                      │
│  - 数据库操作                        │
│  - API 调用                          │
│  - 数据转换                          │
└─────────────────────────────────────┘
           ↓
┌─────────────────────────────────────┐
│  Middleware 层(横切关注点)          │
│  - 参数校验                          │
│  - 权限验证                          │
│  - 异常处理                          │
│  - 日志记录                          │
└─────────────────────────────────────┘

模块化加载

Loader 系统

  • 先扫描目录
  • 再加载模块
  • 然后挂载到 app
  • 支持层级嵌套

启动入口(index.js)

核心流程

javascript 复制代码
const Koa = require("koa");
const path = require("path");
const { sep } =path; 

const env = require("./env");

const middlewareLoader = require("./loader/middleware");
const routerSchemaLoader = require("./loader/router-schema");
const routerLoader = require("./loader/router");
const controllerLoader = require("./loader/controller");
const serviceLoader = require("./loader/service");
const configLoader = require("./loader/config");
const extendLoader = require("./loader/extend");

module.exports = {
    /**
     * 启动项目
     * @params options 项目配置
     * options = {
     *  name 项目名称
     *  homePath 项目首页
     * }
     */
  start(options) {
    // 实例化
    const app = new Koa();

    // 应用配置
    app.options = options; 
    
    // 项目基础路径
    app.baseDir = process.cwd();

    // 业务文件路径
    app.businessPath = path.resolve(app.baseDir, `.${sep}app`);

    // 初始化环境变量
    app.env = env();
    console.log(`-- [start] env: ${app.env.get()} --`);

    // 加载配置 config
    configLoader(app);
    console.log(`-- [start] load config done --`);

    // 加载扩展 extend
    extendLoader(app);
    console.log(`-- [start] load extend done --`);

    // 加载中间件 middleware
    middlewareLoader(app);
    console.log(`-- [start] load middleware done --`);

    // 加载路由 routerSchema
    routerSchemaLoader(app);
    console.log(`-- [start] load routerSchema done --`);

    // 加载服务 service
    serviceLoader(app);
    console.log(`-- [start] load service done --`);

    // 加载控制器 controller
    controllerLoader(app);
    console.log(`-- [start] load controller done --`);
    
    // 注册全局中间件
    // app/middlewareLoader.js
    try{
      require(`${app.businessPath}${sep}middleware.js`)(app);
      console.log(`-- [start] load global middleware done --`);
    }catch(e){
      console.log(`[exception] there is no global middleware file`)
    }

    // 加载路由 router (因为需要经过中间件所以路由分发在最后)
    routerLoader(app);
    console.log(`-- [start] load router done --`);


    // 启动服务
    try {
      const port = process.env.PORT || 8080;
      const host = process.env.IP || "0.0.0.0";
      app.listen(port, host);
      console.log(`Server running on port: ${port}`);
    } catch (e) {
      console.log(e);
    }
  },
};

关键点

  • app 对象是整个框架的核心
  • 所有模块都挂载到 app
  • Loader 按顺序加载,有依赖关系
  • 路由最后加载,确保中间件已注册

Loader 加载机制

Loader 系统概览

Elpis-Core 提供了 7 个 Loader,每个负责加载特定类型的模块:

Loader 功能 输出 依赖
configLoader 加载配置 app.config env
extendLoader 加载扩展 扩展 app
middlewareLoader 加载中间件 app.middlewares
routerSchemaLoader 加载校验规则 app.routerSchema
serviceLoader 加载服务 app.service config
controllerLoader 加载控制器 app.controller service
routerLoader 加载路由 注册路由 controller, routerSchema

Loader 工作原理

通用加载流程

javascript 复制代码
// 1. 扫描目录
const fileList = glob.sync(path.resolve(directory, '**/**.js'));

// 2. 遍历文件
fileList.forEach(file => {
  // 3. 提取文件名
  let name = extractFileName(file);
  
  // 4. 转换命名(驼峰)
  name = name.replace(/[_-][a-z]/ig, s => s.substring(1).toUpperCase());
  
  // 5. 加载模块
  const module = require(file)(app);
  
  // 6. 挂载到 app
  app[category][name] = module;
});

1. Middleware Loader

中间件,采用洋葱圈模型,实现请求参数校验、异常捕获等功能,可以横向拓展。

2. Controller Loader

请求控制,进行http统一处理,api响应等业务处理能力。

3. Service Loader

服务层,负责主要业务逻辑,对数据进行处理,实现数据的获取返回等等。

4. Config Loader

配置层,先行加载,不同配置文件加载不同环境配置信息等。

5. Router Schema Loader

对router进行校验,通过加载json-schema对api进行规则约束。

6. Extend Loader

加载extend模块,将其挂载到app示例,实现横向功能扩展。

7. Router Loader

加载路由模块,根据router-schema动态生成路由并挂载到koa实例上,统一管理。

中间件执行流程

scss 复制代码
        ┌─────────────────────────────┐
        │     请求进入                 │
        └─────────────────────────────┘
                    ↓
        ┌─────────────────────────────┐
        │  koa-static (静态文件)       │  ← 第一层
        └─────────────────────────────┘
                    ↓
        ┌─────────────────────────────┐
        │  koa-nunjucks (模板引擎)     │  ← 第二层
        └─────────────────────────────┘
                    ↓
        ┌─────────────────────────────┐
        │  bodyParser (请求解析)       │  ← 第三层
        └─────────────────────────────┘
                    ↓
        ┌─────────────────────────────┐
        │  errorHandler (异常处理)     │  ← 第四层
        └─────────────────────────────┘
                    ↓
        ┌─────────────────────────────┐
        │  apiSignVerify (签名校验)    │  ← 第五层
        └─────────────────────────────┘
                    ↓
        ┌─────────────────────────────┐
        │  apiParamsVerify (参数校验)  │  ← 第六层
        │  - 校验 headers              │
        │  - 校验 query                │
        │  - 校验 body                 │
        └─────────────────────────────┘
                    ↓
        ┌─────────────────────────────┐
        │  koa-router (路由匹配)       │  ← 第七层
        │  - ctx.params 注入           │
        └─────────────────────────────┘
                    ↓
        ┌─────────────────────────────┐
        │  paramsValidator (参数校验)  │  ← 第八层
        │  - 校验 params               │
        └─────────────────────────────┘
                    ↓
        ┌─────────────────────────────┐
        │  Controller (业务逻辑)       │  ← 第九层
        └─────────────────────────────┘
                    ↓
        ┌─────────────────────────────┐
        │     响应返回                 │
        └─────────────────────────────┘

中间件注册顺序

javascript 复制代码
// app/middleware.js
module.exports = (app) => {
  // 1. 静态文件服务
  app.use(koaStatic('./app/public'));
  
  // 2. 模板渲染引擎
  app.use(koaNunjucks({ ext: 'tpl', path: './app/public' }));
  
  // 3. 请求体解析
  app.use(bodyParser());
  
  // 4. 异常捕获
  app.use(app.middlewares.errorHandler);
  
  // 5. 签名校验
  app.use(app.middlewares.apiSignVerify);
  
  // 6. 参数校验(headers/query/body)
  app.use(app.middlewares.apiParamsVerify);
};

params 校验的特殊处理

问题:params 在路由匹配后才注入,无法在路由前校验。

解决方案

javascript 复制代码
// elpis-core/loader/router.js
const { createParamsValidator } = require('../middleware/validate');

module.exports = (app) => {
  const router = new KoaRouter();
  
  // 在路由内部注册 params 校验中间件
  router.use(createParamsValidator(app));
  
  // 注册路由...
};

执行时机

csharp 复制代码
请求 → apiParamsVerify → koa-router → paramsValidator → Controller
        ↑ 校验headers等    ↑ 注入params   ↑ 校验params

总结

搭建内核引擎不是要去理解业务需求,而是对程序的架构思维理解,如何通过统一约束,通过同种方式加载不同功能,理解生命周期去优化执行顺序,是应用页面开发到架构设计的过渡。

相关推荐
To_OC1 小时前
写了三遍 Todo List,我终于搞懂了 React 父子组件到底怎么通信
前端·javascript·react.js
勇往直前plus2 小时前
Vue3(篇一) 核心概念——响应式模板语法与组件基础
前端·javascript·vue.js
用户938515635073 小时前
从零搭建 AI 日记助手:用 Milvus 向量数据库 + RAG 让机器读懂你的每一天
javascript·人工智能·全栈
a1117764 小时前
坦克大战3D Three.js 3D (开源项目)
开发语言·javascript·3d
kyriewen5 小时前
别再乱用useEffect了——你写的10个里有8个不该存在
前端·javascript·react.js
Ivanqhz5 小时前
Rust &‘static str浅析
java·前端·javascript·rust
zandy10116 小时前
衡石 Agentic BI的ReAct 推理框架在 Agentic BI 中的工程化实践
前端·javascript·react.js
郝亚军7 小时前
webstorm如何创建vue 3.js
javascript·vue.js·webstorm
এ慕ོ冬℘゜7 小时前
jQuery attr() 方法超详细讲解:属性获取、赋值、实战踩坑全解
前端·javascript·jquery
Hilaku8 小时前
为什么大厂对前端算法要求极高?
前端·javascript·程序员