5.2 KiB
5.2 KiB
4-25 [process][bug] 树命令新建/删除后强制刷新导致卡顿 v1
更新时间:2026-05-13
分类归属:
04-tree-domain/process- 关联缺陷:
bugs/05-editor-mainline/process/5-11-mindmap-ghost-assets-and-tree-command-latency-v1.md用户反馈:
- “删除页面和新建页面都很慢,不知道为什么这么卡。”
1. 问题定义
当前页面树/文件树的新建页面、删除页面等命令,在服务端命令成功后仍会触发整页刷新或完整树刷新。用户感知是:新建和删除并不是局部更新,而是卡一下、等整套页面壳或树壳重新加载。
这属于 tree command -> projection update -> UI apply 链路问题,应归到 04-tree-domain,而不是只作为编辑器 UI 问题处理。
2. 真实现象
用户反馈:
- 新建页面慢。
- 删除页面慢。
- 卡顿与同轮 mindmap 文件树重复增长一起出现,怀疑树刷新链路被频繁触发。
期望结果:
tree.node.create成功后,树 UI 局部插入新节点并进入重命名/导航状态。tree.node.archive成功后,树 UI 局部移除节点或移动到回收站 projection。- 只有 delta 无法应用、projection 缺失、SSE 断线或数据不一致时,才进入 resync/reload fallback。
- 普通新建/删除不应默认整页 reload。
3. 证据
3.1 Rust tree shell 有硬刷新路径
rust/crates/mnote-web/src/routes/tree.rs:2976 到 :2986:
scheduleRefresh()在 80ms 后执行window.location.reload()。- 如果带
renameRowId,则通过window.location.assign(url.toString())重新加载。
调用点:
- 文件树删除:
rust/crates/mnote-web/src/routes/tree.rs:2791到:2824 - 新建页面:
rust/crates/mnote-web/src/routes/tree.rs:4309到:4340 - 重命名:
rust/crates/mnote-web/src/routes/tree.rs:4373到:4406 - 移动:
rust/crates/mnote-web/src/routes/tree.rs:4448到:4502
这条路径会让 tree shell 命令体验明显慢于纯 delta / reducer 更新。
3.2 主页面已有 tree live controller,但命令后仍刷新
主页面已经监听 tree live:
rust/crates/mnote-web/src/ssr/pages/layout.rs:3881到:3917处理tree:snapshot/tree:delta/tree:resyncrust/crates/mnote-web/src/ssr/pages/layout.rs:3939到:4050启动/api/tree/eventsEventSource
也就是说,命令完成后理论上可以由 delta/resync 更新 projection;当前硬 reload 与 live projection 机制重复。
3.3 命令本身已有 delta hint
Bridge runtime 对树命令生成 stream delta hint:
tree.node.create:rust/crates/bridge-runtime/src/lib.rs:9545到:9592tree.node.archive:rust/crates/bridge-runtime/src/lib.rs:9655到:9702
当前前端没有把这些结果作为默认局部更新来源,而是在 tree shell 中继续 reload。
3.4 React Sidebar 路径也存在重刷链
子代理只读调查发现 React Sidebar 路径也存在重刷:
- 新建页面:
wolai-frontend/src/components/sidebar/sidebar.tsx:1799、:1847附近在 command 后await refreshTree()再跳转。 - 删除页面:
wolai-frontend/src/components/sidebar/sidebar.tsx:2148附近删除后等待 command、refreshTree()、广播文档变化/跳转。 - Next API 的
api/tree/commandscreate/delete 还会执行 workspace/default scaffold、bridge mutation、artifact 记录等多段流程。
这说明卡顿不只来自单个 reload,而是命令后刷新链路偏重。
4. 当前判断
当前慢的核心不是“Convex 一定慢”,而是树命令执行后缺少轻量本地 apply:
- 命令 result / delta hint 已经具备局部更新信息。
- UI 仍经常走
refreshTree()、window.location.reload()或 full snapshot。 resync_required类事件会触发完整 workspace snapshot,结构性变化越多,越容易造成卡顿。
5. 建议验证
修复前先补一条计时 smoke:
- 登录真实测试账号。
- 新建
TEST-TREE-LATENCY-<timestamp>页面。 - 记录
POST /api/tree/commands响应耗时。 - 记录下一次
tree:delta/tree:resync到达耗时。 - 断言过程中是否发生
window.location.reload()或顶层 navigation。 - 删除该测试页面,重复同样计时。
- 输出新建/删除从点击到 DOM 稳定的总耗时。
6. 建议修复方向
tree.node.create成功后直接用 command result 插入本地节点,并只在后台等待 live delta 校准。tree.node.archive成功后直接从当前 projection 移除节点,并只在后台等待 live delta 校准。scheduleRefresh()改成显式 fallback,只有 reducer 无法应用时才调用。- React Sidebar 的
refreshTree()应去重、节流,并避免与 SSE/full snapshot 同时触发。 - smoke 增加无 reload 断言和耗时阈值。
7. 流转条件
当前状态:process
只有满足以下条件后才能移动到 bugs/04-tree-domain/done/:
- 新建页面普通路径不再默认整页 reload。
- 删除页面普通路径不再默认整页 reload。
- command result / tree delta 能局部更新页面树与文件树 projection。
- fallback reload 只在明确异常条件下触发,并有可观测标记。
- smoke 记录新建/删除耗时,并通过无 reload 断言。