☰
核心包仅325KB、重依赖按需拉取:DSH-better-sidebar性能优化背后的完整原理
2026/9/26 2:48:34 网站建设 项目流程

核心包仅325KB、重依赖按需拉取:DSH-better-sidebar性能优化背后的完整原理

【免费下载链接】DSH-better-sidebar开放的侧边栏底座,支持三方拓展注册新侧边栏页面。内置文件渲染编辑/终端/侧边对话/Git/子代理页面 | Open sidebar foundation, supports third-party extensions to register new sidebar pages. Built-in file rendering/editing, terminal, side chat, Git, and sub-agent pages.项目地址: https://gitcode.com/gh_mirrors/ds/DSH-better-sidebar

DSH-better-sidebar 是一个开放的侧边栏底座:支持三方扩展注册新的侧边栏页面,并内置文件渲染编辑、终端、侧边对话、Git 与子代理页面。它最亮眼的性能设计是——浏览器启动时只下载约 325KB 的核心包,而编辑器、终端、Mermaid 图表这类重依赖全部按需拉取。这篇文章带你完整拆解这套性能优化的背后原理。

1️⃣ 问题背景:为什么启动会这么重

拆分之前,客户端是一个单文件 bundle(约 24.6MB),页面一启动就要全部下载 + 解析 + 执行。体积大头来自预览类重依赖:

重依赖体积用途
@univerjs/*全家桶(含 echarts/zrender)~18MB.xlsx 预览
@codemirror/*+@lezer/*~1.9MB文本编辑器高亮
mermaid+ 图论引擎~7MBMarkdown 图表渲染
xterm~0.3MB终端
插件自身代码~0.35MB—

问题在于:绝大多数用户启动时根本不会打开 .xlsx 或 Mermaid 图表,却要为它们付出下载与解析成本。即使用动态import(),也只是「延迟执行」——下载成本依然发生在启动时。

优化目标很明确:重依赖拆成独立脚本,首次打开对应功能才下载;启动只拉核心(~325KB)。

2️⃣ 原理一:懒加载分块(Lazy Chunks)——用到才付钱

拆分的核心思路是把每个重功能构建成独立脚本,按需注入。整个机制分构建期和运行期两段:

构建期:每个 chunk 由 tsdown.config.ts 编译成独立的浏览器 bundle(lib/client-<name>.js),脚本首行会把自己注册到页面级全局注册表globalThis.__dshChunks__中,而不是走宿主的模块加载器——这样解析行为不依赖具体宿主版本,跨版本最稳。

运行期:chunk-loader.ts 的loadChunk负责三步物化:

  1. 注入<script src="/sidebar/bundle/<name>.js">,由插件自己的路由 bundle-route.ts 服务;
  2. 从全局注册表读取该 chunk 的 factory;
  3. 用自定义require物化——外部依赖(react、cordis 等)经宿主模块表解析,命中「seed 分支」这条跨版本一致的稳定路径。

当前的分块清单(完整设计见 lazy-chunks 设计文档):

Chunk构建产物触发时机
核心client.js(~325KB)页面启动
editorclient-editor.js(~1.6MB)打开 code / md / html 文件
terminalclient-terminal.js(~450KB)打开终端 tab
mermaidclient-mermaid.js(~7MB)预览含 mermaid 的 md
localeclient-locale.js安装了 better-locale 插件时才拉

体验细节同样讲究:lazy-chunk.tsx 给每个懒组件包了一层「loading / error / retry」三态视图——某个 chunk 加载失败只会让该视图显示错误与重试按钮,侧边栏其余部分照常工作。

3️⃣ 原理二:三层缓存契约——按需拉取不等于反复下载

「按需」意味着可能被多次触发,项目为此设计了三层缓存,每层都带失败兜底:

层机制失败路径
内存每 chunk 一个 in-flight promise,并发去重失败删除缓存项,下次重试
执行脚本执行即覆盖全局注册表槽位(赋值幂等,无重复注册错误)物化失败清缓存,重新注入脚本
HTTPno-cache+ ETag,If-None-Match命中返回 304文件变化 ETag 轮转,返回 200

HTTP 层的价值最大:页面刷新、热更新重新激活时,未变化的多 MB chunk 直接 304 免重下载——刷新一次页面不用把 7MB 的 mermaid 再拉一遍。

4️⃣ 原理三:运行时开销瘦身——从轮询到渲染

体积只是性能的一半,运行时 CPU 成本同样要抠。性能优化设计文档 列了 10 项改动,挑几个代表性的:

  • 启动 RPC 合并:boot 阶段两次串行settings.get合并为一次,并给第二个请求补上 2s 超时兜底(此前 RPC 挂起会导致侧边栏永不出现);
  • Git 轮询降频:GitLens 的 2s 轮询不再每 tick 重列 worktrees,git 进程 spawn 每分钟 60 个降到约 34 个(-43%);
  • 渲染稳定化:SideChat 转录中内容未变的行复用旧对象,让下游 React 调和与 markdown 解析整段跳过;FileTree 的展开集合由数组includes()线性扫描改为 Set;
  • 编辑器不再每键全文字符串化:从每次按键 O(文档长度) 的doc.toString()降为 0(只翻 dirty 标记)。

真机实测收益(Playwright 无头 Chromium,每指标 3 次取中位数,测量 lane 见 tests/e2e/perf.e2e.ts):

指标优化前优化后变化
挂载时延(navigationStart → host attach)376.9 ms272.9 ms-28%
宿主聚合 bundle 传输量(gzip)1,436 KB1,234 KB-203 KB / -14%
核心包体积基准再瘦身 45%词典等 ~640KB 源码移出核心

5️⃣ 快速上手:三步复现

git clone https://gitcode.com/gh_mirrors/ds/DSH-better-sidebar cd DSH-better-sidebar pnpm install

构建产物会生成核心lib/client.js与一组lib/client-<name>.js按需 chunk。可以用 scripts/e2e-mount.sh 把构建好的插件挂载到 DSH 宿主跑冒烟,性能回归则由 perf 测量 lane 与 tests/lazy-chunk.spec.tsx、tests/chunk-artifact.spec.ts 等契约测试长期钉住。

6️⃣ 总结:三句话记住这套性能优化原理

  1. 先拆再按需:重依赖在功能首次打开时才下载、解析、执行,启动路径只保留 325KB 核心包;
  2. 三层缓存保底:内存去重 + 幂等执行 + HTTP ETag 304,保证「按需拉取」永远不会变成「反复拉取」;
  3. 运行时开销也是性能:轮询频率、渲染复用、启动 RPC——一堆小改动叠加出挂载时延近三成的提升。

【免费下载链接】DSH-better-sidebar开放的侧边栏底座,支持三方拓展注册新侧边栏页面。内置文件渲染编辑/终端/侧边对话/Git/子代理页面 | Open sidebar foundation, supports third-party extensions to register new sidebar pages. Built-in file rendering/editing, terminal, side chat, Git, and sub-agent pages.项目地址: https://gitcode.com/gh_mirrors/ds/DSH-better-sidebar

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询