mcpField
Y
yjs-best-practices

yjs-best-practices

github.com/liveblocks开发9315 次安装20 周前更新
代码仓库

关于 yjs-best-practices

面向实现或调试协作功能的开发者的 Yjs 技能,涵盖重复导入、子文档使用、键值存储及 Map 的实验性 V2 编码建议。

主要功能

  1. 01诊断 Yjs 重复导入
  2. 02说明何时避免使用子文档
  3. 03推荐用 YKeyValue 存储键值数据
  4. 04介绍 Map 的实验性 V2 编码

适用场景

  1. 01调试 Yjs 同步问题
  2. 02在一个文档中组织多个编辑器
  3. 03减少频繁键值更新导致的数据增长
  4. 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,可以:

  1. 使用包管理器解析:配置包管理器,将 Yjs 解析为单一版本:
// package.json (npm/yarn)
{
  "resolutions": {
    "yjs": "^13.6.0"
  }
}
// package.json (pnpm)
{
  "pnpm": {
    "overrides": {
      "yjs": "^13.6.0"
    }
  }
}
  1. 配置打包工具:使用别名或解析配置,确保只有一个 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,
    // +++
  });
}

这种编码在处理映射时效率更高,并可显著减少带宽使用量。请注意,所有客户端都必须设置相同的选项,否则它们将无法理解彼此的更改。

评论

支持 Markdown