Yjs协同库入门

  目录

Yjs协同库介绍及入门

简介

Yjs是一个基于 ‌CRDT (Conflict-Free Replicated Data Type)‌ 技术的 JavaScript 库,专为构建‌高性能、实时的协同编辑应用‌而设计,例如在线文档编辑器(类似 Google Docs)、设计工具(如 Figma)或多人在线白板‌。它提供了一套核心的‌模块化构建块‌,开发者可以轻松将其集成到现有或新项目中,以实现复杂的多用户实时协作功能‌。

核心特性与优势

‌基于CRDT算法‌:

这是Yjs的核心基础。CRDT 是一种数据结构,确保即使在网络延迟、消息乱序或用户并发编辑的情况下,所有参与者的数据最终都能达成一致状态,无需中心化协调或复杂的冲突解决逻辑‌。
官方测试表明,Yjs 是‌目前性能最高的 CRDT 实现之一‌‌。

‌模块化设计‌:

Yjs本身提供数据结构(如 Y.Array, Y.Map, Y.Text)和协同算法。它不是一个大而全的框架,而是专注于解决协同编辑的底层数据一致性难题‌。
这种设计使其能灵活地与各种‌编辑器框架‌(如 Quill, Monaco, CodeMirror, TipTap, Slate 等)和‌网络传输协议‌(WebSockets, WebRTC, 甚至本地通信或离线存储)集成‌。‌

高性能‌:

优化了操作同步和状态合并的效率,能够处理大量用户的高频编辑操作‌。

离线优先与实时同步‌:

支持用户离线编辑,并在重新上线后自动同步更改‌。
提供近乎实时的协作体验。

丰富的生态系统‌:

提供了官方适配器,简化了与流行编辑器的集成(如 y-quill, y-prosemirror, y-monaco 等)‌。
支持多种网络通信后端(如 y-websocket, y-webrtc)和持久化存储方案(如 y-indexeddb)‌。

Quick Start

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import * as Y from 'yjs'
// Yjs文档是会自动同步的共享对象集合
const ydoc = new Y.Doc()
// 定义一个共享的Y.Map实例
const ymap = ydoc.getMap()
ymap.set('keyA', 'valueA')
// 创建另一个Yjs文档(模拟远程用户)并创建一些冲突的更改
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+quill

创建项目

1
npm create vite@latest

vite对nodejs的版本有要求,根据提示信息切换nodejs版本。
创建项目选择Vanilla

安装依赖包

1
2
3
4
5
6
7
8
npm i --save yjs y-websocket y-quill quill quill-cursors

// 参考依赖包版本
"quill": "^2.0.3",
"quill-cursors": "^4.0.4",
"y-quill": "^1.0.0",
"y-websocket": "2.0.4",
"yjs": "^13.6.27"

修改main.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import Quill from 'quill';
import QuillCursors from 'quill-cursors';
import 'quill/dist/quill.snow.css'; // 使用了 snow 主题色
import * as Y from 'yjs';
import { QuillBinding } from 'y-quill';
import { WebsocketProvider } from 'y-websocket';

const ydoc = new Y.Doc(); // y 文档对象,保存需要共享的数据
const ytext = ydoc.getText('quill'); // 创建名为 quill 的 Text 对象

// 使用 cursors 插件
Quill.register('modules/cursors', QuillCursors);

const quill = new Quill(document.querySelector('#app'), {
modules: {
cursors: true,
toolbar: [
[{ header: [1, 2, false] }],
['bold', 'italic', 'underline'],
['image', 'code-block'],
],
history: {
userOnly: true, // 用户自己实现历史记录
},
},
placeholder: '前端西瓜哥...',
theme: 'snow',
});

// 连接到 websocket 服务端
const provider = new WebsocketProvider('ws://localhost:1234', 'quill-demo-room', ydoc);
// 数据模型绑定,再额外绑上了光标对象
const binding = new QuillBinding(ytext, quill, provider.awareness);

运行项目

启动web前端

1
npm run dev

启动websocket服务端

1
HOST=localhost PORT=1234 npx y-websocket

这句命令要在git bash中执行。
y-websocket这个包使用的是2.0.4版本,新版本的package.json中已经删除了bin的执行命令。

总结

以上对Yjs这个协同编辑库做了简单入门。