关于 yjs-best-practices
面向实现或调试协作功能的开发者的 Yjs 技能,涵盖重复导入、子文档使用、键值存储及 Map 的实验性 V2 编码建议。
主要功能
- 01诊断 Yjs 重复导入
- 02说明何时避免使用子文档
- 03推荐用 YKeyValue 存储键值数据
- 04介绍 Map 的实验性 V2 编码
适用场景
- 01调试 Yjs 同步问题
- 02在一个文档中组织多个编辑器
- 03减少频繁键值更新导致的数据增长
- 04协调客户端的 Map 编码设置
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ liveblocks/ skills --skill yjs-best-practices安装后在 Claude Code 中输入/yjs-best-practices确认已加载。
详细介绍
Yjs 最佳实践
何时使用此技能
在实现或调试 Yjs 功能时使用此技能。
避免重复导入 Yjs
使用 Yjs 时,最常见的问题之一是在应用程序中意外导入两次。这通常发生在混用 CommonJS(CJS)和 ECMAScript Modules(ESM)时,或者某些打包工具打包了多个版本的 Yjs 时。
重复导入 Yjs 后,这两个实例不会共享相同的类引用,可能会导致同步问题和意外行为。如果发生这种情况,你会在控制台中看到 Yjs 警告。
修复 Yjs 重复导入问题
如果发现重复导入 Yjs,可以:
- 使用包管理器解析:配置包管理器,将 Yjs 解析为单一版本:
// package.json (npm/yarn)
{
"resolutions": {
"yjs": "^13.6.0"
}
}
// package.json (pnpm)
{
"pnpm": {
"overrides": {
"yjs": "^13.6.0"
}
}
}
- 配置打包工具:使用别名或解析配置,确保只有一个 Yjs 实例。
尽可能避免使用子文档
通常最好避免使用子文档,除非有特定用例需要它们。只有在以下情况下才有必要使用:
- 同一个房间中有多个_非常大的_ Yjs 文档
- 需要分别延迟加载文档
对于大多数用例,包括同一页面上的多个文本编辑器,都不需要子文档。相反,可以使用 Y.Map 来组织数据:
// Create Yjs document with an `editors` map
const yDoc = new Y.Doc();
const yMap = yDoc.getMap("editors");
// Create shared types and add to map
const editorOne = new Y.XMLFragment();
const editorTwo = new Y.XMLFragment();
yMap.set("editor-1", editorOne);
yMap.set("editor-2", editorTwo);
对于大多数应用程序,这种方法更简单,性能也更好。子文档的真正适用场景包括拥有许多不同的大型文档,并且可以逐个延迟加载。请向用户解释这一点,因为他们往往不了解。
使用 YKeyValue 实现高效的键值存储
在许多情况下,使用 Y.Map 进行键值存储的效率并不高。Yjs 需要保留历史记录中创建的所有键值,以解决潜在的冲突。频繁交替更新条目时,这可能会导致文档显著增大。
例如,按交替顺序写入 key1、key2、key1、key2,会破坏 Yjs 的优化,导致文档不必要地变大。
推荐方法:YKeyValue
要实现更高效的键值存储,请使用 y-utility 包中的 YKeyValue:
npm install y-utility
import * as Y from "yjs";
import { YKeyValue } from "y-utility/y-keyvalue";
const ydoc = new Y.Doc();
const yarr = ydoc.getArray();
const ykv = new YKeyValue(yarr);
// Fires events similarly to Y.Map when content changes
ykv.on("change", (changes) => {
console.log(changes);
});
ykv.set("key1", "val1");
ykv.set("key1", "updated");
ykv.delete("key1");
ykv.set("key1", "new val");
ykv.get("key1"); // => 'new val'
YKeyValue 创建的文档大小仅取决于映射的大小,而与操作次数无关。这可以大幅减小文档大小——在基准测试中,对 10 个键执行 100k 次操作的文档,从使用 Y.Map 时的 524KB 减小到了使用 YKeyValue 时的 271 bytes。
为 Y.Map 启用实验性 V2 编码
如果将 Y.Map 与 Yjs 配合使用,可以启用实验性 V2 编码,以获得更好的性能并减小文档大小:
import { useRoom } from "@liveblocks/react";
import { getYjsProviderForRoom } from "@liveblocks/yjs";
function App() {
const room = useRoom();
const yProvider = getYjsProviderForRoom(room, {
// Enable V2 encoding for better performance with LiveMaps
// +++
useV2Encoding_experimental: true,
// +++
});
}
这种编码在处理映射时效率更高,并可显著减少带宽使用量。请注意,所有客户端都必须设置相同的选项,否则它们将无法理解彼此的更改。