生命周期与中间件
每个 ctx.plugin() 返回一个 Fiber,它是个有限状态机。所有注册(ctx.on/ctx.effect/ctx.provide)都是 effect,被记入 fiber 的 _disposables 列表,卸载时逆序执行。事件系统的 emit/parallel/serial/bail/waterfall 五种 dispatch 覆盖"通知/聚合/串行/短路/中间件"全部通信模式。
Fiber 状态机
vendor/cordis/src/fiber.ts:147-154 定义了 const enum FiberState:PENDING → LOADING → ACTIVE → UNLOADING → DISPOSED
↓ (失败)
FAILED六态:PENDING/LOADING/ACTIVE/FAILED/DISPOSED/UNLOADING,每态有明确语义。
Fiber 字段
vendor/cordis/src/fiber.ts:184-194 的 class Fiber 字段:uid/ctx/config/state/dispose/store/inject/runtime,其中 _disposables 是 DisposableList。Fiber 构造器
vendor/cordis/src/fiber.ts:222-263:- 创建子 ctx
- 注入 intercept config
- 设置
_runner.execute(class 用new,function 直接调) - 把 fiber.dispose 注册成 parent 的 effect
Effect:可逆注册
vendor/cordis/src/fiber.ts:415-560 的 effect(execute, label) 支持五种 Effect 形态:- sync — 同步函数
- async — async 函数
- promise — Promise
- Iterable — 可迭代(每次
next()一个 disposer) - AsyncIterable — 异步可迭代
Disposer 单次触发;effectInertia WeakMap 让外部 join 已运行的 cleanup。
关键:Effect 是"可逆注册"的同义词。
ctx.on内部调register,后者this.ctx.fiber.effect(...)把 listener 入队并返回 disposer——这就是为什么"卸载即清理"是自动的。
Reload 与 Unload
_reload
vendor/cordis/src/fiber.ts:646-673 的 _reload():- 等一帧让旧 epoch 失效
_resolveConfig(走internal/configwaterfall)_execute(runner)- 清
_error
_unload
vendor/cordis/src/fiber.ts:675-696 的 _unload():Promise.all(this._disposables.clear().map(...))并发执行 disposer(逆序在 DisposableList 内),容错吞错并 log。
Disposer 顺序:single-effect 内部逆序,多个 async disposer 并发。若需要严格串行,要塞进单个 disposer 内 await。
update(HMR 挂载点)
vendor/cordis/src/fiber.ts:736-753 的 update(config, noSave):update(config, noSave) {
ctx.waterfall(this, 'internal/update', config, noSave, () => restart())
}internal/update waterfall 是 HMR 与 Loader 持久化的挂载点:loader 在此写回 entry.options.config = config 并 tree.write(),HMR 在此决定是否重启。
事件系统:五种 dispatch
vendor/cordis/src/events.ts:329-352 的 interface Events 内置八个框架事件:internal/plugin | internal/status | internal/config | internal/update
internal/get | internal/set | internal/listener | internal/dispatch文档模式标注 @mode。
dispatch 与 filter
vendor/cordis/src/events.ts:165-175 的 dispatch(type, args):剥 thisArg/name,触发 internal/dispatch,按 Context.filter 过滤 listener。waterfall:中间件模型
vendor/cordis/src/events.ts:234-243 的 waterfall(...args):waterfall(...args) {
const next = args.pop()
// 外层 listener 先跑,next() 链式委托
// 不调 next 即 veto
}这是典型的中间件洋葱模型——外层先跑,通过 next() 委托给内层,不调 next() 即否决。
框架自身事件优先级
EventsService 构造时自动注册 internal/listener bail 监听器,把 internal/update 的 listener 改走 fiber._hooks 单独存储——这是"框架自身事件优先级"的实现,避免插件 listener 干扰框架内部状态变更。