Egg 框架概览:为企业级应用与框架而生的 Node.js 与 Koa 框架
【免费下载链接】egg🥚 Born to build better enterprise frameworks and apps with Node.js & Koa项目地址: https://gitcode.com/gh_mirrors/egg11/egg
Egg(Egg.js)是一个定位独特的 Node.js Web 框架——它不只是帮你写业务应用,更是一套"框架的框架":基于 Koa 提供 Web 开发的核心能力,并以此为核心支持开发者按团队约定定制出自己的上层框架。本文基于仓库中英文文档 docs/source/en/intro/index.md 展开,结合 package.json、lib/egg.js、config/plugin.js 等源码与配置,系统讲解 Egg 的设计原则、与社区框架的差异、核心特性及其落地机制,帮助架构师与技术负责人理解"为什么用 Egg、Egg 能带来什么"。
Egg 是什么
Egg 官方定位是一句话:Egg is born for building enterprise application and framework——为企业级框架和应用而生。它希望孕育出更多上层框架,帮助开发团队和开发人员降低开发与维护成本。
从仓库的 package.json 可以直观看到这一理念:项目描述为 "A web framework's framework for Node.js",即"用于构建 Node.js Web 框架的框架"。它的依赖清单里没有捆绑数据库、模板引擎、前端框架等业务技术选型,而是内置了一批与框架运行本身强相关的基础能力:egg-core(Loader 与核心基类)、egg-cluster(多进程管理)、egg-logger(日志)、egg-security(安全)、egg-view(视图抽象)、egg-session(会话)等。业务侧的选型(如用哪个数据库、哪套模板)则完全交给应用与上层框架通过插件自由决定。
设计原则
不做"大集市":专注核心,拒绝技术选型
社区常见 Web 框架往往采用"大集市"(giant bazaar)模式,开箱即用集成了数据库、模板引擎、前端框架等一揽子功能。Egg 的取舍恰恰相反:
- 只提供 Web 开发的核心功能:HTTP 处理、路由、中间件、配置、日志、多进程等;
- 提供一套灵活可扩展的插件机制:其余能力以插件形式按需引入;
- 不做默认技术选型:因为固定的技术选型会严重压缩框架的扩展性,无法满足千差万别的定制需求。
这一设计让团队的架构师和技术负责人可以基于自身已有的技术栈,在 Egg 之上非常容易地扩展出适合自己业务场景的框架。仓库中 lib/egg.js 的EggApplication类继承自egg-core的EggCore,正是"内核保持精简、能力通过挂载扩展"的体现。
一个插件只做一件事
Egg 的插件机制具有很高的可扩展性,其核心准则是one purpose for one plugin(一个插件只做一件事):
- Nunjucks 模板被封装为
egg-view-nunjucks这类视图插件; - MySQL 数据库访问被封装为
egg-mysql这类数据插件; - 框架通过聚合插件 + 按业务场景定制配置的方式组合能力,从而把应用开发成本降到最低。
以本仓库自身为例,config/plugin.js 集中声明了框架内置并默认启用的 12 个插件:onerror(统一异常处理)、session、i18n(多语言)、watcher(文件监控)、multipart(文件上传)、security(安全)、development(开发辅助)、logrotator(日志切分)、schedule(定时任务)、static(静态资源)、jsonp、view(模板引擎)。每个插件职责单一、可独立启停,这正是"一个插件只做一件事"在框架自身体系中的实践。
约定优于配置(Convention over Configuration)
Egg 奉行『约定优于配置』,按照一套统一的约定进行应用开发,其落点是 Loader 机制,详见 docs/source/zh-cn/advanced/loader.md。
约定的价值在于降低团队协作成本:
- 开发人员不再成为某个模块的"钉子",可以在不同项目间流动;
- 没有约定的团队沟通成本极高——例如有人按目录分"技术栈",有人按目录分"功能",开发者认知不一致很容易犯错。
以本仓库目录结构为典型示例:app/controller放控制器、app/service放业务逻辑、app/middleware放中间件、app/extend放扩展、config/config.{env}.js放各环境配置、app/router.js统一注册路由。任何人进入一个新项目都能立刻定位代码,这就是约定的力量。
但约定不等于扩展性差。Egg 在约定之上保留了极强的扩展能力:
- Loader 允许框架根据不同运行环境加载不同的默认配置(
config.local.js、config.prod.js、config.unittest.js等); - 团队的定制约定可以覆盖 Egg 的默认约定;
- 加载顺序为"插件 → 框架 → 应用",应用最晚加载,因此应用的约定天然拥有最高覆盖优先级(详见 docs/source/zh-cn/advanced/loader.md 中的
loadUnit章节)。
仓库中 lib/loader/app_worker_loader.js 的load()方法按序执行loadApplicationExtend → loadRequestExtend → loadResponseExtend → loadContextExtend → loadHelperExtend → loadCustomApp → loadService → loadMiddleware → loadController → loadRouter,与上述约定一一对应。
与社区框架的差异
与 Express 的对比
Express 是 Node.js 社区使用最广泛的框架,简单且扩展性强,非常适合个人项目。但它的主要短板在于:
- 缺少默认约定,标准 MVC 模型在不同人手里会有各种"千奇百怪"的写法;
- 团队内代码风格难以统一,协作成本高。
Egg 则通过『约定优于配置』强制了统一的开发范式,从而把团队协作成本显著压低——这正是企业级多团队协作最看重的点。
与 Sails 的对比
Sails 同样是奉行『约定优于配置』的框架,扩展性也很好,但两者的路线有本质区别:
- Sails 直接提供 Blueprint REST API、Waterline(可扩展 ORM)、前端集成、WebSocket 等功能,属于"框架直接提供功能";
- Egg不直接提供这些业务功能,而是通过插件集成各类功能扩展,例如社区分别实现
egg-blueprint、egg-waterline等插件,再用sails-egg这样的上层框架整合这些插件,即可实现类似 Sails 的能力组合。
换句话说,Egg 的能力边界更收敛、组合更自由:同样的功能可以通过换插件的方式完成替换与升级,而不必更换整个框架。
核心特性
基于 Egg 定制上层框架
Egg 提供定制上层框架的完整能力,详见 docs/source/zh-cn/advanced/framework.md。其核心模型是"应用 / 框架 / 插件"三层结构:
- 应用(Application):承载具体业务,必须依赖某个框架才能运行;
- 框架(Framework):是一个启动器(默认就是 Egg),也是封装器,将插件能力聚合统一提供,且框架可以无限级继承,类似于类的继承;
- 插件(Plugin):只完成特定功能,两个独立功能互相依赖时应保持两个插件、通过声明依赖关系组合。
仓库中 lib/application.js(Application)与 lib/agent.js(Agent)都继承自EggApplication,而EggApplication继承自egg-core的EggCore,形成了"Koa → EggCore → EggApplication → 上层框架 → 应用"的继承链,与文档描述的框架可继承特性完全吻合。
高度可扩展的插件机制
插件机制是 Egg 的核心特色,它解决了 Koa 中间件的三个痛点(详见 docs/source/zh-cn/advanced/plugin.md):
- 中间件无法自管理顺序:加载顺序只能交给使用者,顺序错了结果可能天壤之别;而插件通过
eggPlugin.dependencies/eggPlugin.optionalDependencies声明依赖,由框架自动计算加载顺序(如c => b => a); - 中间件定位狭窄:中间件只适合拦截请求,无法承载定时任务、消息订阅等与请求无关的逻辑;
- 复杂初始化逻辑无处安放:插件可以通过
app.js/agent.js结合app.beforeStart在应用启动时完成初始化。
插件本质上是一个"迷你应用",其目录结构与应用几乎一致(app/extend、app/service、app/middleware、config/config.{env}.js等),差异在于:插件没有独立的 router 与 controller,且通过package.json的eggPlugin节点声明插件名与依赖关系。此外,Egg 允许相同功能的插件使用相同的插件名(如视图类插件统一命名为view),使用者只需更换插件包即可无缝切换实现,这在模板引擎、数据库等领域非常实用。
内置多进程管理
Egg 内置多进程(Cluster)能力,采用 Master / Agent / Worker 的进程模型,详见 docs/source/zh-cn/advanced/cluster-client.md。其关键设计:
- Master 进程:负责进程管理与 IPC 中转;
- Agent 进程:单例常驻,适合维护与远程服务端的长连接(如数据库连接池、消息订阅客户端),避免 n 个 Worker 建立 n 倍连接;
- Worker 进程:多实例承载请求。
在此基础上,Egg 引入基于 Leader/Follower 模式的cluster-client:Leader 只能在 Agent 中创建并持有真实连接,Follower 通过 socket 直连 Leader(不再经 Master 中转),将长连接复用与数据分发问题封装为统一、易用的客户端接口(subscribe / publish / invoke)。仓库中 lib/egg.js 的this.cluster(clientClass, options)方法即对外暴露了这一能力,并支持isLeader、responseTimeout、maxWaitTime等配置。
基于 Koa,性能优异
Egg 基于 Koa 开发,天然继承了 Koa 精简的中间件洋葱模型与高性能特性。从代码继承链可以看到:EggApplication(lib/egg.js)→EggCore(egg-core)→ Koa 的Application。Egg 在 Koa 之上主要增强的是约定加载(Loader)、配置体系(app.config)、日志体系(app.logger/app.coreLogger)与多进程模型,而请求处理的底层路径仍保持 Koa 的高效实现。
稳定内核与高测试覆盖率
Egg 的核心理念之一是"框架必须稳定",这依赖完善的单元测试保障。仓库中的 test 目录覆盖了application、agent、loader、logger、router、httpclient、messenger、插件体系(i18n、security、session、schedule、static、watcher等)以及test/fixtures/apps下数十个真实场景 fixture,可用npm test(等价于npm run lint -- --fix && egg-bin pkgfiles && npm run test-local)或npm run cov运行覆盖率测试来验证。文档亦强调:无论应用、插件还是框架,单元测试都是必须项,并尽量追求 100% 覆盖率。
渐进式开发
Egg 提供 渐进式开发 的演进路径,让代码可以随业务成熟度逐步沉淀为可复用资产:
- 阶段一:写在应用里——先直接在
app/extend/context.js中实现通用逻辑(如 UA 解析ctx.isIOS); - 阶段二:以插件形态留在应用内——将代码按插件目录结构放入
lib/plugin/egg-ua,通过config/plugin.js的path方式挂载,方便在项目内复用但暂不抽离; - 阶段三:抽成独立插件——逻辑稳定后发布为
egg-uanpm 包,应用侧改用package: 'egg-ua'引入(发布前可用npm link本地联调); - 阶段四:沉淀为上层框架——当团队项目大量复用同一组插件与配置时,将其聚合抽象为
example-framework,应用只需在package.json中声明egg.framework字段指向该框架即可。
{ "name": "progressive", "version": "1.0.0", "egg": { "framework": "example-framework" }, "dependencies": { "example-framework": "*" } }这条路径充分体现了 Egg 在"代码共建、复用与模块化"上的收益:其他项目只需npm install即可复用整套沉淀下来的能力。
仓库中的落地印证
为便于读者深入源码理解,以下梳理与本文主题对应的关键文件:
- 框架定义与继承:lib/egg.js 定义
EggApplication(继承egg-core的EggCore),并挂载messenger、httpclient、loggers、cluster等核心对象; - 应用与 Agent 进程:lib/application.js、lib/agent.js 分别对应 Worker 与 Agent 的运行时;
- Loader 体系:lib/loader/index.js 导出
AppWorkerLoader与AgentWorkerLoader,加载约定见 docs/source/zh-cn/advanced/loader.md; - 内置插件清单:config/plugin.js 声明 12 个默认启用的框架级插件;
- 默认配置:config/config.default.js 给出
bodyParser、logger、httpclient、cluster等核心配置项及其默认值,是理解框架行为的第一手资料; - 快速上手:docs/source/en/intro/quickstart.md 提供了从零启动一个 Egg 应用的完整流程。
小结
Egg 的差异化价值可以概括为三点:内核精简不选型(只提供 Web 核心 + 插件机制)、约定统一促协作(Loader 驱动的目录与配置约定降低团队沟通成本)、分层可扩展(应用 → 插件 → 框架三层模型,框架可无限继承)。对于需要同时服务多个业务团队、追求长期可维护性的企业级场景,Egg 提供了一条"从应用起步、渐进式沉淀为团队框架"的清晰路径。
【免费下载链接】egg🥚 Born to build better enterprise frameworks and apps with Node.js & Koa项目地址: https://gitcode.com/gh_mirrors/egg11/egg
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考