yjs-best-practices について
共同編集機能の実装やデバッグを行う開発者向けの Yjs スキルです。重複インポート、サブドキュメント、キー・バリュー保存、Map の実験的な V2 エンコーディングを扱います。
主な機能
- 01Yjs の重複インポートを診断
- 02サブドキュメントを避ける場面を説明
- 03キー・バリュー保存に YKeyValue を推奨
- 04Map の実験的な V2 エンコーディングを解説
活用シーン
- 01Yjs の同期問題をデバッグ
- 021つのドキュメントで複数エディターを整理
- 03頻繁なキー・バリュー更新による肥大化を抑制
- 04クライアント間の Map エンコーディング設定を調整
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ liveblocks/ skills --skill yjs-best-practicesインストール後、Claude Code で/yjs-best-practicesを入力して読み込まれたか確認します。
詳細
Yjs のベストプラクティス
このスキルを使うタイミング
Yjs の機能を実装またはデバッグするときに、このスキルを使ってください。
Yjs の二重インポートを避ける
Yjs を扱うときによくある問題の一つは、アプリケーションで誤って Yjs を二重にインポートしてしまうことです。これは、CommonJS(CJS)と ECMAScript Modules(ESM)を混在させた場合や、バンドラーによって複数のバージョンの Yjs がバンドルされた場合によく発生します。
Yjs を二重にインポートすると、2 つのインスタンスでクラス参照が共有されないため、同期の問題や予期しない動作につながる可能性があります。この場合、コンソールに Yjs の警告が表示されます。
Yjs の重複インポートを解消する
Yjs の重複インポートが見つかった場合は、次の方法を使えます。
- パッケージマネージャーの解決設定を使う:Yjs が単一のバージョンに解決されるように、パッケージマネージャーを設定します。
// package.json (npm/yarn)
{
"resolutions": {
"yjs": "^13.6.0"
}
}
// package.json (pnpm)
{
"pnpm": {
"overrides": {
"yjs": "^13.6.0"
}
}
}
- バンドラーを設定する:エイリアスまたは解決設定を使って、Yjs のインスタンスが 1 つだけになるようにします。
可能な限りサブドキュメントを避ける
特定の用途で必要な場合を除き、一般的にはサブドキュメントを避けるのが望ましいです。サブドキュメントが必要なのは、次の場合に限られます。
- 同じルームに非常に大きな 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 個のキーに対する 10 万回の操作を含むドキュメントのサイズが、Y.Map の 524KB から YKeyValue のわずか 271 バイトに削減されました。
Y.Map の実験的な V2 エンコーディングを有効にする
Yjs と組み合わせて Y.Map を使用している場合、パフォーマンスの向上とドキュメントサイズの縮小のために、実験的な 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,
// +++
});
}
このエンコーディングはマップを扱う際により効率的で、帯域幅の使用量を大幅に削減できます。すべてのクライアントで同じオプションを設定する必要があります。設定が異なると、互いの変更を理解できません。