Cordis 的生命观:Context、Effect、Disposer 与 Fiber
学完你会:理解 Cordis 如何追踪组件对环境造成的影响,并能判断 disposer 适用和不适用的边界。
资源在 Context 中被创建并登记清理方式。
Cordis 的独特价值不在于多一个 deactivate 钩子,而在于把资源创建、依赖变化、组件状态与逆向清理组织成同一套运行时关系。
Context 不是一个全局大对象
它更像一片经过裁剪的运行环境:组件能看见什么、依赖什么、留下什么,都在其中发生。
在 React 里,Context 常被理解成避免层层传参的环境;useEffect 让组件与外部系统同步,并返回 cleanup。这个类比可以帮助入门,但 Cordis 的 Context 更像一个运行时容器:它同时管理服务、事件、插件层级、过滤作用域和生命周期。
全局变量的问题不是“看起来不优雅”,而是依赖关系不可观察。任何代码都可能读写它,系统无法知道一个服务消失后哪些组件应该暂停。Cordis Context 可以派生与过滤,让组件只看到符合条件的环境,并在环境改变时重新计算依赖。
从产品视角看,Context 代表“能力在什么范围内有效”。未来 Lumi 的扩展作用域可能是 instance、workspace、Engagement 或 TaskRun;作用域越精确,权限、清理和故障爆炸半径越容易解释。
Effect 与 disposer 的局部性
把创建和撤销写在一起,审查者就不必去另一个生命周期钩子猜清理是否完整。
一个 effect 可以注册事件监听、定时器、文件 watcher 或临时服务,并返回一个 disposer。插件卸载或作用域结束时,运行时触发这些 disposer。最重要的设计原则是 locality:产生资源的地方同时声明如何撤销它。
Cordis 会逆序启动 disposer,这符合“后创建的依赖先离开”的直觉。但异步 disposer 之间可能并发;如果两个步骤必须严格排序,插件作者仍要把它们放进同一个 disposer 并显式 await。框架追踪责任,不会替作者证明每个 inverse 都正确。
对 LumiClaw 的直接启发不是把 Cordis 搬进 Core,而是建立 LifecycleScope、ResourceLease 和 DispositionReceipt:无论底层 Runtime 是 Harness、CLI 还是其他 Provider,平台都能知道资源是谁创建、属于哪个 Run、关闭是否完成。
Fiber 是插件的生命记录,不是线程
它让运行时知道一个插件当前为什么 active、pending、failed 或 disposed。
Fiber 可以被理解为一次插件实例的运行记录。它绑定父子关系、依赖状态和 effect 列表。服务到齐时,插件可以从 pending 进入 active;依赖消失时重新停用;加载失败时记录错误,而不是让整个系统只能选择“启动成功”或“进程崩溃”。
这类显式状态对 Extension Control Center 很有价值:用户不只看到“安装了什么”,还看到“为什么没有生效”“缺哪项依赖”“最近一次健康验证是什么时候”。但是 Fiber phase 仍只是 Harness 内部状态;Lumi 不应把它直接投影成业务可用或成果成功。
HMR 则是生命周期机制上的应用:旧实现先释放 effect,新实现重新申请。它可以加快开发和受控更新,却不保证外部 API、数据库写入或用户正在执行的任务天然无缝。
可逆的资源,不可逆的世界
生命周期清理解决“宿主里留下什么”,却不能自动撤销外部世界已经发生的事实。
关闭 watcher、移除 listener、释放内存缓存、停止子进程,适合用 disposer。发送邮件、支付、发布内容、修改客户系统、写入已经被其他服务读取的数据,则不能假装存在一个完美 inverse。很多动作只能补偿,甚至只能由人处理。
企业平台因此需要在生命周期之外增加 side-effect class、withholding、幂等键、事务边界、Saga compensation 和 outcome_unknown。运行中断后,如果系统无法证明远端动作是否完成,最安全的状态不是 failed,而是“结果未知,等待核验”。
这也是对 Cordis 最重要的正确学习方式:吸收“资源责任与清理局部性”,拒绝把它夸张成“系统可以任意自我修改且一切都能回滚”。
你真正要带走的,不只是技术解释
切换身份,看看这项技术会怎样改变战略、产品、工程和长期运营。
Cordis 值得吸收的是生命周期纪律,而不是把公司产品押在某个框架 API 上。
四张可以带走的卡片
Context 是有作用域的运行环境
effect 与 disposer 应保持局部
Fiber 记录组件生命状态
外部业务动作不因 dispose 自动回滚
哪一种动作最适合直接交给 disposer?
把理解变成自己的语言
试着写下:这项机制能解决什么、不能解决什么,以及它会怎样影响你的产品判断。内容只保存在当前浏览器。
原文与源码放在最后,不打断学习
正文已经完成中文梳理。只有当你想核验作者原话、查看完整公式或进入代码时,才需要离开本站。