用SyncKit打造类Google Docs实时协作编辑器:LocalWrite Demo源码拆解 用SyncKit打造类Google Docs实时协作编辑器LocalWrite Demo源码拆解【免费下载链接】synckitLocal-first collaboration SDK for React, Vue, and Svelte. Batteries-included: Rich text, undo/redo, cursors, and presence.项目地址: https://gitcode.com/gh_mirrors/syncki/synckitSyncKit 是一个面向 React、Vue、Svelte 的 Local-first 实时协作编辑器 SDK自带富文本、撤销重做、实时光标与在线状态Presence。它的官方 Demo——LocalWrite——就是一个类 Google Docs 的多人协作编辑器打开两个标签页输入文字会看到字符级实时同步、冲突自动合并、他人光标跟随等核心协作能力。本文带你逐层拆解 LocalWrite Demo 的源码帮你理解如何从零搭出自己的实时协作编辑器。LocalWrite Demo 是什么代码在哪里LocalWrite 是 SyncKit 的旗舰示例包名就叫synckit-localwrite见 demo/package.json它把 SDK 的全部能力装进了一个 Notion 风格的博客编辑器能力对应实现区块化文档编辑Slash 命令、拖拽排序demo/src/components/Editor.tsx字符级实时文本同步demo/src/hooks/useBlockText.ts实时光标 在线状态demo/src/components/Cursors.tsx房间路由与分享链接demo/src/lib/rooms.ts离线优先存储OPFS/IndexedDBdemo/src/lib/storage.ts整体思路一句话概括页面元数据用 LWW 文档同步正文文字用 Fugue CRDT 同步光标和在线状态走 Awareness 广播。三层各用对的工具正是类 Google Docs 体验的关键。初始化 SyncKit5 行代码接通协作能力入口在 demo/src/App.tsx它只负责一件事——调用initializeSyncKit()并注入 React Contextconst { synckit, storage } await initializeSyncKit(); // ... SyncKitProvider synckit{synckit} storageType{storage.type} AppContent / /SyncKitProvider真正的核心逻辑在 demo/src/lib/synckit.ts整个初始化只有 5 行const storageInfo await initializeStorage(); // 1. 本地存储 const synckit new SyncKit({ // 2. 创建实例 name: localwrite, storage: storageInfo.storage, serverUrl: wss://synckit-localwrite.fly.dev/ws, // 3. 可选接入服务端 }); await synckit.init(); // 4. 启动同步引擎三个要点值得学习storage本地存储是可信源设备数据先落盘再同步断网也能继续编辑serverUrl可选参数。不传就纯本地/跨标签页同步传了才接入 WebSocket 服务器做多设备协作Context 注入demo/src/contexts/SyncKitContext.tsx全应用共享同一个 SyncKit 实例任何组件用useSyncKit()取用避免重复初始化。房间路由URL 怎么映射成同步文档Google Docs 靠文档链接拉人协作LocalWrite 用 URL hash 实现同样的房间模型代码见 demo/src/lib/rooms.tswindow.location.hash /room/abc123; // 分享链接关键函数roomToDocumentId()把房间 ID 转成 SyncKit 的文档 IDexport function roomToDocumentId(roomId: string, isPrivate: boolean false): string { return isPrivate ? proom:${roomId} : room:${roomId}; }这样#/room/abc123和#/proom/abc123私有房间就自然映射到两份不同的同步文档。任何人打开同一个房间链接App.tsx会用这个 ID 执行synckit.document(...)doc.init()自动从服务器拉取最新内容——这就是一个链接拉进一个协作空间的全部秘密。数据模型为什么用每块一字段而不是数组这是 Demo 中最值得抄的架构决策见 demo/src/lib/blocks.ts。LocalWrite 没有把整篇文档存成一个大数组而是每个区块标题、段落、待办……作为文档的一个独立字段export interface PageDocument { id: string; title: string; blockOrder: string; // [block-1,block-2] 顺序表 [key: string]: unknown; // block:block-1: { id, type, content, ... } ← 每个区块一个字段 // block:block-2: { ... } }源码注释特意强调 do NOT use arrays!。原因是 SyncKit 文档字段走 Last-Write-Wins 合并两个人同时编辑不同区块互不干扰若整个页面是一个数组任何人的插入都会触发整体覆盖合并并发编辑极易丢内容。顺序表 独立字段是区块编辑器对抗写冲突的标准姿势。字符级实时同步Fugue CRDT 是怎么接入的页面元数据用 LWW 足够但正文文字需要两人同时打字谁都不丢这就要靠 CRDT。Demo 的封装在 demo/src/hooks/useBlockText.tsconst text synckit.text(${pageId}:text:${blockId}); // 每个区块一个 SyncText await text.init(); text.subscribe((newContent) setContent(newContent)); // 订阅远端变更编辑流程是useBlockText的updateContent()ContentEditable 输入产生新字符串computeTextDiff()对比新旧内容算出最少的插入/删除操作序列逐条text.insert(pos, str)/text.delete(pos, len)应用到 Fugue CRDT远端变更到达后CRDT 自动合并subscribe回调刷新 UI。其中两个工程细节很实用多操作时用beginBatch()/endBatch()批量提交避免跨标签页广播产生竞态操作前重新校验位置合法性应对并发编辑导致的偏移。区块渲染层 demo/src/components/CRDTBlockComponent.tsx 只是把这个 Hook 包进可编辑组件——内容不再由父组件传值而是 CRDT 自己说了算。实时光标与在线状态Awareness 广播看到别人的光标在动是类 Google Docs 体验的灵魂实现见 demo/src/components/Cursors.tsxconst awareness synckit.getAwareness(documentId); await awareness.init(); // 订阅他人状态用户信息、光标位置、是否正在打字光标、选区、正在输入…这类状态不参与数据合并只是临时广播所以 SyncKit 用独立的 Awareness 通道承载本地输入时更新自己的状态远端状态驱动[Cursors.tsx](https://link.gitcode.com/i/28d231b3f4c4c1296ab295ad84849e1c)渲染彩色光标与打字指示。注意它的注释强调该组件是READ-ONLY——只读订阅他人状态本地状态由 Editor 统一写入防止自己覆盖自己这是多人协作 UI 的经典防坑点。离线优先断网继续写恢复自动同步LocalWrite 默认完全离线可用。存储层在 demo/src/lib/storage.ts// 优先 OPFS写入快 3.75 倍、读取快 6 倍不支持时回退 IndexedDB const storage new OPFSStorage(); // 首选 await storage.init(); // 失败则 const storage new IndexedDBStorage(); // 兜底这套本地存储 操作队列 断点续传意味着飞机上编辑照常保存落地联网后操作队列自动重放同步——这正是 SyncKit True offline-first 的承诺文档可见 docs/guides/offline-first.md。部署与延伸阅读Demo 附带 demo/Dockerfile 和 demo/fly.toml一条fly deploy就能上线Nginx 静态托管 官方服务器接收同步流量。想动手跑起来git clone https://gitcode.com/gh_mirrors/syncki/synckit cd synckit/demo npm install npm run dev # 本地纯离线即可体验两个标签页互相协作源码导读地图demo/src/App.tsx入口、路由与全局状态demo/src/lib/synckit.tsSDK 初始化demo/src/lib/rooms.ts房间模型demo/src/lib/blocks.ts区块数据模型demo/src/hooks/useBlockText.tsCRDT 文本同步demo/src/components/Cursors.tsx实时光标docs/architecture/ARCHITECTURE.md整体架构设计docs/guides/getting-started.md5 分钟上手指南总结LocalWrite 用三层同步策略撑起类 Google Docs 体验——页面元数据走 LWW 文档、正文走 Fugue CRDT、光标走 Awareness 广播配合每块一字段的数据模型和 OPFS 离线存储。照 demo/ 的源码路径走一遍你就拥有了在自己项目里搭建实时协作编辑器的完整路线图。【免费下载链接】synckitLocal-first collaboration SDK for React, Vue, and Svelte. Batteries-included: Rich text, undo/redo, cursors, and presence.项目地址: https://gitcode.com/gh_mirrors/syncki/synckit创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考