オフラインで編集して、後でマージする。聞こえは簡単だが、複数のユーザーが同時に変更すると「どちらの編集を優先するか」という問題が必ず発生する。Loro CRDTはこの競合解消を自動化し、ローカルファーストアプリ開発を大幅にシンプルにするオープンソースライブラリだ。

この記事でわかること:

  • CRDTとは何か、なぜ共同編集に有効なのか
  • Loroが提供する主な機能(タイムトラベル、バージョン管理、P2P同期)
  • Yjs・Automergeとの違い
  • 基本的な使い方

CRDTとは何か、なぜ必要なのか

リアルタイム共同編集アプリを作るとき、最大の壁になるのが「競合」だ。AさんとBさんが同じドキュメントをオフラインで編集し、後でマージしようとすると、どちらの変更を採用すべきかをシステムが判断しなければならない。

従来のアプローチでは中央サーバーがこの裁定を担う。ただしサーバーが落ちると編集できなくなり、オフライン中の変更はサーバー復帰まで保留される。

CRDT(Conflict-free Replicated Data Types)はこの問題を別の方法で解く。データ構造に「どの変更も数学的に矛盾なくマージできる」という性質を持たせることで、サーバーなしでも競合を自動解消できる。

Loroとは

https://github.com/loro-dev/loro

Loroは、CRDTを使ってJSONデータを共同編集・バージョン管理できるオープンソースライブラリだ。Rustで実装されており、JavaScript(WASM経由)・Swift・Pythonのバインディングも提供している。GitHubスター数は5500超で、FOSDEM 2026でも採用事例が発表されるなど実用段階にある。

2026年4月26日にv1.12.0がリリースされた。

主な機能

P2P同期・自動マージ

ピアツーピアで変更を同期し、競合を自動解消する。サーバーが不要なため、ユーザーがオフラインでも編集を続け、オンラインに戻ったタイミングでマージが完了する。

タイムトラベル

Gitのように過去の任意のバージョンへ高速で移動できる。Loroはすべての変更履歴をDAG(有向非巡回グラフ)として保持し、差分を効率よく計算する。

バージョン管理とリアルタイム協調

Gitのブランチモデルに相当する「バージョン管理」と、リアルタイムコラボレーションを両立する。変更をブランチとして分岐させて後でマージするという操作をAPIで直接行える。

対応データ型

テキスト(Fugueアルゴリズム)・リッチテキスト・ツリー構造・リスト・マップを標準でサポートする。テキスト編集には同時編集の割り込みを最小化するFugueアルゴリズムを採用しており、複数ユーザーが同じ箇所を編集しても意図どおりの順序が維持されやすい。

シャロースナップショット

Gitのシャロークローンに相当する機能で、完全な履歴ではなく直近のスナップショットだけを共有できる。古い履歴が不要な場面では同期コストを大幅に削減できる。

v1.12.0の変更点

4月26日リリースのv1.12.0では、インポート処理がアトミックになった。importimport_json_updatesがステート適用に失敗した場合、オプログの変更がロールバックされる。これにより、インポートが途中失敗してもオプログとステートが不整合な状態で残るリスクがなくなった。

エンコーディングパスの堅牢化も行われ、不正な入力に対してパニックではなく適切なエラーを返すようになった。本番環境での予期せぬクラッシュが減少する改善だ。

Yjs・Automergeとの違い

Loro・Yjs・Automergeはいずれもブラウザで使えるCRDTライブラリだが、方向性が異なる。

Yjsは成熟度とエコシステムの広さが強みだ。CodeMirrorやTiptapなどのエディタとの統合が豊富で、既存のWebアプリに組み込む際の選択肢が多い。ただしバージョン管理機能はなく、履歴を保存するには追加のストレージ設計が必要になる。

Automergeも同様にJSONデータモデルを持ち、Rust + WASM構成の点でLoroと似ている。テキスト編集にはRGAアルゴリズムを使う。

Loroの差別化点は、タイムトラベルとバージョン管理を標準搭載している点だ。FOSDEM 2026でSQLRoomsチームがYjsからLoroへ移行した理由として、「読み取り専用データ(DuckDB)と協調状態(CRDT)を分離して管理しやすくなる」点が挙げられている(参考)。

基本的な使い方

npm install loro-crdt
import { LoroDoc } from "loro-crdt";

const docA = new LoroDoc();
const list = docA.getList("list");
list.insert(0, "A");
list.insert(1, "B");

// 変更をバイト列としてエクスポート
const bytes = docA.export({ mode: "update" });

// 別のドキュメントにインポートして同期
const docB = new LoroDoc();
docB.import(bytes);
console.log(docB.toJSON()); // { list: ["A", "B"] }

exportimportだけで複数ドキュメント間の同期が完了する。WebSocketやWebRTCと組み合わせることで、リアルタイム共同編集の基盤を最小限のコードで構築できる。

まとめ

Loroはタイムトラベル・バージョン管理・P2P同期を1つのライブラリで提供する。オフライン対応の共同編集アプリを作る際に、競合解消ロジックをゼロから実装する必要がなくなる。

Yjsと比べてエコシステムはまだ小さいが、Rustベースの高性能実装と豊富な履歴管理機能が強みだ。ローカルファーストアプリの設計を検討しているなら、採用を検討する価値がある。