实时协作CRDT性能优化
实时协作白板
支持多人光标与离线合并的轻量白板,首屏 LCP 从 2.8s 降到 0.9s。
- 角色
- 前端负责人
- 周期
- 2025-03 ~ 2025-08
- 技术栈
- React · TypeScript · Yjs · WebSocket
背景
团队需要一块可以嵌进工单系统的白板:多人同时标注、断网后继续编辑、恢复网络时自动合并。市面方案要么体积过大,要么离线能力不足,最终决定自研核心画布与同步层。
我的职责
- 负责画布渲染、交互手势与同步层的整体设计
- 制定 CRDT 数据结构与冲突合并策略
- 搭建性能基线,推动首屏与输入延迟优化
方案与取舍
画布采用 Canvas 分层渲染,静态图形与实时光标分离,避免每次光标移动触发全量重绘。同步层基于 Yjs,文档按区块切分,只同步可见区域。
| 方案 | 包体积 | 离线合并 | 结论 |
|---|---|---|---|
| 全量状态广播 | 小 | 不支持 | 放弃 |
| CRDT 全文档 | 中大 | 支持 | 合并粒度粗 |
| 分区块 CRDT | 中 | 支持 | 采用 |
const doc = new Y.Doc({ gc: false });
const shapes = doc.getMap<Shape>("shapes");
export function applyRemote(update: Uint8Array) {
Y.applyUpdate(doc, update, "remote");
}
结果与复盘
首屏 LCP 从 2.8s 降到 0.9s,协作冲突率下降 92%。复盘时发现最大的收益来自「减少同步数据量」,而不是渲染层优化;如果重做,会先做流量剖析再动渲染。