蓝戒博客

  • 首页
  • 研发说
  • 架构论
  • 效能录
  • AI谈
  • 随笔集
智构苍穹
融合 AI、架构与工程实践,沉淀方法论,构建可持续的技术价值。
  1. 首页
  2. 研发说
  3. 正文

用 Yjs 打造下一代协同编辑应用

2026年1月10日 51点热度 0人点赞 0条评论

在 Google Docs、Figma 这类应用中,多人同时编辑、实时同步、离线可用已经成为“标配”。这些能力的背后,离不开一个关键技术:协同数据同步模型。

今天要介绍的 Yjs,正是当前前端领域中性能最强、生态最成熟的协同编辑底层库之一。


一、什么是 Yjs?

Yjs 是一个高性能的 CRDT(无冲突复制数据类型)实现,用于构建可自动同步的协作应用程序。

简单来说,Yjs 解决的是:

多个客户端在不同时间、不同顺序、甚至离线状态下修改同一份数据,最终还能 自动合并且永远不冲突。

CRDT 是什么?

CRDT(Conflict-free Replicated Data Type)是一类数据结构,具备以下特性:

  • 支持多端并发修改
  • 不依赖中心服务器进行冲突裁决
  • 修改顺序无关,最终一定能收敛到一致状态
  • 非常适合分布式、实时协作、离线优先场景

Yjs 正是 CRDT 思想在工程实践中的一次“极致实现”。


二、Yjs 的核心设计理念

1️⃣ 文档(Y.Doc)

Yjs 的一切,都围绕 Y.Doc 展开。

TypeScript
import * as Y from 'yjs'

// 创建一个 Yjs 文档
const ydoc = new Y.Doc()

Y.Doc 是一个共享数据容器,内部可以包含多个共享类型(Shared Types),它们会自动同步、合并和持久化。


2️⃣ 共享类型(Shared Types)

Yjs 将 CRDT 模型暴露为类似原生数据结构的共享类型:

类型说明
Y.Text文本(支持富文本)
Y.Array数组
Y.Map键值映射
Y.Xml类 DOM 结构

示例:Y.Map

TypeScript
const ymap = ydoc.getMap()

ymap.set('keyA', 'valueA')

模拟一个“远端用户”并产生冲突修改:

TypeScript
const ydocRemote = new Y.Doc()
const ymapRemote = ydocRemote.getMap()
ymapRemote.set('keyB', 'valueB')

// 合并远端更新
const update = Y.encodeStateAsUpdate(ydocRemote)
Y.applyUpdate(ydoc, update)

console.log(ymap.toJSON())
// => { keyA: 'valueA', keyB: 'valueB' }

👉 没有冲突、无需锁、无需手写合并逻辑。


三、五分钟上手:打造一个协作式编辑器

Yjs 本身并不提供编辑器,它采用的是 “编辑器绑定”机制。

1️⃣ 选择编辑器:Quill

Bash
npm i quill quill-cursors
npm i yjs y-quill

2️⃣ 绑定编辑器与 Yjs 文档

TypeScript
import * as Y from 'yjs'
import { QuillBinding } from 'y-quill'

// 创建文档
const ydoc = new Y.Doc()

// 定义共享文本
const ytext = ydoc.getText('quill')

// 绑定 Quill 编辑器
const binding = new QuillBinding(ytext, quill)

此时:

  • ytext 是 CRDT 文本结构
  • Quill 的编辑状态 ⇄ Y.Text 自动双向同步
  • 并发编辑自动合并

切换编辑器(如 Monaco、CodeMirror)时,只需替换绑定层即可。


四、连接其他客户端:Provider(提供商)

编辑器现在只能“本地协作”,还无法和其他用户同步。

这一步由 Provider(提供商) 负责。

常见网络提供商

Provider特点
y-webrtc点对点,无需服务器,适合 Demo
y-websocket常规生产方案
y-webxdc / y-dat去中心化
Liveblocks / Tiptap / Y-Sweet商业托管

使用 y-webrtc 示例

TypeScript
import { WebrtcProvider } from 'y-webrtc'

const provider = new WebrtcProvider(
  'quill-demo-room',
  ydoc
)
  • 相同 room-name 的客户端会自动同步
  • Provider 可并行使用,形成冗余链路
  • 切换 Provider 无需改动文档结构

五、感知(Awareness):光标、在线状态、存在感

协同编辑不仅是“内容同步”,还需要协作感知:

  • 谁在线
  • 光标在哪里
  • 当前正在编辑什么

Yjs 提供了一个 轻量级 Awareness CRDT:

  • 不写入文档
  • 不做持久化
  • 用户离线后自动清理
  • 所有官方 Provider 均支持

常见用途:

  • 光标位置
  • 用户名、头像、颜色
  • 选区范围

六、离线支持:y-indexeddb

Yjs 是天然离线优先的。

只需引入 y-indexeddb:

TypeScript
import { IndexeddbPersistence } from 'y-indexeddb'

const ydoc = new Y.Doc()
const persistence = new IndexeddbPersistence('my-room', ydoc)

persistence.once('synced', () => {
  console.log('本地内容已加载')
})

效果:

  • 修改自动写入 IndexedDB
  • 离线可编辑
  • 下次上线仅同步增量
  • 节点之间可“反向修复”丢失数据

配合 Service Worker,甚至可以实现 完全离线可用的协作应用。


七、事务(Transaction):性能与一致性的关键

Yjs 的所有修改都发生在 事务 中。

TypeScript
ydoc.transact(() => {
  ymap.set('food', 'pancake')
  ymap.set('number', 31)
})

好处:

  • 合并多次修改
  • 减少更新广播
  • 减少 observer 触发次数
  • 显著提升性能

事务事件顺序

  1. beforeTransaction
  2. 数据变更
  3. beforeObserverCalls
  4. observe / observeDeep
  5. afterTransaction
  6. update(Provider 广播)

👉 大量修改时,一定要手动包事务。


八、数据建模最佳实践

1️⃣ 一个 YDoc 还是多个?

考虑维度:

  • 数据是否经常一起使用
  • 权限是否不同
  • 是否需要独立历史/撤销
  • 是否需要按需加载

2️⃣ 推荐模式

  • 使用一个顶级 Y.Map('data')
  • 子实体通过 ID 管理
  • 或结构与内容分离(列表 Doc + 内容 Doc)
TypeScript
ydoc.getMap('data').get('page-1')

九、生态系统与语言支持

编辑器支持

  • ProseMirror
  • Tiptap
  • Monaco
  • Quill
  • CodeMirror
  • Remirror

数据库 Provider

  • y-indexeddb
  • y-leveldb
  • y-redis

多语言实现

  • Y-CRDT(Rust) → WASM / Python / Swift / Java
  • Y-Octo(Rust,线程安全)
  • Ycs(C#)

十、为什么选择 Yjs?

✅ 无中心、无限扩展
✅ 极致性能(目前最快的 CRDT 实现)
✅ 网络无关、Provider 可插拔
✅ 离线优先、本地优先
✅ 丰富成熟的生态
✅ 工程实践充分验证


结语

Yjs 并不是一个“编辑器库”,而是一个 协同数据模型的基础设施。

一旦你理解了:

“编辑器只是视图,Yjs 才是状态源”

你就可以用它构建的不只是协同编辑器,而是:

  • 协作白板
  • 多人建模工具
  • 实时表单
  • 去中心化应用
  • 本地优先系统

找个地方开始用 Yjs 吧。你会发现,协同并没有那么复杂。 🚀

标签: CRDT Yjs 协同编辑 多人编辑 实时协作
最后更新:2026年1月10日

cywcd

我始终相信,技术不仅是解决问题的工具,更是推动思维进化和创造价值的方式。从研发到架构,追求极致效能;在随笔中沉淀思考,于 AI 中对话未来。

打赏 点赞
< 上一篇
下一篇 >

文章评论

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
取消回复

cywcd

我始终相信,技术不仅是解决问题的工具,更是推动思维进化和创造价值的方式。从研发到架构,追求极致效能;在随笔中沉淀思考,于 AI 中对话未来。

最新 热点 随机
最新 热点 随机
前端开发 TanStack 化:从“框架思维”到“能力组合”的工程演进 Docker 进阶(七):容器化体系设计总结与生产落地经验复盘 Docker 进阶(六):生产环境中的 Docker 安全、监控与日志体系 Docker 进阶(五):Docker + CI/CD —— 从代码提交到自动部署 Docker 进阶(四):使用 Docker Swarm 与 Kubernetes 实现容器编排 Docker 进阶(三):深入理解镜像层(Layer)与缓存机制
Workbox:可直接用于生产环境的 Service Worker 利器快速构建项目文档网站:主流文档站点工具选型与对比DiceBear:30+ 风格、完全可定制的开源头像生成解决方案ES2015 → ES2025:JavaScript 十年演进全景回顾与核心 API 总结ECMAScript 2025(ES16)深度解析20 个现代 JavaScript API 深度盘点
DApp开发前端技术全解析:技术选型、功能实现与开发步骤 jquery.chosen下拉框多选插件使用详解 🔥 Nitro v3:全栈开发的新选择,与 Vite 的完美融合 Three.js 3D 可视化项目实战:从快速启动到性能优化全攻略 JS判断移动设备浏览器信息 JWT 认证:从原理到前后端实战的最佳实践
最近评论
渔夫 发布于 3 个月前(11月05日) 学到了,感谢博主分享
沙拉小王子 发布于 8 年前(11月30日) 适合vue入门者学习,赞一个
沙拉小王子 发布于 8 年前(11月30日) 适合vue入门者学习,赞一个
cywcd 发布于 9 年前(04月27日) 请参考一下这篇文章http://www.jianshu.com/p/fa4460e75cd8
cywcd 发布于 9 年前(04月27日) 请参考一下这篇文章http://www.jianshu.com/p/fa4460e75cd8

COPYRIGHT © 2025 蓝戒博客_智构苍穹-专注于大前端领域技术生态. ALL RIGHTS RESERVED.

京ICP备12026697号-2