Skip to Content

OT vs CRDT:前端开发者的协同编辑技术选择

作为前端开发者,当我们需要实现类似 Google Docs 的协同编辑功能时,主要有两种技术方案:OT(操作转换)CRDT(无冲突复制数据类型)。本文将从实际开发角度对比这两种方案。

快速理解两种方案

OT(操作转换)- 传统方案

想象两个人同时在文档的同一位置插入文字,OT 需要”协调”这些操作:

// 用户A在位置5插入"Hello" // 用户B同时在位置5插入"World" // OT需要转换:谁的操作先执行?位置如何调整?

CRDT(无冲突复制数据类型)- 现代方案

每个操作都有唯一标识,自动合并,无需协调:

// 每个操作都有全局唯一ID,自动排序合并 // 不需要复杂的转换逻辑

从开发体验对比

OT 的开发痛点

1. 复杂的转换逻辑

// OT需要为每种操作组合写转换函数 function transformInsertInsert(op1, op2) { if (op1.position <= op2.position) { return [op1, { ...op2, position: op2.position + op1.length }] } else { return [{ ...op1, position: op1.position + op2.length }, op2] } } function transformInsertDelete(op1, op2) { // 又是一堆复杂逻辑... } function transformDeleteDelete(op1, op2) { // 更多复杂逻辑... } // 还有很多很多组合...

2. 难以调试

// OT的bug很难追踪 // 操作A + 操作B = 正常 // 操作B + 操作A = 出错? // 需要检查所有转换函数的组合

CRDT 的开发优势

1. 简洁的实现

// 使用Yjs,几行代码搞定协同编辑 import * as Y from 'yjs' import { WebsocketProvider } from 'y-websocket' const ydoc = new Y.Doc() const ytext = ydoc.getText('content') const provider = new WebsocketProvider('ws://localhost:1234', 'room', ydoc) // 插入文本 ytext.insert(0, 'Hello World') // 就这么简单!

2. 与前端框架完美集成

// React + TipTap + Yjs import { useEditor, EditorContent } from '@tiptap/react' import StarterKit from '@tiptap/starter-kit' import Collaboration from '@tiptap/extension-collaboration' function CollaborativeEditor() { const editor = useEditor({ extensions: [ StarterKit, Collaboration.configure({ document: ydoc, // 直接传入Yjs文档 }), ], }) return <EditorContent editor={editor} /> }

实际项目中的差异

网络处理

OT 的网络问题

// OT需要保证操作顺序,网络延迟会影响体验 class OTEditor { sendOperation(op) { // 必须等待服务器确认才能继续 this.waitingForAck = true this.socket.send(op) } onAck() { this.waitingForAck = false // 处理缓存的操作... } }

CRDT 的网络优势

// CRDT可以立即应用操作,后台同步 class CRDTEditor { insert(pos, text) { // 立即在本地显示 this.ytext.insert(pos, text) // 自动同步到其他客户端,无需等待 } }

离线支持

OT 的离线困难

// OT离线后重连很复杂 class OTEditor { goOffline() { // 需要缓存所有操作 this.offlineOps = [] } goOnline() { // 重连时需要重新计算所有转换 this.resyncAllOperations() } }

CRDT 的离线友好

// CRDT天然支持离线 import { IndexeddbPersistence } from 'y-indexeddb' // 自动本地存储 const persistence = new IndexeddbPersistence('doc-id', ydoc) // 离线编辑,上线自动同步 // 无需额外代码!

性能对比(前端关心的指标)

指标OTCRDT
首次加载稍慢(需要加载更多元数据)
编辑响应慢(需要等待转换)快(立即响应)
内存占用中等
包大小大(复杂逻辑)小(Yjs ~100KB)
开发难度极高

实际项目选择建议

选择 CRDT 的场景(推荐)

// 适合大部分前端项目 const shouldUseCRDT = { richTextEditor: true, // 富文本编辑器 codeEditor: true, // 代码协同编辑 drawingApp: true, // 绘图应用 mobileApp: true, // 移动端应用 offlineFirst: true, // 需要离线支持 rapidDevelopment: true // 快速开发 }

选择 OT 的场景(少数)

// 只在特殊情况下考虑 const shouldUseOT = { extremeBandwidthLimit: true, // 极端带宽限制 simpleTextOnly: true, // 只有纯文本 legacySystem: true // 已有OT系统 }

现代前端生态系统

CRDT 生态(推荐)

// 丰富的前端工具链 import * as Y from 'yjs' // 核心库 import { WebsocketProvider } from 'y-websocket' // WebSocket同步 import { IndexeddbPersistence } from 'y-indexeddb' // 本地存储 import { TiptapCollabExtension } from '@tiptap/extension-collaboration' // TipTap集成 // Vue集成 import { VueEditor } from '@tiptap/vue-3' // React集成 import { useEditor } from '@tiptap/react'

实际项目示例

// 一个完整的协同编辑器组件 import React, { useEffect } from 'react' import { useEditor, EditorContent } from '@tiptap/react' import StarterKit from '@tiptap/starter-kit' import Collaboration from '@tiptap/extension-collaboration' import CollaborationCursor from '@tiptap/extension-collaboration-cursor' import * as Y from 'yjs' import { WebsocketProvider } from 'y-websocket' export default function CollaborativeEditor({ roomId, userName }) { const ydoc = new Y.Doc() const editor = useEditor({ extensions: [ StarterKit.configure({ history: false }), Collaboration.configure({ document: ydoc }), CollaborationCursor.configure({ provider: new WebsocketProvider('ws://localhost:1234', roomId, ydoc), user: { name: userName, color: '#f783ac' }, }), ], }) return <EditorContent editor={editor} /> } // 就这么简单,一个协同编辑器就完成了!

为什么前端开发者更喜欢 CRDT?

1. 开发效率

  • OT: 需要几个月实现和调试
  • CRDT: 几天就能上线

2. 用户体验

  • OT: 操作有延迟,需要等待服务器
  • CRDT: 立即响应,感觉像本地编辑

3. 维护成本

  • OT: 复杂的bug,难以修复
  • CRDT: 简单直观,易于维护

4. 现代化特性

// CRDT支持现代前端需求 const modernFeatures = { offlineFirst: '✅ 天然支持', mobileOptimized: '✅ 移动端友好', frameworkAgnostic: '✅ 框架无关', typescript: '✅ 完整类型支持', ssr: '✅ 服务端渲染支持' }

总结

作为前端开发者,强烈推荐选择 CRDT 方案

  1. 学习成本低 - 几小时就能上手
  2. 开发速度快 - 几天就能实现协同功能
  3. 用户体验好 - 真正的实时协同
  4. 维护简单 - 不用担心复杂的转换逻辑
  5. 生态完善 - 与主流前端框架完美集成

除非你的项目有极特殊的限制(比如极端的带宽要求),否则 CRDT 就是最佳选择。现代协同编辑应用如 Notion、Figma 等都在使用 CRDT 相关技术,这已经成为行业标准。

一句话总结:选择 CRDT,让协同编辑变得简单!

Last updated on