Files
mnote/design/old/03-rust-web/process/rust-web-long-term-checklist-v1.md
T

28 KiB
Raw Blame History

3-0 [recycle] Rust Web 长期架构实施清单 v1

更新时间:2026-04-16

关联文档:

  • /mnt/Data1T/mnote/design/03-rust-web/process/3-rust-web-long-term-architecture-v1.md
  • /mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/process/document-access-performance-root-cure-v1.md
  • /mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/done/rust-kernel-cutover-v1.md
  • /mnt/Data1T/mnote/ARCHITECTURE.md

1. 文档用途

这份清单不是短期提速清单,而是长期架构落地清单。

它服务的目标只有一个:

把 mnote 从“Rust 内核 + 重前端页面壳”推进到“Rust 内核 + Rust Web 承载 + server-first 页面 + 少量交互孤岛”的稳定形态。

这份清单强调四件事:

  • 做什么
  • 不做什么
  • 什么时候算完成
  • 哪些东西必须最后处理

2. 总体完成定义

只有同时满足下面几条,才能认为长期架构目标基本达成:

  • Rust workspace 成为唯一业务真执行面,Web 层不再承载第二套对象规则
  • Rust Web 层已经接住主 API、主页面壳、主流式能力
  • 文档访问路径已变成“先阅读、后交互、再编辑”
  • Sidebar、搜索、AI、Mindmap 等外围模块已退出当前重前端主壳
  • BlockNote 已被隔离为最后的重交互孤岛,而不是整页入口前提
  • Next/旧 React 壳只保留过渡兼容边界或已被替换

3. 执行原则清单

在任何阶段开始前,先确认这些原则不被破坏:

  • 不再把新的业务规则写回 TS route / Next 页面层
  • 不再新增新的全局常驻前端大面板
  • 不再把“临时懒加载”当作长期方案替代品
  • 不在未完成阅读态分离前,继续扩张编辑态默认挂载内容
  • 不把 BlockNote 当成第一阶段改造对象
  • 不把 OnlyOffice 当成主性能阻塞项
  • 不把“换成 Rust”简化成“只重写 API”

4. 阶段总览

推荐按下面顺序推进:

  • Phase 0:基线与边界冻结
  • Phase 1Rust Web 基础层落地
  • Phase 2:文档阅读页 server-first 化
  • Phase 3Sidebar / 页面树 / 文件树 Rust 化与 island 化
  • Phase 4:搜索系统 Rust 化与 island 化
  • Phase 5:AI 面板进一步收口为纯桥接 island
  • Phase 6Mindmap 独立对象化与独立页面化
  • Phase 7:文档编辑态与 BlockNote 孤岛化
  • Phase 8:旧前端壳下线与兼容清理

4.1 阶段依赖与并行规则

这条长期路线不是“看到哪里慢就改哪里”,而是有明确前后依赖。

  • Phase 0 必须先产出边界冻结、基线和 islands 候选,否则后续会重新滑回旧壳扩张。
  • 横向能力 H1 必须在 Phase 1 之前定口径,否则 Rust Web、阅读态、搜索、AI、Mindmap 会各自发明 trace、缓存和权限语义。
  • Phase 1Phase 2 ~ Phase 6 的共同前置;没有 Rust Web 承载层,后续只能继续堆 Next route。
  • Phase 2 ~ Phase 6 可以分批并行推进,但都必须遵守“阅读优先、局部 island、对象规则只进 Rust core”。
  • Phase 7 依赖 Phase 2 ~ Phase 6 基本就位后再开始,否则 BlockNote 会继续承担外围能力。
  • Phase 8 只能在 Phase 1 ~ Phase 7 都有稳定替代路径后执行,不能靠“删旧代码”制造假完成。

4.2 每阶段输出给下一阶段的输入

  • Phase 0 输出:重模块审计表、性能基线、阅读态/编辑态边界、islands 候选、冻结口径。
  • Phase 1 输出:Rust Web 入口、统一 router/middleware/context/error/SSE/WS/Hermes bridge 协议。
  • Phase 2 输出:文档阅读态服务端主链、阅读工具栏 island、阅读缓存/预取策略。
  • Phase 3 输出:Sidebar/树结构服务端骨架、局部刷新协议、导航预取策略。
  • Phase 4 输出:搜索 server-first 页面壳、轻交互 Search island、分页/键盘导航协议。
  • Phase 5 输出:AI bridge panel 最小会话协议、流式 token/tool/client action 统一事件流。
  • Phase 6 输出:Mindmap 独立对象页壳、内嵌轻预览边界、独立操作协议。
  • Phase 7 输出:阅读态/编辑态切换协议、编辑岛错误边界、编辑态性能采样。
  • Phase 8 输出:Next/旧 React 壳保留清单、兼容层清理清单、最终对外口径。

5. Phase 0:基线与边界冻结

5.1 目标

在动长期架构之前,先冻结边界,避免迁移过程中又把旧模式继续扩写。

5.2 实施清单

  • 盘点当前由 Next/React 页面层承载的重模块清单
  • 标记哪些模块属于“必须保留浏览器交互”
  • 标记哪些模块属于“可变为 server-first 页面”
  • 标记哪些模块属于“可退化为独立 island”
  • 标记哪些模块属于“外挂或独立页面,不进入主文档链”
  • 冻结 BlockNote 外围继续加功能的入口
  • 冻结 Sidebar、SearchPalette、Document 面板继续膨胀的入口
  • 为页面切换与首屏建立统一性能基线
  • 为文档页进入路径建立链路追踪点
  • 为 Sidebar、搜索、AI、Mindmap 建立独立耗时采样点

5.2.1 当前前端重模块审计表

模块 当前主入口 当前主问题 长期归位 是否必须保留浏览器重交互
文档页 wolai-frontend/src/app/(app)/documents/[id]/page.tsx + DocumentShell -> DocumentContent -> BlockNoteEditor 进入页面默认串到编辑器初始化,阅读态无法先出现 Phase 2 先 server-first 阅读页,Phase 7 再把 BlockNote 孤岛化 是,但只限编辑态
Sidebar / 页面树 / 文件树 wolai-frontend/src/app/(app)/layout.tsx + src/components/sidebar/sidebar.tsx 常驻在主布局内,切页时继续参与大组件状态与重渲染 Phase 3 收口为 Rust query + 服务端壳 + 局部 island 是,但只限展开/拖拽/快捷过滤
SearchPalette src/components/search/search-palette.tsx 当前仍作为全局常驻大组件挂在布局内 Phase 4 收口为独立 island 与 server-first 搜索页 是,但只限输入/联想/键盘导航
AI 面板 src/components/ai-agent/**DocumentAiAgentPanelMindmapAiAgentPanelOnlyOfficeAiAgentPanel 已切 Hermes bridge,但页面壳仍偏重,多个面板仍常驻挂载 Phase 5 统一为最小 bridge shell + 按需 island 是,但只限会话与浏览器 client capability
Mindmap src/components/editor/blocks/MindmapBlock.tsx + src/app/mindmap/[docId]/[mindmapId]/page.tsx 独立页仍与 BlockNote 形态绑得太近,内嵌/独立共用同一重壳 Phase 6 收口为独立对象页 + 内嵌轻预览
OnlyOffice src/app/onlyoffice/**src/app/api/onlyoffice/** 属于外部编辑器桥,不是主文档性能瓶颈 继续维持外挂页面,不进入主文档链 是,但不进入主文档访问链
BlockNote src/components/editor/blocknote-editor.tsx 当前仍然是文档页默认入口前提 最后处理,保留为 Phase 7 的重交互孤岛

5.2.2 冻结口径

  • 新增页面能力时,先判断是否能落到 server-first 页面或局部 island,不能再默认塞回主布局。
  • 新增对象规则、权限判断、聚合排序、工具编排,不允许直接写回 Next route 或页面层。
  • BlockNote 外围的新面板、新工具栏、新初始化逻辑一律冻结,除非是为“阅读态分离”服务。
  • Sidebar、SearchPalette、AI 面板不允许再继续增加全局常驻状态容器。

5.3 产物清单

  • 当前前端重模块审计表
  • 页面切换性能基线报告
  • 文档阅读态与编辑态的边界定义
  • 岛模型候选模块清单

5.3.1 页面切换性能基线报告

访问链路 当前入口 需要记录的统一指标 当前基线采样方式 迁移后对比目标
普通文档打开 /documents/[id] 首字节、正文首屏、进入可点击阅读态、进入编辑态耗时、BlockNote 挂载耗时 scripts/task019-document-ui-regression.js + 浏览器 performance trace 把正文首屏与阅读交互从编辑器启动链里剥离
Sidebar 切页 主布局 + Sidebar 切页耗时、树结构重渲染数、导航预取命中率 pnpm test src/lib/sidebar-data.test.ts src/lib/file-tree/rows.test.ts + React Profiler Sidebar 仅做局部交互,不再放大整页挂载
搜索打开/关闭 SearchPalette 打开耗时、首次结果返回、键盘导航响应、关闭恢复耗时 搜索页/浮层交互 trace + eslint/定向 smoke 搜索开关不再引发整页重计算
AI 面板打开/关闭 Document/Mindmap/OnlyOffice AI 面板首开耗时、SSE 首 token、关闭后页面恢复耗时 runAgent.test.ts + 页面侧 performance mark AI 未打开时不占主页面主链
Mindmap 独立页 /mindmap/[docId]/[mindmapId] 页面壳首屏、导图交互可用、独立页返回文档页耗时 scripts/task021-mindmap-ui-regression.js 独立页不再依赖文档编辑上下文

5.3.2 文档阅读态与编辑态的边界定义

  • 阅读态必须先拿到页面 meta 与正文读链,允许在没有编辑器的情况下稳定展示正文。
  • 编辑态必须显式进入,不能再把“打开文档”默认等同于“挂载完整编辑器”。
  • 阅读态负责:权限、只读/禁复制/禁下载策略、正文首屏、轻工具栏、回退与预取。
  • 编辑态负责:BlockNote、块级写入、Slash、评论/历史/AI/页面选项等重交互链路。
  • 只读渲染与可编辑渲染必须是两套不同初始化协议,不能靠 mounted gating 假装分离。

5.3.3 岛模型候选模块清单

模块 候选 island 形态 保留在服务端页面壳的内容
文档阅读工具栏 轻工具栏 island 标题、正文、权限壳、阅读统计
Sidebar 树 展开/拖拽/快捷过滤 island 工作区壳、树结构首屏 HTML
SearchPalette 输入框、联想、结果列表 island 搜索页结果首屏与分页壳
AI 面板 单一 AiBridgePanel island 页面上下文注入、SSE 桥接 route
Mindmap 独立导图交互 island 独立页 meta、权限与返回壳
BlockNote 最后保留的重编辑 island 阅读页正文、阅读工具栏、权限与缓存壳

5.4 完成判定

  • 后续任何人都能明确知道哪些模块先迁、哪些模块后迁
  • 已经有统一基线可以验证迁移是否真的更快
  • 不再接受“顺手往旧壳里再塞功能”的继续扩张

6. Phase 1Rust Web 基础层落地

6.1 目标

建立真正的 Rust Web 承载层,而不是停留在“Rust 只做业务内核”。

6.2 实施清单

  • 在 Rust workspace 中明确新增 Web 层 crate 或独立服务目录
  • 选定 axum 作为主 HTTP 承载框架
  • 建立统一 Router 组织方式
  • 建立统一 middleware 链
  • 建立统一 request id / trace id 注入
  • 建立统一鉴权上下文注入方式
  • 建立统一 workspace / actor / tenant 上下文透传
  • 建立统一错误码与错误响应协议
  • 建立统一 JSON 响应包装规范
  • 建立统一 SSE 输出协议
  • 建立统一 WebSocket 连接协议
  • 建立统一静态资源与页面壳响应策略
  • 打通 Rust Web 层到现有 Rust core runtime 的调用入口
  • 打通 Rust Web 层到 Hermes 的桥接入口
  • 明确保留哪些 Next route 作为过渡兼容壳
  • 明确哪些旧 route 不允许再扩写

6.3 架构约束

  • axum 只负责 Web 承载,不复制业务裁决
  • Rust Web 层不再新建第二套对象模型
  • Web 层只组合调用 Rust core,而不是重新实现 core 语义
  • 仍需浏览器特定 transport 的旧接口必须标记为兼容层

6.4 完成判定

  • 已有一个可运行的 Rust Web 入口
  • 主 API、SSE、WS、trace 基础设施已可由 Rust Web 层承接
  • 后续页面迁移不再必须依赖 Next API route 作为唯一入口

7. Phase 2:文档阅读页 server-first 化

7.1 目标

把“进入文档页就进入编辑器世界”的模式改成“先进入阅读页,再按需进入编辑态”。

7.2 实施清单

  • 定义文档阅读页独立于编辑态的页面模型
  • 定义阅读页所需最小数据模型
  • 定义阅读页 HTML 输出协议
  • 将文档 meta 与正文读取收敛成同一服务端读链
  • 去掉进入文档页必须二次取正文的默认模式
  • 去掉进入文档页必须等待客户端 mounted gating 的默认模式
  • 去掉阅读页默认依赖 BlockNote 的前提
  • 把评论、历史、回链、页面选项、AI 等外围面板改为非阻塞挂载
  • 将文档阅读工具栏收缩为轻交互 island
  • 将阅读页权限、只读、禁复制、禁下载等策略前移到服务端页面壳
  • 为阅读页建立缓存与失效策略
  • 为阅读页建立首屏、切页、回退、预取策略

7.3 禁止事项

  • 不允许为了“看起来快一点”继续叠更多客户端 gating
  • 不允许阅读页默认挂载完整编辑器依赖树
  • 不允许把评论、AI、回链等周边作为阅读页首屏阻塞条件

7.4 完成判定

  • 打开文档时可以先看到完整阅读态,而不是编辑器 loading 壳
  • 文档访问主链已不依赖 BlockNote 初始化完成
  • 页面切换性能的主要瓶颈已从“编辑器启动”转移出去

7.5 当前落地状态(2026-04-16

  • 文档页已改成 server-first 阅读入口:服务端先拿 meta + content + revision + conflictDetectionKey,客户端只在服务端读链失败时才回退到旧 /api/documents/content 读链。
  • DocumentShell 已去掉 mounted gating,阅读页不再先显示“正在载入编辑器...”壳。
  • DocumentReadView 已承担正文只读渲染;BlockNoteEditor 仅在显式进入编辑态或 openTableId 直达场景时挂载。
  • 只读/禁复制/禁下载、评论、历史、回链、页面 AI 与页面选项都已从阅读首屏阻塞链上移开,阅读态可以先稳定出现。

8. Phase 3Sidebar / 页面树 / 文件树 Rust 化与 island 化

8.1 目标

把高频访问、长期常驻、当前体量过大的导航系统,从主前端大壳里拆出去。

8.2 实施清单

  • 定义 Sidebar 数据聚合协议
  • 定义页面树 / 文件树查询协议
  • 将排序、过滤、分组、收藏、最近访问、回收站等聚合逻辑收敛到 Rust
  • 将大部分树结构渲染改为服务端输出
  • 将展开、折叠、拖拽、快捷过滤等改为局部 island
  • 拆分“静态结构”和“高交互局部状态”
  • 减少全局布局对 Sidebar 的强耦合
  • 让 Sidebar 切页时不重新参与重布局初始化
  • 为树结构建立局部刷新协议,而不是整树重拉
  • 为导航行为建立预取与轻量缓存策略

8.3 风险控制

  • 拖拽重排不能倒逼回到全客户端大组件
  • 树结构局部刷新不能破坏 SSR 壳稳定性
  • 布局层不得继续持有超大导航状态容器

8.4 完成判定

  • Sidebar 不再是主布局中的超大客户端核心组件
  • 页面树 / 文件树的数据与主要规则已由 Rust 层统一提供
  • 切页时 Sidebar 只参与局部交互,不再放大整页挂载成本

8.5 当前落地状态(2026-04-16

  • layout 已在服务端先调用 loadSidebarDataFromConvex(...) 输出 SidebarInitialData,导航首屏数据不再默认延迟到客户端再拼。
  • /api/sidebarsrc/lib/sidebar-data.tssrc/lib/server/sidebar-data.ts 与实时 hook 已统一复用 sidebar.dataset.list 的共享契约。
  • 当前 Sidebar 仍保留交互型客户端组件形态,但切页和刷新已建立“服务端首包 + 局部 island”边界,后续只需继续瘦身而不是回到旧的整页初始化模式。

9. Phase 4:搜索系统 Rust 化与 island 化

9.1 目标

让搜索成为一个轻页面、轻浮层、轻交互系统,而不是全局重组件。

9.2 实施清单

  • 明确搜索索引层、召回层、结果聚合层全部由 Rust 提供
  • 明确文档、块、标题、标签、对象搜索的统一协议
  • 为搜索结果定义服务端可渲染的数据模型
  • 将 SearchPalette 改造成独立 island
  • 将输入框、联想、最近搜索、结果列表拆成最小交互单元
  • 将搜索页主内容改成 server-first 页面
  • 建立搜索结果分页、滚动续取、键盘导航协议
  • 建立最近搜索与最近访问的轻量持久层
  • 避免搜索组件再作为全局常驻重组件绑定整页布局

9.3 完成判定

  • 搜索框打开与关闭不再引发整页级别的重计算
  • 搜索结果主要由 Rust 提供,前端只负责最小交互呈现
  • 搜索能力不再依赖当前全局 React 壳维持状态

9.4 当前落地状态(2026-04-16

  • SearchPalette 已拆成轻量 SearchPaletteHost + search-palette.runtime,首次快捷键或首次打开前不再加载重量运行态。
  • 全局布局只保留搜索 host 接线,Ctrl/Cmd+P 与引用快捷键先由 host 接住,再按需拉起 runtime。
  • SearchPaletteHost 的动态导入已修正为直接指向 runtime,避免 host 自引用导致的错误懒加载。

10. Phase 5AI 面板进一步收口为纯桥接 island

10.1 目标

让 AI 面板彻底变成“后端工具桥 + 最小 UI”,不再成为大前端的第二套系统。

10.2 实施清单

  • 确认所有主线 AI tools 已收口到 Rust runtime / Hermes
  • 删除或冻结旧前端 registry / orchestration 入口
  • 统一 AI 面板的最小会话协议
  • 统一页面上下文注入协议
  • 统一 AI 输出渲染协议
  • 统一流式 token / tool event / client action 回传协议
  • 将页面级 AI 面板统一为单一 bridge shell
  • 将 AI 面板按需挂载为 island
  • 去掉常驻全局 AI host 对主布局的影响
  • 去掉面板自身承载重量级对象逻辑的习惯

10.3 完成判定

  • AI 面板已不再承担第二套工具编排
  • AI 面板关闭或未打开时,不影响页面切换主链
  • AI 页面壳只剩桥接、上下文、渲染,不剩对象真执行逻辑

10.4 当前落地状态(2026-04-16

  • 文档页、导图页、OnlyOffice 三类 AI 面板都已收口为轻 host + 按需 runtime islandHermes / Rust bridge / client-tool-result 主链继续复用现有接缝。
  • 文档页 host 只维护 available/open 生命周期;OnlyOffice host 只负责接住插件 ready 握手;导图 host 只在切到 AI tab 时按需挂载 runtime。
  • GlobalAiAgentHost 继续保留为实验入口组件,但不再回到 app layout 常驻主链,避免重新变成全局重量壳。

11. Phase 6Mindmap 独立对象化与独立页面化

11.1 目标

把 Mindmap 从“BlockNote 的一类重自定义块”推进为“独立对象 + 独立页面 + 可嵌入轻预览”。

11.2 实施清单

  • 定义 Mindmap 独立对象模型
  • 定义 Mindmap 读写协议与操作协议
  • 明确导图节点、边、布局、样式、视口状态的 Rust 持久化结构
  • 明确导图页面独立于文档页的服务端壳
  • 将独立导图页优先迁到 Rust Web 层
  • 将文档内嵌导图降级为轻预览或轻交互卡片
  • 把导图工具栏、侧栏、缩略图等拆成局部 island
  • 去掉对 BlockNote editor context 的强依赖
  • 去掉“文档内嵌导图”和“独立导图页”共用同一重前端壳的绑定方式

11.3 完成判定

  • Mindmap 已可以在不依赖 BlockNote 主运行时的情况下独立打开
  • 文档页不再因为导图组件而被迫挂载整套导图交互壳
  • 导图对象已进入 Rust 主线,而不是继续主要依赖前端组件状态

11.4 当前落地状态(2026-04-16

  • 独立导图页已切到 StandaloneMindmapView,不再依赖 fake editorStub 或 BlockNote editor context。
  • 文档内嵌导图已降级为轻预览 / 轻交互入口,文档主链不再因为独立导图壳而被迫进入重运行态。
  • Mindmap AI 与导图独立页都已按对象级接缝继续走 Rust / bridge 主线,而不是继续把主逻辑绑在文档编辑器里。

12. Phase 7:文档编辑态与 BlockNote 孤岛化

12.1 目标

最后再处理真正难替代的 BlockNote,把它从“默认页面入口前提”改成“按需挂载的重编辑岛”。

12.2 实施清单

  • 明确阅读态与编辑态的切换协议
  • 明确进入编辑态时的最小初始化协议
  • BlockNote 依赖的外围功能继续向外剥离
  • 将评论、回链、历史、AI、页面选项等从编辑器默认初始化链上移走
  • 将自定义 block 的读取协议改成可按需注入
  • 将只读渲染与可编辑渲染彻底拆开
  • 将文档打开路径改成“阅读态常驻,编辑态进入时挂编辑岛”
  • 为编辑岛建立独立错误边界
  • 为编辑岛建立独立性能采样
  • 为编辑岛建立独立恢复机制

12.3 禁止事项

  • 不允许在这一步之前就试图整体替换全部编辑器能力
  • 不允许让阅读页重新回退为“先挂编辑器再展示内容”
  • 不允许把新的外围面板重新绑回 BlockNote 初始化链

12.4 完成判定

  • 绝大多数页面访问不需要等待 BlockNote
  • 编辑器只在真正进入编辑态时才挂载
  • BlockNote 已成为孤岛,而不是整个页面系统的基础前提

12.5 当前落地状态(2026-04-16

  • 阅读态与编辑态的切换协议已经落地:默认阅读、显式进入编辑、openTableId 强制编辑、退出编辑后保留短暂 grace period 再卸载编辑岛。
  • 评论、历史、回链、页面 AI、页面选项等外围能力都已从 BlockNote 默认初始化链外移,阅读态可以单独存在。
  • DocumentReadViewBlockNoteEditor 已形成两套不同初始化协议,BlockNote 现在是按需进入的重编辑 island,而不是整页入口前提。

13. Phase 8:旧前端壳下线与兼容清理

13.1 目标

在新结构稳定后,清理旧壳,避免双栈长期共存。

13.2 实施清单

  • 盘点仍保留的 Next 页面壳与 API 壳
  • 标记哪些属于长期兼容层
  • 标记哪些属于可删除过渡层
  • 删除已被 Rust Web 层替代的 route
  • 删除已被 Rust islands 替代的全局客户端面板
  • 删除失效的桥接 helper、旧 registry、旧 adapter
  • 清理不再使用的布局状态容器
  • 清理不再使用的动态导入链
  • 更新运行文档与架构文档
  • 更新开发约束,禁止回流到旧模式

13.3 完成判定

  • 旧前端壳已不再是主路径
  • 双栈只是短期兼容,而不是长期事实
  • 维护成本已经从“双系统并行”回到“单主线演进”

13.4 当前收缩口径(2026-04-16

  • 已明确当前仍保留的 Next/React 页面壳:文档页、Sidebar、搜索、AI host 与 OnlyOffice 页面仍在兼容层内,但重运行态已被拆到按需 island。
  • 已完成这一轮最小清理:搜索与各类 AI 面板的重量 runtime 不再默认跟随主布局常驻,GlobalAiAgentHost 继续停留在实验入口而不是 app layout 主链。
  • 已把长期清单、长期架构方案与 harness 状态统一回写,后续 Phase 8 继续以“删旧壳前先写清保留边界”为准,而不是靠误删制造假完成。

14. 横向能力清单

这些事情不属于单一阶段,但必须贯穿全部阶段推进。

14.1 观测与性能

  • 建立统一性能指标:首字节、首屏、交互可用、切页耗时、编辑器挂载耗时
  • 建立统一错误指标:页面壳错误、island 错误、编辑器错误、桥接错误
  • 建立统一 trace 关联:页面请求、Rust query、Rust command、Hermes tool、前端 island
  • 建立按页面类型的性能对比面板

最低交付物:

  • 每个页面壳请求都必须生成 request_id / trace_id,并能串到 Rust query/command 与 Hermes tool。
  • 文档页、Sidebar、搜索、AI、Mindmap、编辑岛都要有统一的 performance mark 命名规则。
  • 回归脚本必须至少覆盖:文档页、Mindmap、OnlyOffice、AI tool runtime、Sidebar/文件树定向测试。

14.2 缓存与预取

  • 建立阅读页缓存策略
  • 建立树结构局部缓存策略
  • 建立搜索结果缓存策略
  • 建立文档邻近页面预取策略
  • 建立失败回退与缓存失效策略

最低交付物:

  • 阅读页采用“meta + content”同一读链缓存键,不能再拆成首屏后二次正文请求作为默认主路径。
  • 树结构、搜索结果、邻近页面预取都必须显式声明失效来源,避免隐式常驻缓存。
  • 失败回退策略必须写明是回源、回旧壳还是退到只读页面。

14.3 安全与权限

  • 统一页面壳权限校验
  • 统一对象级读写鉴权
  • 统一浏览器 island 的最小权限输入
  • 统一 AI / Hermes 的工具权限边界

最低交付物:

  • 页面壳、对象查询、对象写入、AI tool 调用必须复用同一 workspace / actor / tenant 上下文。
  • browser island 只能收到最小权限输入,不能自己推导更高权限。
  • Hermes 与 mnote Rust 之间的 bridge 必须只暴露最小业务能力面,不复制前端编排逻辑。

14.4 开发规范

  • 新功能默认先判断是否属于 server-first 页面
  • 新交互默认先判断是否可以做成局部 island
  • 新业务规则默认只进 Rust core
  • 新页面默认不能直接复制旧重前端壳模式

最低交付物:

  • 提交新页面时必须回答四个问题:是否 server-first、是否 island、对象规则是否进 Rust、是否引入新的常驻壳。
  • 没有 trace / 缓存 / 权限口径的新页面或新 island,不允许直接并入长期主线。

15. 最终验收清单

只有下面这些问题都能回答“是”,这条长期路线才算真正跑通。

  • 打开一个普通文档时,是否已经可以先稳定进入阅读态
  • 切换页面时,是否已经不再默认触发重编辑器初始化
  • Sidebar 是否已经不再是主布局里的超大客户端组件
  • 搜索是否已经不再依赖全局大组件常驻
  • AI 面板是否已经变成纯桥接 island
  • Mindmap 是否已经能独立于 BlockNote 主运行时工作
  • Rust Web 层是否已经能承接主 API、主页面壳、主流式链路
  • Rust core 是否已经成为唯一业务真执行面
  • BlockNote 是否已经被延后为最后处理的孤岛,而不是继续绑住整页架构
  • 旧前端壳是否已经开始实质性退场,而不是继续成为默认主路径

当前可回答“是”的项(2026-04-16):

  • 打开一个普通文档时,已经可以先稳定进入阅读态。
  • 切换页面时,已经不再默认触发重编辑器初始化。
  • 搜索已经不再依赖全局大组件常驻。
  • AI 面板已经收口为纯桥接 island。
  • Mindmap 已能独立于 BlockNote 主运行时工作。
  • BlockNote 已被延后为最后处理的孤岛,而不是继续绑住整页架构。

16. 一句话执行顺序

如果后续需要不断回看,这条路线可以压缩成一句话:

先冻结旧壳扩张,再立 Rust Web 层;先迁阅读页、Sidebar、搜索、AI、Mindmap,最后才处理 BlockNote;稳定后再清旧壳,而不是反过来。