メインコンテンツへスキップ

Documentation Index

Fetch the complete documentation index at: https://kawax.biz/llms.txt

Use this file to discover all available pages before exploring further.

Inertia.jsとは

フロントエンドをReactやVueで作りたい。でもAPIを別途設計・実装・管理するのは避けたい——そんなジレンマを解決するのが Inertia.js です。 Inertia はサーバーサイドのルーティングとコントローラーをそのままに、フロントエンドだけをReact・Vue・Svelteで書けるようにする「グルー(接着剤)」です。フレームワークではなく、既存のLaravelとJavaScriptフレームワークをつなぐアダプター層として機能します。
現在の最新バージョンはInertia v3(2026年3月26日リリース)です。Laravel 13のスターターキット(React・Vue・Svelte)はInertia対応済みです。

従来のSPA・MPAとの違い

アーキテクチャ特徴課題
MPA(従来のBladeアプリ)シンプル、Laravelとの統合が容易ページ遷移のたびにフルリロード
SPA(API + フロントエンド分離)高いインタラクション性API設計・認証・型定義の二重管理
Inertia(モダンモノリス)SPAのUX + サーバー側のシンプルさ独自の学習コストがある
Inertia を使うと、Laravelのコントローラーから直接VueコンポーネントやReactコンポーネントにデータを渡せます。REST APIを定義する必要はなく、ページ遷移もブラウザのフルリロードではなくXHRで行われるため、SPA的なスムーズな操作感を実現できます。

Laravelスターターキットとの関係

laravel new でプロジェクトを作成する際にReact・Vue・Svelteを選ぶと、Inertiaが自動的にセットアップされます。
laravel new my-app
# 対話式プロンプトでReact / Vue / Svelteを選ぶとInertia構成になる
スターターキットでは以下の構成が自動で用意されます。
  • inertiajs/inertia-laravel(サーバーサイドアダプター)
  • @inertiajs/react / @inertiajs/vue3 / @inertiajs/svelte(クライアントアダプター)
  • HandleInertiaRequests ミドルウェア
  • ログイン・登録・パスワードリセットなどの認証画面(すでにInertiaコンポーネントで実装済み)
既存プロジェクトに手動でInertiaを導入する場合はサーバーサイドとクライアントサイドを別々にインストールします。詳細は公式ドキュメントのインストール手順を参照してください。

Inertia::render() の基本

Laravelのコントローラーから Inertia レスポンスを返すには Inertia::render() を使います。第一引数にJavaScriptコンポーネント名、第二引数にプロップとして渡すデータを指定します。
use Inertia\Inertia;

class PostController extends Controller
{
    public function index()
    {
        return Inertia::render('Posts/Index', [
            'posts' => Post::latest()->paginate(10),
        ]);
    }

    public function show(Post $post)
    {
        return Inertia::render('Posts/Show', [
            'post' => $post->only('id', 'title', 'content', 'created_at'),
            'author' => $post->user->only('id', 'name'),
        ]);
    }
}
Inertia::render() の代わりに inertia() ヘルパー関数も使えます。どちらを使うかはチームのスタイルで統一してください。
コンポーネント名 'Posts/Index' はファイルパスに対応します。Reactなら resources/js/Pages/Posts/Index.jsx、Vueなら resources/js/Pages/Posts/Index.vue が対応するコンポーネントです。

ページコンポーネントの構造

Inertiaのページコンポーネントは通常のVue/Reactコンポーネントです。コントローラーから渡したデータがプロップとして受け取れます。
React
// resources/js/Pages/Posts/Index.jsx
import { Link } from '@inertiajs/react'

export default function PostsIndex({ posts }) {
    return (
        <div>
            <h1>投稿一覧</h1>
            {posts.data.map(post => (
                <article key={post.id}>
                    <h2>
                        <Link href={`/posts/${post.id}`}>{post.title}</Link>
                    </h2>
                </article>
            ))}
        </div>
    )
}
Vue
<!-- resources/js/Pages/Posts/Index.vue -->
<script setup>
import { Link } from '@inertiajs/vue3'

defineProps({
    posts: Object,
})
</script>

<template>
    <div>
        <h1>投稿一覧</h1>
        <article v-for="post in posts.data" :key="post.id">
            <h2>
                <Link :href="`/posts/${post.id}`">{{ post.title }}</Link>
            </h2>
        </article>
    </div>
</template>
<Link> コンポーネントを使うと、ページ遷移がXHRで行われ、フルページリロードを回避できます。通常の <a> タグとまったく同じように書けますが、裏側でInertiaがページコンポーネントだけを差し替えます。

共有データ — HandleInertiaRequests ミドルウェア

すべてのページで共通して必要なデータ(ログイン中のユーザー情報・フラッシュメッセージなど)は、HandleInertiaRequests ミドルウェアの share() メソッドで定義します。
// app/Http/Middleware/HandleInertiaRequests.php
use Illuminate\Http\Request;
use Inertia\Middleware;

class HandleInertiaRequests extends Middleware
{
    public function share(Request $request): array
    {
        return array_merge(parent::share($request), [
            'appName' => config('app.name'),

            'auth' => [
                'user' => $request->user()
                    ? $request->user()->only('id', 'name', 'email')
                    : null,
            ],

            'flash' => [
                'success' => $request->session()->get('success'),
                'error' => $request->session()->get('error'),
            ],
        ]);
    }
}
共有データは自動的にすべてのページのプロップにマージされます。
React
// レイアウトコンポーネントからアクセスする例
import { usePage } from '@inertiajs/react'

export default function Layout({ children }) {
    const { auth, flash } = usePage().props

    return (
        <main>
            <header>
                {auth.user ? `ログイン中: ${auth.user.name}` : 'ゲスト'}
            </header>
            {flash.success && <div className="alert-success">{flash.success}</div>}
            <article>{children}</article>
        </main>
    )
}
共有データはすべてのリクエストに含まれるため、必要最低限のデータに絞ることを推奨します。fn() を使ったレイジー評価にすると、実際に必要なリクエストでのみ評価されます。

フォーム送信とバリデーションエラーの処理

Inertiaでのフォーム処理はLaravelのバリデーションと自然に統合されます。useForm() ヘルパーを使うと、フォームの状態管理・送信・エラー表示がシンプルに実装できます。

コントローラー側

class PostController extends Controller
{
    public function store(Request $request)
    {
        $validated = $request->validate([
            'title'   => ['required', 'string', 'max:255'],
            'content' => ['required', 'string'],
        ]);

        Post::create($validated + ['user_id' => auth()->id()]);

        return redirect()->route('posts.index')
            ->with('success', '投稿を作成しました。');
    }
}
バリデーションエラーが発生した場合、Laravelは自動的にフォームページにリダイレクトし、エラー情報をセッションに保存します。Inertiaはこれを自動的に検知して errors プロップとしてページに渡します。

フロントエンド側

React
// resources/js/Pages/Posts/Create.jsx
import { useForm } from '@inertiajs/react'

export default function PostsCreate() {
    const { data, setData, post, processing, errors } = useForm({
        title: '',
        content: '',
    })

    function handleSubmit(e) {
        e.preventDefault()
        post('/posts')
    }

    return (
        <form onSubmit={handleSubmit}>
            <div>
                <label>タイトル</label>
                <input
                    value={data.title}
                    onChange={e => setData('title', e.target.value)}
                />
                {errors.title && <p className="error">{errors.title}</p>}
            </div>

            <div>
                <label>本文</label>
                <textarea
                    value={data.content}
                    onChange={e => setData('content', e.target.value)}
                />
                {errors.content && <p className="error">{errors.content}</p>}
            </div>

            <button type="submit" disabled={processing}>
                {processing ? '送信中...' : '投稿する'}
            </button>
        </form>
    )
}
Vue
<!-- resources/js/Pages/Posts/Create.vue -->
<script setup>
import { useForm } from '@inertiajs/vue3'

const form = useForm({
    title: '',
    content: '',
})

function submit() {
    form.post('/posts')
}
</script>

<template>
    <form @submit.prevent="submit">
        <div>
            <label>タイトル</label>
            <input v-model="form.title" />
            <p v-if="form.errors.title" class="error">{{ form.errors.title }}</p>
        </div>

        <div>
            <label>本文</label>
            <textarea v-model="form.content"></textarea>
            <p v-if="form.errors.content" class="error">{{ form.errors.content }}</p>
        </div>

        <button type="submit" :disabled="form.processing">
            {{ form.processing ? '送信中...' : '投稿する' }}
        </button>
    </form>
</template>
バリデーションエラーが返ったとき、useForm() は入力内容を保持したままエラーを表示します。フォームを再入力させる手間がなく、ユーザー体験が向上します。

向いているユースケース・向いていないケース

Inertiaが向いているケース

  • Laravelをよく知っているチームがSPA的なUIを作りたいとき
  • 認証・認可・バリデーションをLaravel側で一元管理したいとき
  • 管理画面・社内ツールなど、SEOの優先度が低いアプリ
  • APIを別途設計・管理するコストを避けたいプロジェクト

向いていないケース

  • 外部の複数クライアント(モバイルアプリなど)が同じAPIを使う場合
  • SEOが非常に重要なコンテンツサイト(SSRで対応可能だが複雑になる)
  • マイクロフロントエンド構成など、フロントエンドが完全に独立したチームで開発される場合
Inertia はサーバーサイドレンダリング(SSR)もサポートしています。SEOが必要なページがある場合は SSR オプションを検討してください。Laravel のスターターキットでも SSR 設定が組み込まれています。

Inertia v3 の主な変更点

Inertia v3 は2026年3月26日にリリースされました。v2からの主な変更点を紹介します。

Axios を廃止 — 軽量な組み込みXHRクライアントへ

v3 では Axios が廃止され、より軽量な組み込みXHRクライアントに置き換えられました。ほとんどのアプリケーションでコード変更は不要です。Axios のインターセプターは組み込みインターセプターに直接移行できます。引き続き Axios を使いたい場合は Axios アダプター経由で利用できます。

@inertiajs/vite プラグインによるSSRのシンプル化

新しい Vite プラグインを導入すると、ページコンポーネントの自動解決とSSR設定が大幅に簡略化されます。開発中のSSRは npm run dev を実行するだけで動作するようになり、別途Nodeサーバーを起動する必要がなくなりました。
npm install @inertiajs/vite@^3.0

useHttp フック — ページ遷移を伴わないHTTPリクエスト

useHttp フックを使うと、ページ遷移(Inertia visit)を発生させずにサーバーへHTTPリクエストを送れます。モーダルの保存やバックグラウンド処理など、現在のページを維持したまま通信したい場面で役立ちます。

楽観的UI更新(Optimistic Updates)

useForm およびルーターレベルで楽観的な更新がサポートされました。サーバーの応答を待たずにUIを即座に更新し、失敗した場合は自動的にロールバックします。

レイアウトプロップ(Layout Props)

useLayoutProps フックを使うと、ページコンポーネントから永続レイアウトへデータを渡せるようになりました。従来は共有データかページプロップに頼るしかなかった「特定ページのレイアウト状態制御」がシンプルに書けます。

要件の変更

v3 では以下の最低バージョンが引き上げられました。
項目v2v3
PHP8.1+8.2+
Laravel10+11+
React18+19+
Svelte4+5+

Inertia::lazy() の廃止

v2 で非推奨になっていた Inertia::lazy() が v3 で完全に削除されました。代わりに Inertia::optional() を使います。
// v2(非推奨)
'users' => Inertia::lazy(fn () => User::all()),

// v3
'users' => Inertia::optional(fn () => User::all()),

イベント名の変更

v2v3
invalidhttpException
exceptionnetworkError

future オプションの廃止

v2 で実験的オプションとして提供されていた future 設定ブロックが廃止されました。これらのオプションはすべてデフォルトで有効になっています。createInertiaApp の設定から future ブロックを削除してください。
v2 からのアップグレード手順の詳細は 公式アップグレードガイド を参照してください。v2 は2026年9月26日までバグ修正が、2027年3月26日までセキュリティ修正が提供されます。

まとめ

Inertia.js は「LaravelはそのままでフロントエンドをReact/Vueで書きたい」という現実的なニーズに応えるツールです。APIを設計せずに、コントローラーから直接コンポーネントにデータを渡せるシンプルさが最大の強みです。 Laravel 13 のスターターキットが Inertia に対応していることからも、Laravel エコシステムにおける Inertia の位置づけは確立されています。Livewire がPHPだけで動的UIを作るアプローチなら、Inertia はJavaScriptフレームワークのパワーをサーバー側のシンプルさを損なわずに使えるアプローチです。 どちらを選ぶかはチームのスキルセットとプロジェクトの要件次第ですが、「LaravelのコントローラーをそのままにReactで画面を作りたい」という場面では Inertia が最も自然な選択です。

Inertia.js公式ドキュメント

Inertia v3の全機能については公式ドキュメントを参照してください。
Last modified on March 29, 2026