Skip to content
源码版本47f9438 (dsh@0.1)

生命周期与中间件

每个 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-194class Fiber 字段:uid/ctx/config/state/dispose/store/inject/runtime,其中 _disposablesDisposableList

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-560effect(execute, label) 支持五种 Effect 形态:
  1. sync — 同步函数
  2. async — async 函数
  3. promise — Promise
  4. Iterable — 可迭代(每次 next() 一个 disposer)
  5. 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():
  1. 等一帧让旧 epoch 失效
  2. _resolveConfig(走 internal/config waterfall)
  3. _execute(runner)
  4. _error

_unload

vendor/cordis/src/fiber.ts:675-696_unload():
ts
Promise.all(this._disposables.clear().map(...))

并发执行 disposer(逆序在 DisposableList 内),容错吞错并 log。

Disposer 顺序:single-effect 内部逆序,多个 async disposer 并发。若需要严格串行,要塞进单个 disposer 内 await。

update(HMR 挂载点)

vendor/cordis/src/fiber.ts:736-753update(config, noSave):
ts
update(config, noSave) {
  ctx.waterfall(this, 'internal/update', config, noSave, () => restart())
}

internal/update waterfall 是 HMR 与 Loader 持久化的挂载点:loader 在此写回 entry.options.config = configtree.write(),HMR 在此决定是否重启。

事件系统:五种 dispatch

vendor/cordis/src/events.ts:329-352interface 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-175dispatch(type, args):剥 thisArg/name,触发 internal/dispatch,按 Context.filter 过滤 listener。

waterfall:中间件模型

vendor/cordis/src/events.ts:234-243waterfall(...args):
ts
waterfall(...args) {
  const next = args.pop()
  // 外层 listener 先跑,next() 链式委托
  // 不调 next 即 veto
}

这是典型的中间件洋葱模型——外层先跑,通过 next() 委托给内层,不调 next() 即否决。

框架自身事件优先级

EventsService 构造时自动注册 internal/listener bail 监听器,把 internal/update 的 listener 改走 fiber._hooks 单独存储——这是"框架自身事件优先级"的实现,避免插件 listener 干扰框架内部状态变更。

接下来读什么