diff --git a/AGENTS.md b/AGENTS.md index b909a41..dc6fd75 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -396,6 +396,7 @@ interface BetterSidebarService { | **host 半无此服务** | `ctx.betterSidebar` 只在 client 侧存在;host 半需要 better-sidebar 数据走 `/sidebar/api/*` HTTP 路由 | | **portal 限制** | 整面板 slot 由 ui-layout 独占,外部 tab 只能进入 better-sidebar 的 portal 内部,无法全屏替换 | | **id 冲突** | `registerTab` / `registerFileViewer` 对重复 id 抛错;建议用包前缀(`my-plugin:xxx`) | +| **懒加载 chunk** | 内置重依赖(Univer/xterm/CodeMirror/pptx/docx)在独立 bundle(`lib/client-.js`)中,经 `/sidebar/bundle` 路由按需下发;每个脚本把 factory 赋到插件自有全局注册表 `globalThis.__dshChunks__[]`,由 `src/client/chunk-loader.ts` 用自定义 require(externals 经 `__DSH_MODULES__` seed 分支解析)物化——**不经过** `__ModuleLoader__` 注册;**核心 bundle 禁止静态 import `src/client/chunks/*`**(会把库拖回启动路径);对消费插件透明——懒加载只作用于内置 descriptor,`component` 契约(`(props) => ReactNode` 纯渲染函数)不变 | --- diff --git a/README.md b/README.md index db1e883..6a6a8c4 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ - **🗂️ 资源管理器**:懒加载目录树(根 = 会话 cwd)、点击在侧边栏打开、行尾 `@文件` 引用到输入框、右键复制路径 - **📝 编辑与预览**:CodeMirror 6 多语言高亮 + Ctrl/Cmd+S 原子保存;图片 / Markdown(预览/编辑切换)/ HTML(沙箱 iframe 预览,相对资源可加载)/ PDF / Word / Excel / PPT 内联预览,切换 Tab 不丢草稿 +- **⚡ 客户端懒加载**:Office / 终端 / 代码编辑器等重依赖按需分块加载——启动只拉 ~325KB 核心,打开 .xlsx 才拉 Univer(~20MB)、打开 .docx 只拉 docx 预览器、打开终端才拉 xterm;首次打开短暂 loading 后即用(详见 `docs/plans/2026-08-12-lazy-chunks-design.md`) - **🌐 浏览器**:内嵌网页浏览 tab(多开),后退/前进/刷新 +「在浏览器中打开」;页面在**沙箱 iframe** 中运行(不透明源:无法访问界面数据与本地文件,拒绝 localhost 等本机地址),界面实时显示沙箱状态、可临时解锁(关闭时红色警示);被站点拒绝嵌入(X-Frame-Options)时显示原因面板;聊天/界面里的 http(s) 外链默认在侧边栏打开 - **💻 终端**:xterm.js + node-pty 真实 shell(每会话 3 个 UI 上限)、Tab 保活重连回放;可选为模型注入 8 个 `terminal_*` 工具 - **🌿 Git 面板**:真 diff + VSCode 式 diff tab、懒加载历史、右键暂存/放弃/提交/还原/捡取 diff --git a/docs/plans/2026-08-12-lazy-chunks-design.md b/docs/plans/2026-08-12-lazy-chunks-design.md new file mode 100644 index 0000000..0a81d9d --- /dev/null +++ b/docs/plans/2026-08-12-lazy-chunks-design.md @@ -0,0 +1,88 @@ +# 客户端懒加载分块(lazy chunks)设计 + +> 日期:2026-08-12 +> 状态:已实现 +> 范围:`dsh-better-sidebar` 插件,客户端 bundle 拆分 + +## 1. 背景与问题 + +改造前客户端是单文件 bundle(`lib/client.js`,约 24.6MB),页面启动时全部**下载 + 解析 + 执行**。实测构成(按 sourcemap 源字节): + +| 依赖 | 体积 | 用途 | +|---|---|---| +| `@univerjs/*` 全家桶 + echarts/zrender 等 | ~18MB | .xlsx 预览 | +| `@codemirror/*` + `@lezer/*` | ~1.9MB | 文本编辑器高亮 | +| `xlsx`(SheetJS) | ~0.6MB | .xlsx 解析 | +| `@aiden0z/pptx-renderer` | ~0.5MB | .pptx 预览 | +| `xterm` | ~0.3MB | 终端 | +| `docx-preview` + `jszip` | ~0.2MB | .docx 预览 | +| 插件自身代码 | ~0.35MB | — | + +虽然 `office-view.tsx` 用了动态 `import()`,但 `codeSplitting: false` 只保证**延迟执行**(`Promise.resolve().then(() => (init_docx_preview(), ...))`),下载与解析成本仍在启动时;且 `xlsx-to-univer.ts` 对 `@univerjs/presets` 的静态 value-import 让 Univer 核心实际在启动时执行。 + +**目标**:重依赖拆成独立脚本,首次打开对应功能才下载/解析/执行;启动只拉核心(~325KB)。 + +## 2. 机制 + +chunk 脚本**不经过** `window.__ModuleLoader__` / `ClientModuleSystem.import()` 的物化路径——模块系统的 import() 只解析 seed word / shell-own 模块 / 已注册 factory / boot graph row,chunk id 四者皆非,解析行为依赖 DSH 版本(实测某些版本在 factory 已注册时仍抛 "cannot resolve")。因此改为插件自有的全局 factory 注册表: + +1. **构建期**:每个 chunk 是独立 tsdown 浏览器 bundle(`lib/client-.js`),脚本首行为: + ```js + globalThis.__dshChunks__ = globalThis.__dshChunks__ || {}; + globalThis.__dshChunks__["terminal"] = (require) => { /* CJS 闭包体 */ }; + ``` + 与主 bundle 相同的 externals(react 等走 module table)、纯度门、CSS 内联管线;`codeSplitting: false` 保持单文件。 +2. **运行期** `loadChunk(name)`: + - 注入 `