概要
Linear を使い始めたことで、 local-firstアーキテクチャ に興味を持ち、従来のWebアプリ開発の常識が覆された体験。 Jazz や Electric SQL など、最新のlocal-firstツールやエコシステムの現状を調査。 local-first のメリット・課題・適用場面について実体験を交え解説。 今後の local-first の発展性と、開発者体験の変化への期待。 自身の経験や知見を共有し、読者にも新しいアーキテクチャへの挑戦を推奨。
Local-Firstアーキテクチャとの出会い
- Linear は驚くほど高速なプロジェクト管理ツール
- クリックやステータス更新が 即時反映 される体験
- 従来型Webアプリ との違いに困惑
- ネットワーク遅延や競合処理、オフライン対応の疑問
- LiveStore のデモがlocal-firstの理解に最適
技術的な深掘りのきっかけ
- 雨の週末に技術調査へ没頭
- Linearの同期エンジン のリバースエンジニアリング記事
- CTO Tuomas Artmanによるアーキテクチャ解説
- Figma のマルチプレイヤー技術も参考
- IndexedDB を本格的なDBとして活用
- 変更はまずローカルで発生し、GraphQLやWebSocketで同期
- local-first はUX戦略・データ哲学の両面を持つ
- クライアントが自前DBを持ち、サーバーは同期先の一つという発想
従来型 vs local-firstの構造比較
- 従来型 :サーバーが唯一の信頼ソース
- Client → HTTPリクエスト → Server → DB → レスポンス → Client
- local-first型 :各クライアントがほぼ完全なDBを保持
- Client → ローカルDB → UI更新
- ↓(非同期で)
- Syncエンジン → Server → 他クライアント
- ネットワーク遅延排除 による体感速度の向上
実装の難しさと課題
- Linear方式 の模倣は非常に困難
- オフライン/オンライン切替、競合解決、部分同期、スキーマ移行、分散環境でのセキュリティ等の複雑性
- 既存のlocal-firstソリューションの必要性
2025年のLocal-Firstエコシステム
- Electric SQL :Postgresベースの同期エンジン
- PowerSync :エンタープライズ向け
- Jazz :シンプルさで注目
- Replicache :先駆者(サービス終了)
- Zero :Replicacheチームの新アプローチ
- Triplit :TripleStore型同期
- Instant :開発者体験重視
- LiveStore :Electric等のリアクティブレイヤー
Jazzの詳細解説
- Jazz は「ローカル状態の更新と同じくらい簡単にlocal-firstアプリが作れる」と謳う
- Collaborative Values(CoValues) :リアルタイム協調用データ構造
- JazzとZodでスキーマ定義
- 例:
import { co, z } from "jazz-tools"; const ListOfComments = co.list(Comment); export const Post = co.map({ title: z.string(), content: z.string(), comments: ListOfComments, });
- 例:
- 取得・更新はフックで
- 例:
const post = useCoState(Post, postId) const setTitle = (title: string) => { post.title = title // 自動同期 }
- 例:
- APIルートやDTO不要、オブジェクト操作だけで同期
Jazzの内部技術
- 自動一意性 :全データにユニークID付与
- イベントソーシング :全変更をイベントとして保存、差分のみ同期
- エンドツーエンド暗号化 :クライアントで暗号化、サーバーは暗号化データのみ保持
- グループによる権限管理
- 例:
const group = Group.create() group.addMember(alice, 'admin') group.addMember(bob, 'writer') Post.create({ title: "a new post"}, { owner: group });
- 例:
Jazzのトレードオフ
- サーバーはデータ内容を読めない (暗号化のため)
- プライバシー強化だが、モデレーションや不正防止が難しい
- イベントソーシングによる「削除不可」問題
- 全変更履歴が残り、GDPR対応等が課題
- ストレージ消費の増加
- 小規模なら問題なし、大規模SaaSではコスト増
- Passkeys認証のローカル開発時の煩雑さ
- HTTPS必須、証明書管理や外部Auth連携に工夫が必要
- 今後Better Auth統合で改善予定
それでもJazzは魅力的
- 開発体験の生産性・楽しさ
- 早期段階だが今後の成長に期待
Electric SQLとZeroの比較
- Electric SQL/Zero はPostgres等既存DBを活用する漸進的アプローチ
- 例:通常通りPostgresテーブル作成
- Electric はリアクティブクエリで部分同期
- 例:
import { useShape } from '@electric-sql/react' function Component() { const { data } = useShape({ url: `http://localhost:3000/v1/shape`, params: { table: `posts` } }) return (<pre>{ JSON.stringify(data, null, 2) }</pre>) }
- 例:
- LiveStore追加 でJazz並みの生産性も視野
- TanStack DB も候補
- Zero はElectricに近く、直接ミューテーションもサポート
Local-Firstが適する場面・難しい場面
- 最適なケース
- クリエイティブツール(デザイン・執筆・音楽)
- 協調作業アプリやその一部
- オフライン対応必須なモバイルアプリ
- 開発者向けツール
- 個人向け生産性アプリ
- 課題が多いケース
- サーバーサイド業務ロジックが重い場合
- 厳格な監査要件
- 大規模分析処理
- 既存システムとの深い統合
- サーバー側で頻繁にリクエスト拒否が発生する場合(楽観的更新が困難)
今後の展望・まとめ
- local-first はアプリ開発の根本的転換
- ユーザー体験の劇的向上 (Linearが証明)
- アーキテクチャのトレードオフを見極める重要性
- Jazz で個人アプリ開発中、抽象化の「綻び」も注視
- エコシステムはまだ若いが、今後の成熟に期待
- データをローカルに保つことで高速体験 が得られる本質は変わらない
- 新規開発で制約に対応可能なら、 local-firstを試す価値大
- 最悪でも新しい設計思想を学べる、最良ならユーザーに「異次元の速さ」を提供可能
- 体験談やフィードバック歓迎、意見や経験はぜひ共有してほしい