Offline Mode
すべての plasma アプリは、mutation が IDB から即座に返り、sync ループがバックグラウンドで起こるという意味で offline-first です。しかし plasma には より オフラインにしたいときのための追加のノブが 2 つあります:
PlasmaClientOptions.offline: true— ネットワークを完全にスキップします。plasma sync サーバーがまったく存在しない React Native、Tauri、Electron、エアギャップ環境に便利です。TableOptions.changeLogSuppressed: true— table ごとに sync ループをオプトアウトします。ブラウザを決して離れないローカル専用のキャッシュ table です。
これらは自由に組み合わせられます。
offline: true — クライアント全体
Section titled “offline: true — クライアント全体”const plasma = createPlasmaClient({ schema, mutators, dbName: "notes", endpoint: "/sync", // 依然として必須(ダミー値でよい) clientGroupID: "user-42", schemaVersion: "notes-v1", getContext: async () => ({ userId: "u1" }),
offline: true,})設定すると:
client.start()はポーリングタイマー /onlineリスナー / WebSocket サブスクリプションを開きません。client.pushOnce()とclient.pullOnce()は no-op です(HTTP 呼び出しなしで即座に解決します)。- blob アップロードは実行されません。
client.readFile(ref)は_plasma_blobs_localからのみ提供します; 本来なら blob をlocal→readyに遷移させるアップロードはlocalのままです。 - outbox は依然として蓄積します。 mutation は通常どおりエンキューされます。
offlineを(クライアントを再構築して)falseに戻すと、outbox は通常の push パスを通じてフラッシュします。
resetLocalState の拒否
Section titled “resetLocalState の拒否”オフラインモードでの client.resetLocalState() は throw します:
plasma: resetLocalState() is not supported when PlasmaClientOptions.offline is true — the local state cannot be re-hydrated from the server and the offline outbox would be lost.
オフラインアプリには再ハイドレートするサーバーがありません。ローカル状態を消去すると、戻る手段なしにすべての未フラッシュの mutation を破壊します。本当に必要なら、まずオンラインに切り替え、クライアントを再構築し、そこでリセットしてください。
changeLogSuppressed — table ごと
Section titled “changeLogSuppressed — table ごと”一部の table はクライアントのみに属します。セッションドラフト、タブごとのキャッシュ、リロードを生き延びるべきだがサーバーには決して sync すべきでない一時的なフィルタ状態です:
const drafts = table("drafts", { id: id(), snapshot: text(), updatedAt: int(),}, { changeLogSuppressed: true,})
const schema = defineSchema({ todos, // synced(デフォルト) drafts, // ローカル専用})サーバー側への効果:
ensureSchema/runMigrationsは suppressed table の AFTER-write トリガーをスキップします。draftsへの生ドライバ書き込みは_plasma_changes行を生成しません。- pull レスポンスは suppressed table の変更を決して含みません。
クライアント側への効果:
rebuildOptimisticはユーザー可視ストアをクリアするとき suppressed table をスキップします。ローカル専用の行は pull をまたいで保持されます。runMutateは mutator がどの table を触ったかを検査します(新しいengine.recordTouchedTableshook 経由)。触ったすべての table が suppressed なら、outbox エントリは完全にスキップされます — その mutation に対して push は決して出ていきません。
offline + changeLogSuppressed の組み合わせ
Section titled “offline + changeLogSuppressed の組み合わせ”これらは一緒に機能します。Tauri アプリはクライアント全体に offline: true を使い、いくつかの table には「内部の change log ですら不要な帳簿付け」として changeLogSuppressed: true を使うかもしれません:
- すべての書き込みはローカル IDB 書き込みです。
- 非 suppressed table は依然として
_plasma_changesトリガーを埋めます(後でオンラインに切り替えたくなった場合のため)。 - suppressed table はトリガーもスキップします — 純粋なローカル状態です。
ネットワークが戻ったとき
Section titled “ネットワークが戻ったとき”PlasmaClientOptions.offline は 構築時 のフラグです。v1.0 には client.setOffline(true) のランタイムトグルはありません。
アプリをオフラインからオンラインに遷移させるには:
- オフライン outbox が保持している未フラッシュの状態を保存します(通常は何もありません — plasma がフラッシュしてくれます)。
offline: falseでクライアントを再構築します。client.start()を呼びます。
IDB ストア(base + user ストア + outbox)は dbName でキーが付くため、再構築をまたいで共有されます。オフライン実行のすべての outbox エントリは、最初の push でフラッシュされます。
オフライン vs オンラインの検出
Section titled “オフライン vs オンラインの検出”クライアントは fetch が失敗すると kind: "network" の SyncClientError イベントを発火します。実際には onError を追加してサブスクライブできます:
createPlasmaClient({ ..., onError: (err) => { if (err.kind === "network") { setBanner("offline") } },})
// 次の成功した push/pull でバナーをリセット:組み込みの「今オンライン」イベントはありません — plasma は透過的にリトライします。ブラウザレベルのオンライン/オフライン遷移に反応する必要があれば navigator.onLine を使ってください。
次に読むべきもの
Section titled “次に読むべきもの”- Concepts / Push, Pull, Rebase —
offline: trueのとき sync ループが何をスキップするか - Concepts / Change Log and Cookies —
changeLogSuppressedが無効化するトリガー - Troubleshooting / Sync errors — オフラインモードの失敗のトリアージ