> ## Documentation Index
> Fetch the complete documentation index at: https://tegg.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# 为什么这样设计 Tegg

下面是我对 tegg 为什么设计成现在这种架构的系统性分析，结合 tegg 仓库的结构来回答“动机-分层-机制-取舍”四个维度，帮助你从“为什么这样设计”的角度理解它。

## 为什么这样设计

### 一、目标与约束（Why）

* 核心目标
  * 面向复杂业务的“可组合能力”：将控制器、AOP、DAL、事件总线、调度等能力模块化、按需装配，避免“一个包做所有事”的内聚膨胀。
  * 与 Egg.js 生态的“解耦集成”：核心能力要独立于 Web/框架，但又能通过插件自然接入 Egg 的生命周期、配置和中间件体系。
  * 强类型与装饰器的开发体验：以 TypeScript + 装饰器为入口，提升领域建模的表达力，把设计“显式化”“可扫描化”。
  * 生命周期与上下文的正确性：异步调用链下的上下文传递与隔离，用于解决“异步堆栈里传参散落”的顽疾。
  * 单测与演化友好：以 monorepo 管理多包，使能力可以独立演进、单独发布与回滚，降低全局耦合风险。
* 外部约束
  * Node.js 平台语义（模块系统、异步模型）与 Egg 插件机制。
  * 工程化约束（多包发布、类型共享、构建一致性）。
  * 对既有项目渐进迁移的现实需求（CJS 到 ESM、全局上下文到 ALS）。

### 二、分层与包的职责（How it’s structured）

* 核心（Core）层：抽象出“运行时/元数据/装载器”三件套
  * 元数据：装饰器标注 → 可被扫描/序列化的元数据
  * 装载器：扫描工程、解析元数据、构建原型/装配单元（LoadUnit/Prototype）
  * 运行时容器：依赖注入、实例生命周期、上下文、作用域等
  * 类型与跨包契约：抽离公共类型，降低编译耦合
  * 能力入口/外观（Facade）：聚合核心能力（为上层提供简化入口）
* 能力（Decorator/Runtime）层：将横切/领域能力按“装饰器 + 运行时”解耦
  * 例如 AOP、DAL、ORM、事件总线、调度等均以“装饰器声明 + 对应运行时”组合出现
* 集成（Plugin）层：把核心能力与 Egg 的应用框架做“边界清晰”的桥接
  * HTTP/Controller 插件：把控制器声明/路由/参数校验等与核心容器打通
  * 与 Egg 的集成外壳（入口/初始化/配置），将 tegg 功能以插件方式启用
  * 其它插件（orm/schedule/ajv 等）将具体能力接入 Egg
* 运行形态（Standalone）层：除了在 Egg 中运行，也支持独立运行模式

这套分层遵循“能力内聚、耦合外移”的原则：核心保持与框架无关，插件负责落地集成，增强了运行时形态的可移植性与渐进引入能力。

### 三、关键机制与设计取舍（How it works）

* Decorator → Metadata → Loader → Runtime 的流水线
  * 为什么要“先装饰器再元数据”：装饰器让“意图”显式化、可静态扫描；元数据是稳定的中间层，屏蔽语言/框架差异。
  * 为什么要“装载器”：将分散在项目各处的声明统一装配为“原型/LoadUnit”，把“扫描/解析/组装”的复杂度从业务代码挪走。
  * 为什么要“容器/运行时”：解决依赖注入、生命周期、作用域、实例化策略、上下文传播等通用问题。
* 上下文管理采用 AsyncLocalStorage（演进点）
  * 解决异步调用链中的上下文丢失问题，替代手写传参或全局变量，提升一致性与可靠性。
  * 与 Egg 的请求生命周期天然契合，插件层可以围绕请求/任务创建异步上下文作用域。
* ESM only 与类型抽离（工程化演进）
  * ESM only：与现代 Node/工具链对齐，简化双模块形态带来的复杂性与坑点。
  * 类型抽离到 types：将跨包契约集中管理，降低“隐式类型耦合”，便于重构与发布。
* 与 Egg 的解耦集成
  * 为什么把“HTTP 控制器能力”做成插件而不是放在核心：保持核心对框架无感，支持多运行形态；同时让“控制器如何映射到 Egg 的路由/中间件”由插件层决定，避免强耦合。
* Monorepo 的组织理由
  * 每个能力独立发版、独立回滚；变更影响范围可控；同时共享构建/规范工具链，降低总体维护成本。

### 四、相对其它方案的取舍（Why not X）

* 不做“单一大包（one big package）”
  * 优点：降低初期心智负担；缺点：后期耦合过高，发布与回滚风险极大，难以扩展新能力或裁剪。
  * tegg 选择“多包/可插拔”，以长期演进/大型团队协同为优先。
* 不把 HTTP/框架语义塞进核心
  * 核心一旦耦合框架语义，将限制运行形态与扩展；插件可以自由演化适配不同的框架/协议（HTTP、RPC、消息）。
* 不继续使用全局变量/手写传参做上下文
  * 在 Node 异步场景下不可靠、不可维护；AsyncLocalStorage 是更符合异步模型的“正交能力”。
* 不维持双模块（CJS+ESM）长期并存
  * 工程复杂度高、边界 case 多；ESM only 让生态与工具链更清晰一致。

### 五、这个架构带来的收益与成本

* 收益
  * 解耦：核心可独立复用，插件可平行演进。
  * 可测试：每个能力包可单测/集成测隔离执行。
  * 可演化：装饰器/元数据/容器作为“稳定三件套”，外部能力以“模块化”扩展。
  * 类型安全：跨包契约集中在 types，重构风险更可控。
* 成本
  * 学习曲线：理解装饰器→元数据→装载器→运行时流水线需要一定门槛。
  * 工程复杂度：多包构建/发布/版本管理需要规范与工具链保障。
  * 性能权衡：启动期的扫描/装载有开销，需要通过缓存/按需加载来权衡。

## 架构总览

装饰器→元数据→装载器→运行时→插件

下图展示 tegg 的关键流转与边界：装饰器将“意图”转化为元数据；装载器扫描并构建 LoadUnit/Prototype；运行时负责 DI/生命周期/上下文（基于 AsyncLocalStorage）；插件层与 Egg 集成。

<p align="center">
  <img src="https://mintcdn.com/tegg/NJD9IpokOUU5-uQ5/img/tegg-architecture-sequence.svg?fit=max&auto=format&n=NJD9IpokOUU5-uQ5&q=85&s=a7c2fe442f499a03351d040007f21fc6" alt="Tegg 架构时序/组件图" width="960" data-path="img/tegg-architecture-sequence.svg" />
</p>

关键数据结构（示例清单）：

* Metadata：ClassMetadata、PropertyMetadata、ParamMetadata
* Loader：LoadUnit、EggPrototype/EggObject、Qualifier/Scope
* Runtime：Context（ALS）、Container、LifecycleHook
* Plugin：HTTPController、路由注册/参数解析

## 数据结构索引

以下索引帮助你从“架构图/生命周期图”跳到具体源码

* Controller 元数据：plugin/controller/lib/ControllerMetadata.ts

* 方法元数据接口：core/types/MethodMeta.ts

* 原型接口：core/types/EggPrototype.ts

* 加载单元：core/types/LoadUnit.ts

* 对象包装：core/types/EggObject.ts

* 请求上下文：core/types/EggContext.ts

* 生命周期钩子：core/types/LifecycleHook.ts

* 控制器注册工厂：plugin/controller/lib/ControllerRegisterFactory.ts

* HTTP 方法注册器：plugin/controller/lib/HTTPMethodRegister.ts

* 容器对象工厂：core/lib/EggContainerFactory.ts（或所在实现位置）
