inertia-rails-architecture について
Rails、Inertia.js、Reactで開発するエンジニア向けのアーキテクチャガイドです。ルーティング、データ、認証はRailsが担い、Reactは描画に専念する方針と、よく使うパターンの選択基準を示します。
主な機能
- 01サーバーとクライアントの役割分担
- 02ページデータと状態の選択基準
- 03フォーム、ナビゲーション、更新のパターン
- 04遅延プロパティと無限スクロールの指針
- 05ワークフロー別の関連スキル案内
活用シーン
- 01RailsとInertia.jsのページ設計
- 02状態をサーバーとReactのどちらで管理するかの判断
- 03フォーム送信やページ遷移方式の選択
- 04遅いクエリやスクロールデータの扱い
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ inertia-rails/ skills --skill inertia-rails-architectureインストール後、Claude Code で/inertia-rails-architectureを入力して読み込まれたか確認します。
同梱ファイルreferences/AGENTS.mdreferences/decision-trees.md
詳細
Inertia Rails のアーキテクチャ
ページ、フォーム、ナビゲーション、データの更新を構築する際の、Rails + Inertia.js + React 向けのサーバー駆動型アーキテクチャです。Inertia は従来型の SPA ではありません。ルーティング、データ、認証はサーバーが管理します。React はレンダリングのみを担当します。
コアとなる考え方
真実の情報源はサーバーです。React はデータを props として受け取り、UI をレンダリングします。クライアント側ルーター、グローバル状態ストア、API レイヤーはありません。
機能を構築する前に、次の点を確認してください:
- データはどこから取得しますか? → サーバーからの場合:コントローラーの prop。ユーザー操作の場合:
useState。 - この状態は誰が管理しますか? → URL または DB にある場合:サーバーが管理します(props を使用)。一時的な UI 状態の場合:React が管理します。
- React/SPA のパターンを使おうとしていませんか? → まず以下の判断基準を確認してください。Inertia にはサーバー駆動型の代替手段がある可能性が高いです。
判断基準
| 必要なもの | 解決策 | これは使わない |
|---|---|---|
| サーバーからのページデータ | コントローラーの props | useEffect + fetch |
| グローバルデータ(認証、設定) | inertia_share + usePage() | React Context / Redux |
| フラッシュメッセージ/トースト | Rails flash + usePage().flash | inertia_share / React state |
| フォーム送信 | <Form> コンポーネント | fetch/axios + useState |
| ページ間の移動 | <Link> / router.visit | react-router / window.location |
| 特定のデータの更新 | router.reload({ only: [...] }) | React Query / SWR |
| 処理コストの高いサーバーデータ | InertiaRails.defer | useEffect + ローディング状態 |
| 無限スクロール | InertiaRails.scroll + <InfiniteScroll> | クライアント側のページネーション |
| 参照先が変わらないデータ | InertiaRails.once | React の状態にキャッシュ |
| リアルタイム更新(基本) | ActionCable + router.reload | setInterval によるポーリング |
| シンプルなポーリング(MVP/プロトタイピング) | usePoll(バックグラウンドのタブでは自動的に頻度を下げます) | setInterval + router.reload |
| URL 駆動型の UI 状態(ダイアログ、タブ) | コントローラーが params を読み取り → prop に渡し、router.get で更新 | useEffect + window.location |
| 一時的な UI 状態 | useState / useReducer | サーバー props |
| 外部 API 呼び出し | 専用の API エンドポイント | Inertia props と混在させる |
影響度別ルール
| # | 影響度 | ルール | 理由 |
|---|---|---|---|
| 1 | CRITICAL | ページデータに useEffect+fetch を絶対に使わない | Inertia はナビゲーション時にコンポーネント全体を再レンダリングします。useEffect の fetch は props から乖離する第 2 のデータライフサイクルを作り、古い UI の原因になります |
| 2 | CRITICAL | クライアント側で認証を絶対に確認しない | React の認証状態は偽装できます。実際のゲートとなるのはサーバー側のチェックだけです。クライアント側の「ガード」は誤った安心感を与えます |
| 3 | CRITICAL | fetch/axios ではなく <Form> を使う | <Form> は CSRF、リダイレクトの追跡、エラーのマッピング、ファイルの検出、履歴状態を処理します。fetch はこれらを重複して実装するか、壊してしまいます |
| 4 | HIGH | <a> や window.location ではなく、<Link> と router を使う | <a> はページ全体を再読み込みし、React の状態とレイアウトの永続化をすべて失わせます |
| 5 | HIGH | React Query/SWR ではなく、部分再読み込みを使う | React Query は Inertia のページベースのキャッシュやバージョン管理と競合する第 2 のキャッシュ層を追加します |
| 5b | HIGH | usePoll は MVP に限って使い、本番環境のリアルタイム処理には ActionCable を優先する | usePoll は便利ですが、帯域幅を無駄にします。変更がなくても、間隔ごとにサーバーへアクセスするためです。ActionCable は実際に変更があったときだけプッシュします |
| 6 | HIGH | グローバルデータには React Context ではなく、inertia_share を使う | Context は変更のたびにコンシューマーを再レンダリングします。共有 props はリクエストごとに設定され、部分再読み込みと統合されています |
| 7 | HIGH | 通知には共有 props ではなく、Rails のフラッシュを使う | フラッシュは 1 回のレスポンス後に自動的にクリアされます。共有 props は明示的に変更されるまで保持されるため、古いトーストが表示される原因になります |
| 8 | MEDIUM | 負荷の高いクエリには遅延/オプション props を使う | そうしないと初期レンダリングがブロックされ、遅いクエリが完了するまでユーザーに空白のページが表示されます |
| 9 | MEDIUM | 状態を保持するには永続レイアウトを使う | 永続レイアウトを使わない場合、ナビゲーションのたびにレイアウトが再マウントされ、スクロール位置、音声再生、コンポーネントの状態が失われます |
| 10 | MEDIUM | React コンポーネントはデータ取得ではなく、レンダリングに専念させる | データ取得をコンポーネントに混在させるとテストできなくなり、Inertia のサーバー駆動モデルも損なわれます |
スキルマップ
一般的なワークフローは複数のスキルにまたがります。全体を網羅するには、以下に示すスキルをすべて読み込んでください。
| ワークフロー | 読み込むスキル |
|---|---|
| props を使った新しいページ | inertia-rails-controllers + inertia-rails-pages + inertia-rails-typescript |
| バリデーション付きフォーム | inertia-rails-forms + inertia-rails-controllers |
| shadcn のフォーム入力 | inertia-rails-forms + shadcn-inertia |
| フラッシュトースト | inertia-rails-controllers + inertia-rails-pages + shadcn-inertia |
| 遅延/遅延読み込みデータ | inertia-rails-controllers + inertia-rails-pages |
| URL で制御するダイアログ/タブ | inertia-rails-controllers + inertia-rails-pages |
| Alba のシリアライズ | alba-inertia + inertia-rails-typescript |
| コントローラーのテスト | inertia-rails-testing + inertia-rails-controllers |
参考資料
必須 — 新しい Inertia ページまたは機能を構築する前に、ファイル全体を読んでください。
references/AGENTS.md(約 430 行)— 上記の判断マトリクスにある各パターンのフルスタックの例です。
必須 — どの Inertia パターンを使うべきか判断できない場合は、ファイル全体を読んでください。
references/decision-trees.md(約 70 行)— props の種類、ナビゲーション方法、データ戦略を選ぶためのフローチャートです。
上記の判断マトリクスですでに説明されている単一パターンについての簡単な質問では、参考資料を読み込まないでください。
個別の API が必要な場合
Inertia のリクエストサイクルですべてを処理できるわけではありません。次の場合は、従来の API エンドポイントを使用してください。
| シグナル | 理由 | 例 |
|---|---|---|
| ブラウザー以外の利用者 | Inertia の JSON エンベロープ(component、props、url、version)はフロントエンドアダプター向けに設計されているため、ほかの利用者は使用できません | モバイル API、CLI ツール、決済 Webhook |
| 大規模データセットの検索 | データセットが大きすぎて props として読み込めず、入力のたびにサーバー側でフィルタリングする必要があります。検索には生の fetch を使用し、選択後の副作用は props を介して Inertia に処理させます。 | 市区町村/住所のオートコンプリート、郵便番号検索 |
| バイナリ/ストリーミングレスポンス | Inertia が配信できるのは JSON props のみです。標準のダウンロードレスポンスを返す別のルートを使用してください。 | PDF/CSV のエクスポート、ファイルのダウンロード |