基于 Node.js + Koa 实现的企业级服务端框架内核,采用”约定优于配置”的设计理念,通过 Loader 机制实现自动扫描与挂载。
elpis.start(options)
功能:
- 创建 Koa 实例
- 初始化路径配置(baseDir、businessPath)
- 按依赖顺序执行各类 Loader
- 启动 HTTP 服务
app.env
config.js 分层配置加载
app.config
extend.js 框架扩展
app.xxx
service.js 服务层加载
app.service.xxx
middleware.js 中间件加载
app.middlewares.xxx
router-schema.js API Schema 加载
app.routerSchema
controller.js 控制器加载
app.controller.xxx
router.js 路由注册 Koa Router
app/ ├── controller/ # 控制器 → app.controller.xxx ├── service/ # 服务层 → app.service.xxx ├── middleware/ # 中间件 → app.middlewares.xxx ├── extend/ # 扩展 → app.xxx ├── router/ # 路由定义 ├── router-schema/ # API 校验规则 ├── public/ # 静态资源/模板 └── middleware.js # 全局中间件注册
config/ ├── config.default.js # 默认配置(必选) ├── config.local.js # 本地开发(可选) ├── config.beta.js # 测试环境(可选) └── config.prod.js # 生产环境(可选)
// 第一阶段:基础能力(被依赖的先加载) configLoader(app) // 1. 配置 - 所有模块都可能用 extendLoader(app) // 2. 扩展 - 先扩展 app,再加载业务
// 第二阶段:业务模块(依赖上层) serviceLoader(app) // 3. 服务 middleWareLoader(app) // 4. 业务中间件(暂不注册) routerSchemaLoader(app)// 5. 路由 Schema controllerLoader(app) // 6. 控制器
// 第三阶段:注册(按洋葱模型) app.use(middlewares.xxx) // 全局中间件 routerLoader(app) // 路由及路由级中间件
考量:确保被依赖的模块先加载,避免 undefined 错误。
- 文件自动扫描:无需手动
require和new - 命名转换:kebab-case → camelCase
- 结构映射:目录结构 → 对象嵌套结构
优势:
- 减少重复代码
- 统一项目结构
- 降低上手成本
// service/controller 中访问配置 constructor() { this.app = app this.config = app.config }
优势:
- 解耦模块间依赖
- 便于单元测试(可 mock app)
- 统一数据来源
请求处理链路
flowchart LR A["Request"] –> B["errorHandle"] B –> C["apiSignVerify"] C –> D["router match"] D –> E["router.use(‘/api’, apiParamsVerify)"] E –> F["controller"] F –> G["service"] G –> H["response"]
补充:apiParamsVerify 作为路由级中间件挂载在 /api 下,这个设计是正确的,能确保路由参数注入后再校验。
请求 → error-handle → api-sign-verify → router.routes()
↓ api-params-verify ↓ controller
关键设计:
- 全局中间件用
app.use()注册 - 路由级中间件用
router.use()挂载 - 确保执行顺序符合业务逻辑
用于构建嵌套对象结构:
// 输入:'customModule/customService'
// 输出:{ customModule: { customService: … } }
let cursor = service // cursor 是"钻头" for (const key of names) cursor = cursor[key] // 逐层深入 }
优势:
- 优雅处理任意层级嵌套
- 代码可读性强
问题:Object.assign 是浅合并
const base = { db: { host: ‘prod’, port: 3306 } } const override = { db: { host: ‘local’ } }
Object.assign({}, base, override) // 结果:{ db: { host: ‘local’ } } ← port 丢失!
当前状态:代码中存在此问题,待实现深度合并。
只捕获预期的错误:
try { envConfig = require(‘config.beta.js’) } catch (error) else {
// 语法错误等,必须暴露 throw error
} }
原因:盲目捕获所有错误会掩盖真正的问题。
问题场景:api-params-verify 需要获取 ctx.params
// 错误顺序:params 还未注入 app.use(apiParamsVerify) // ← params 为 undefined app.use(router.routes())
// 正确做法:挂在路由下 router.use(‘/api’, apiParamsVerify) // ← params 已注入
router.get(‘*’, async (ctx, next) => { ctx.status = 302 // 临时重定向,非永久(301) ctx.redirect(app.options?.homePage) })
考量:使用 302 而非 301,因为模板缺失是临时问题。
Date.now() - st > // 10分钟
安全考量:防止重放攻击,签名有时效性。
已达成:
- ✅ 完整的 Loader 体系
- ✅ 约定优于配置的目录结构
- ✅ 分层架构(Config → Service → Controller)
- ✅ 中间件系统
- ✅ 参数校验与签名安全
- ✅ 错误处理机制
下一步规划
- 里程碑1:基于 Node.js 实现服务端内核引擎 ✅
- 里程碑2:基于 Webpack5 完成工程化建设
- 里程碑3:基于 Vue3 完成领域模型架构建设
- 里程碑4:基于 Vue3 完成动态组件库建设
- 里程碑5:完成 elpis-npm 包分离并发布
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/281692.html