0008. 跨端演进在现有 Monorepo 内增量进行
- Status: Proposed
- Date: 2026-10-09
- Deciders: 363045841(owner), tseka
- Source: 《KCQ 前端架构方案 v1.1》(2026-10-08),本 ADR 覆盖其 ADR-001/002/005/008/009/010/012
Context
v1.1 的目标是 Desktop(Electron)+ Mobile(Expo/React Native)+ 共享 KCQ Core。对照 main(11ff88e7)核实后的现状:
| 事实 | 证据 |
|---|---|
已是 pnpm workspace,纳入 packages/*、examples/* | pnpm-workspace.yaml |
| Core 约 7.8 万行 TS,已有 WebGPU / WebGL2 / Canvas2D 三后端和能力分级探测 | packages/core/src/rendering/render/backend/*、foundation/utils/rendererCapability.ts |
| 「StateKernel」是 signal 体系的约定(只读 signal + action 写入),不是单独的类 | packages/core/src/foundation/reactivity/signal.ts |
Agent 通过 Core 上 @Tool 注册的原语操作图表 | packages/core/src/features/agent/* |
Desktop 渲染进程只有 61 行 App.vue,通过相对路径 ../../vue/src/index 直接引用 Vue 包源码 | packages/desktop-electron/src/App.vue |
产品 UI 全部在 packages/vue:61 个 SFC、约 2.8 万行,KLineChart.vue 约 79 KB,Agent 工作台 8,599 行 | packages/vue/src |
指针、滚轮、捏合、画线的 DOM 输入接线在 KLineChart.vue,Core 只暴露 handlePointerEvent 等处理函数 | KLineChart.vue 约 1380–1460 行 |
线上 Web 产品(kcq.nebutra.com)由 nebutra-sailor apps/kcq 承载,使用同一套 Vue 图表 UI | sailor apps/kcq/README.md |
v1.1 没有覆盖 Web 这一宿主。Web、Desktop、Mobile 是三个宿主,不是两个。
Decision
- 接受 v1.1 ADR-001/002:继续使用
packages/*workspace,不迁移到apps/。新增应用(如packages/mobile)也放在packages/下。 - 接受 v1.1 ADR-005/009:保留 TypeScript Core,不重写渲染引擎,不引入 Rust。渲染层冻结范围沿用既有约定。
- 接受 v1.1 ADR-008:暂不从 Core 拆出 indicators / drawings / state 等包。
- 接受 v1.1 ADR-010:Agent 与用户共享 Core 原语;移动端 Agent 运行在 WebView 内(
agent-runtime已有browser.ts入口),原生侧只负责凭据存储,与 Electron 的credential-ipc对称。 - 接受 v1.1 ADR-012,并补充一条可执行规则:宿主应用只能通过包的
exports导入,不得相对路径引用其他包的src。Desktop 现有的../../vue/src引用列为待清偿债务。 - 新增:跨宿主共享的关键路径是「框架无关的输入绑定」。把
KLineChart.vue中的 DOM 输入接线抽成 Core 内的独立模块(新目录,不触碰渲染与控制器内部),Vue 先接入并以现有测试证明等价,然后 React、Angular、Mobile WebView 复用。没有这一步,任何非 Vue 宿主只能拿到「能渲染、不能交互」的图表。
修订后的推进顺序
| 阶段 | 工作 | 验收 |
|---|---|---|
| P0 | 固定基线 | library-ci 全绿(已有) |
| P1 | React 直连 Core 适配器(ADR 0009,本 PR) | 挂载、释放、增量同步、SSR 测试通过 |
| P1b | 抽取框架无关输入绑定,Vue 先接入 | Vue 交互测试零回归;React/Angular 获得交互 |
| P2 | Web + Desktop 保持 Vue(ADR 0011 方案 C);Desktop 改用包 exports,清理相对源码导入 | Desktop 不再引用 ../../vue/src |
| P3 | 移动端 spike:Expo DOM component + React 适配器 + 输入绑定(ADR 0010) | 中端 Android 平移/缩放 60 FPS,记录冷启动、内存、桥往返延迟 |
| P4 | packages/mobile 应用骨架(Expo Router);仅在 spike 证明需要时新增 packages/chart-mobile | iOS / Android 真机运行 |
| P5 | 触控交互:长按十字线、双指缩放、画线、横屏 | 交互用例通过 |
| P6 | 跨宿主一致性:同一份配置与持久化快照在各宿主渲染结果一致 | golden 测试 |
| P7 | 性能与发布 | FPS、内存、启动时间、桥延迟达标 |
P1b 实施时确认:平移、十字线、坐标轴拖拽、双指缩放(PinchTracker)和滚动监听都已在 Core 内部,宿主缺的只是 DOM 接线。抽取结果为 @363045841yyt/klinechart-core/input 的 bindChartInput,Vue 组件与 React 适配器已改用它。
v1.1 原 P1「重构 React」与 P2「Desktop React 迁移」之间缺了 P1b。P2 的工作量取决于 ADR 0011,而不是 Desktop 壳本身(壳只有约 450 行)。
Consequences
- 不产生仓库级重构;已发布的包名与入口不变。
- P1b 是 Desktop、Web、Mobile 三条线共同的前置条件,应优先于任何 UI 迁移排期。
- 每个新增目录在创建前按 v1.1 ADR-012 复核本地文件树与导入关系。
Core 导出与源码别名
项目是 pnpm workspace monorepo。@363045841yyt/klinechart-core 是发布包,生产消费者通过 packages/core/package.json 的 exports 使用其公开入口;Vue preview、React preview、Electron renderer…
0009. React 适配器直接挂载 Core
@363045841yyt/klinechart-react 目前只导出 KLineChartWC,它渲染由 Vue 打包的 <kline-chart> 自定义元素。v0.10.4 曾主动移除直连 Core 的工厂、hooks 和 KLineChart 组件,…