搜索 抖音"哲玄前端"《大前端全栈实践》
Elpis-Core 架构设计
概述
Elpis-Core 是基于 Koa.js 构建的企业级 Node.js 应用框架,采用约定优于配置的设计理念,通过自动化加载机制和模块化架构,为开发者提供开箱即用的全栈开发体验。
整体架构设计
架构图


分层架构
- 框架核心层 - 基于 Koa.js 的核心运行时
- 自动加载层 - 通过 Loader 模块自动发现和加载业务代码
- 业务逻辑层 - 控制器、服务、中间件等业务组件
- 配置管理层 - 环境配置、路由模式配置等
设计原则
1. 约定优于配置 (Convention over Configuration)
- 文件命名约定: kebab-case 文件名自动转换为 camelCase 属性名
- 目录结构约定: 固定的目录结构自动映射到应用对象属性
- 环境配置约定: 通过环境变量自动选择配置文件
javascript
// 文件: app/controller/user-profile.js
// 映射: app.controller.userProfile
// 文件: app/service/data-processor.js
// 映射: app.service.dataProcessor
2. 自动化加载 (Auto Loading)
- 零配置启动: 框架启动时自动扫描并加载所有业务模块
- 热重载友好: 文件系统监听,支持开发期间的动态加载
- 依赖注入: 自动解析模块间依赖关系
3. 模块化架构 (Modular Architecture)
- 单一职责: 每个 Loader 只负责一种类型的模块加载
- 松耦合: 模块间通过 app 实例进行通信,减少直接依赖
- 可扩展性: 支持自定义 Loader 和插件机制
4. 环境一致性 (Environment Consistency)
- 多环境支持: local、beta、production 环境配置
- 配置继承: 环境配置覆盖默认配置的继承机制
- 环境隔离: 不同环境下的行为差异化管理
核心架构特点
1. 启动生命周期管理
javascript
// 严格按顺序执行的启动流程
app.env = env() // 1. 环境检测
configLoader(app) // 2. 配置加载
extendLoader(app) // 3. 扩展加载
middlewareLoader(app) // 4. 中间件定义加载
routerSchemaLoader(app) // 5. 路由模式加载
controllerLoader(app) // 6. 控制器加载
serviceLoader(app) // 7. 服务加载
middleware.js(app) // 8. 基础中间件注册
routerLoader(app) // 9. 路由注册
2. 智能命名转换
javascript
// kebab-case → camelCase 自动转换
'user-profile' → 'userProfile'
'api-params-verify' → 'apiParamsVerify'
'data-processor' → 'dataProcessor'
3. 嵌套模块支持
javascript
// 目录结构
app/controller/
├── user/
│ ├── profile.js
│ └── settings.js
└── admin/
└── dashboard.js
// 自动映射为
app.controller.user.profile
app.controller.user.settings
app.controller.admin.dashboard
4. 类工厂模式
javascript
// 控制器和服务采用类工厂模式
module.exports = (app) => {
return class UserController extends BaseController {
async getProfile(ctx) {
// 业务逻辑
}
}
}
模块详解
1. 环境模块 (env.js)
职责: 环境检测和管理
javascript
module.exports = (app) => {
return {
isLocal: () => process.env._ENV === "local",
isBeta: () => process.env._ENV === "beta",
isProduction: () => process.env._ENV === "production",
get: () => process.env._ENV ?? "local"
}
}
特性:
- 支持 local/beta/production 三种环境
- 提供便捷的环境判断方法
- 默认环境为 local
2. 配置加载器 (config.js)
职责: 多环境配置文件加载和合并
javascript
// 配置文件优先级
config.default.js // 基础配置
config.local.js // 本地环境覆盖
config.beta.js // 测试环境覆盖
config.production.js // 生产环境覆盖
加载策略:
- 加载默认配置
config.default.js
- 根据当前环境加载对应配置文件
- 使用
Object.assign()
合并配置 - 挂载到
app.config
3. 扩展加载器 (extend.js)
职责: 应用扩展功能加载
特性:
- 直接挂载到 app 实例上
- 冲突检测,防止覆盖已有属性
- 支持嵌套目录结构
- 命名转换 kebab-case → camelCase
使用示例:
javascript
// app/extend/logger.js
module.exports = (app) => {
return {
log: (message) => console.log(`[${app.env.get()}] ${message}`)
}
}
// 访问: app.logger.log('Hello')
4. 中间件加载器 (middleware.js)
职责: 中间件定义加载(非注册)
特性:
- 中间件工厂函数加载
- 挂载到
app.middlewares
对象 - 支持嵌套目录结构
- 延迟注册,由业务代码控制注册时机
5. 路由模式加载器 (router-schema.js)
职责: API 验证模式加载
javascript
// app/router-schema/user.js
module.exports = {
'/api/user/profile': {
get: {
query: {
type: 'object',
properties: { id: { type: 'string' } },
required: ['id']
}
}
}
}
特性:
- 基于 JSON Schema 的 API 验证规则
- 自动合并所有模式文件
- 挂载到
app.routerSchema
- 配合 API 参数验证中间件使用
6. 控制器加载器 (controller.js)
职责: 控制器类加载和实例化
特性:
- 类工厂模式支持
- 自动实例化控制器类
- 嵌套目录支持
- 挂载到
app.controller
7. 服务加载器 (service.js)
职责: 服务类加载和实例化
特性:
- 与控制器加载器类似的机制
- 业务逻辑封装
- 可复用的服务组件
- 挂载到
app.service
8. 路由加载器 (router.js)
职责: 路由定义加载和注册
javascript
// app/router/user.js
module.exports = (app, router) => {
const { user: UserController } = app.controller
router.get('/api/user/profile',
app.middlewares.apiParamsVerify,
UserController.getProfile.bind(UserController)
)
}
特性:
- 基于 koa-router
- 自动扫描路由文件
- 支持路由级中间件
- 提供路由兜底机制
项目结构
ruby
elpis/
├── elpis-core/ # 框架核心
│ ├── index.js # 框架入口和启动流程
│ ├── env.js # 环境管理模块
│ └── loader/ # 加载器模块
│ ├── config.js # 配置加载器
│ ├── extend.js # 扩展加载器
│ ├── middleware.js # 中间件加载器
│ ├── router-schema.js # 路由模式加载器
│ ├── controller.js # 控制器加载器
│ ├── service.js # 服务加载器
│ └── router.js # 路由加载器
├── app/ # 业务代码目录
│ ├── controller/ # 控制器
│ ├── service/ # 服务层
│ ├── middleware/ # 中间件定义
│ ├── router/ # 路由定义
│ ├── router-schema/ # API 验证模式
│ ├── extend/ # 应用扩展
│ ├── public/ # 静态资源和模板
│ └── middleware.js # 基础中间件注册
├── config/ # 配置文件
│ ├── config.default.js # 默认配置
│ ├── config.local.js # 本地环境配置
│ ├── config.beta.js # 测试环境配置
│ └── config.production.js # 生产环境配置
└── index.js # 应用入口
数据流
1. 启动阶段数据流
markdown
Environment Detection → Configuration Loading → Extension Loading
↓
Middleware Definition Loading → Schema Loading → Controller Loading
↓
Service Loading → Base Middleware Registration → Router Registration
2. 请求处理数据流
vbscript
HTTP Request → Koa Middleware Stack → Route Matching
↓
Route-level Middleware → Controller Method → Service Layer
↓
Business Logic Processing → Response Generation → HTTP Response
3. 模块依赖关系
markdown
┌─────────────┐ ┌──────────────┐ ┌─────────────┐
│ Config │───→│ Extend │───→│ Middleware │
└─────────────┘ └──────────────┘ └─────────────┘
│ │ │
↓ ↓ ↓
┌─────────────┐ ┌──────────────┐ ┌─────────────┐
│ Schema │ │ Controller │───→│ Router │
└─────────────┘ └──────────────┘ └─────────────┘
│ │ │
└───────────────────┼───────────────────┘
↓
┌──────────────┐
│ Service │
└──────────────┘
核心优势
1. 开发效率
- 零配置启动: 新建文件自动加载,无需手动注册
- 约定优于配置: 减少配置文件数量和复杂度
- 热重载支持: 开发期间修改代码立即生效
2. 代码质量
- 强制分层: 控制器、服务、中间件清晰分离
- 统一规范: 文件命名和目录结构标准化
- 类型安全: 基于 JSON Schema 的 API 验证
3. 可维护性
- 模块化设计: 每个 Loader 职责单一,易于理解和维护
- 松耦合架构: 模块间通过 app 实例通信,降低耦合度
- 扩展友好: 支持自定义扩展和插件
4. 生产就绪
- 多环境支持: 开发、测试、生产环境配置管理
- 错误处理: 完善的异常处理和错误恢复机制
- 性能优化: 基于 Koa.js 的高性能请求处理
最佳实践
1. 目录组织
- 按功能模块组织目录结构
- 控制器保持简洁,复杂逻辑下沉到服务层
- 中间件职责单一,可复用性强
2. 命名规范
- 文件名使用 kebab-case
- 类名使用 PascalCase
- 方法名使用 camelCase
3. 配置管理
- 敏感配置通过环境变量传递
- 配置文件支持注释和文档
- 不同环境配置差异最小化
4. 错误处理
- 统一的错误响应格式
- 完善的日志记录
- 优雅的降级处理
扩展开发
自定义 Loader
javascript
// elpis-core/loader/custom.js
module.exports = (app) => {
// 自定义加载逻辑
const customPath = path.resolve(app.businessPath, './custom')
const fileList = glob.sync(path.resolve(customPath, './**/*.js'))
fileList.forEach(file => {
// 处理文件加载
})
}
自定义中间件
javascript
// app/middleware/rate-limit.js
module.exports = (app) => {
return async (ctx, next) => {
// 限流逻辑
await next()
}
}
自定义扩展
javascript
// app/extend/utils.js
module.exports = (app) => {
return {
formatDate: (date) => {
// 日期格式化逻辑
}
}
}