ブログ
Laravelフロントエンド(Blade、Livewire、Inertia.js)の比較
LaravelはフルスタックのWebアプリケーションフレームワークであり、フロントエンドの実装方法にも複数の選択肢があります。今回は公式ページにも記載されているBlade、Inertia.js(以降、Inertia)、Livewireでアプリを作成し、実装方法や機能の違いを比較しました。
目次
比較環境
今回使用した言語、実行環境、パッケージは以下のとおりです。 InertiaはVue.jsと組み合わせて使用しました。
実行環境はDocker Composeで構築し、app、node、dbの3サービスで構成しています。
| 項目 | バージョン/構成 |
|---|---|
| PHP | 8.3(Apacheイメージ) |
| Node.js | 22 Alpine |
| MySQL | 8.4 |
Composerパッケージ
| 項目 | バージョン/構成 |
|---|---|
| Laravel | 12.65.0 |
| Inertia Laravel Adapter | 2.0.25 |
| Livewire | 3.8.3 |
| Livewire Volt | 1.11.2 |
npmパッケージ
| 項目 | バージョン/構成 |
|---|---|
| @inertiajs/vue3 | 2.3.27 |
| Vue | 3.5.41 |
アプリの機能
簡単なCRUD操作が行える1画面のTODOアプリを作りました。 比較のため実用上はやや不自然な機能も含みますが、タスクに対する以下の機能をそれぞれの方法で実装しました。
- 登録(タイトル、説明)
- タスク入力時の文字数カウント
- 完了状態の編集
- 削除
- ページネーション(5件/ページ)
- 検索(タイトルの部分一致検索、完了状態の絞り込み)
アプリのイメージ

各実装の概要と比較
ここからは実装に関する違いをピックアップしてお伝えします。
Blade
ファイル構成
src/
├─ app/
│ └─ Http/
│ └─ Controllers/
│ └─ BladeTaskController.php # 一覧表示・登録・完了切替・削除
├─ resources/
│ └─ views/
│ ├─ comparison/
│ │ └─ blade.blade.php # Blade版の画面(登録・検索フォーム)
│ └─ components/
│ ├─ layouts/
│ │ └─ comparison.blade.php # 比較画面共通レイアウト
│ ├─ task-list.blade.php # タスク一覧・完了切替・削除
│ └─ task-pagination.blade.php # ページネーション
└─ routes/
└─ web.php # Blade用ルート定義概要
BladeはLaravelのコア機能として組み込まれており、追加設定なしで使用可能です。@if、@foreachといった制御構文や、@authなどLaravelの認証状態をチェックするディレクティブが用意されており、素早くページを作ることができます。サーバー側でHTMLを生成するため、検索エンジンが内容を取得しやすい一方で、リアルタイムバリデーションなどのリアクティブな機能を実装する場合はJavaScriptを組み合わせる必要があります。
Inertia
ファイル構成
src/
├─ app/
│ └─ Http/
│ ├─ Controllers/
│ │ └─ InertiaTaskController.php # 一覧表示・登録・完了切替・削除
│ └─ Middleware/
│ └─ HandleInertiaRequests.php # ルートHTML・共有props(フラッシュなど)
├─ resources/
│ ├─ js/
│ │ ├─ app.js # Inertia + Vue の起動
│ │ ├─ Components/
│ │ │ └─ TaskListCard.vue # タスク一覧・ページネーション
│ │ └─ Pages/
│ │ └─ Comparison/
│ │ └─ Inertia.vue # Inertia版の画面(登録・検索・通信)
│ └─ views/
│ └─ app.blade.php # Vueのマウント先となるルートHTML
├─ routes/
│ └─ web.php # Inertia用ルート定義
└─ vite.config.js # Vueプラグインなどフロントのビルド設定概要
比較環境に記載のとおり、バックエンドとフロントエンドの両方にパッケージの導入と設定が必要です(詳細は公式ページ参照)。
一般的なSPAの構成では、アプリ側でルーティングを行い、バックエンドAPIを呼び出してデータを連携します。一方、InertiaではLaravel側でルーティングを行い、Controllerから渡すデータ、errors、フラッシュメッセージなどをフロントエンドでpropsとして受け取れるため、独立したAPIを用意する手間を省けます。
Controller側は、view()をInertia::render()に置き換えることでデータをpropsとして渡す形に変更できます。ただし、画面側はBladeテンプレートからVueコンポーネントへの書き換えが必要です。
フロントエンドに状態を持ち、DOMの一部を更新できるため、動的で複雑な要件に対応しやすく、UXの向上も図りやすくなります。また、npmのエコシステムが充実しているため、ツールやライブラリの選択肢が多いことも利点です。
Livewire
ファイル構成
src/
├─ app/
│ └─ Livewire/
│ ├─ TaskManager.php # 登録・検索の状態と処理(親コンポーネント)
│ └─ TaskList.php # 一覧・完了切替・削除・ページネーション(子)
├─ resources/
│ └─ views/
│ ├─ comparison/
│ │ └─ livewire.blade.php # Livewire版のページ(コンポーネントを埋め込み)
│ ├─ livewire/
│ │ ├─ task-manager.blade.php # 登録・検索フォーム(TaskManagerのView)
│ │ └─ task-list.blade.php # タスク一覧(TaskListのView)
│ └─ components/
│ ├─ layouts/
│ │ └─ comparison.blade.php # 比較画面共通レイアウト
│ └─ task-pagination.blade.php # ページネーション(wire:clickで切替)
└─ routes/
└─ web.php # Livewire用ルート定義概要
Livewireは、即時フィードバックや部分的なDOM更新などのリアクティブな機能をPHP中心で実現できます。
BladeやInertiaではControllerからViewへデータを渡しますが、Livewireでは、状態と処理を受け持つサーバー側のコンポーネントと、画面描画を担当するView側のコンポーネントをセットで使用します。両者はLivewire独自のwire:ディレクティブによって紐づけます。 また、wire:modelは修飾子を使用して同期のタイミングを調整できます。
ただし、npmのエコシステムと比べると利用できる選択肢が限られるため、標準機能で対応できない要件では解決策を探すのに時間がかかる可能性があります。
wire構文の一部
| 構文 | 内容 |
|---|---|
| wire:click | クリック時に呼び出すサーバー側のメソッドを指定可能 |
| wire:submit | フォーム送信時のサーバー側のメソッドを指定可能(ページ移動しない非同期の処理) |
| wire:loading | サーバーからの応答待ちの状態 |
wire:modelの修飾子の一部
| 修飾子 | 内容 |
|---|---|
| .live | ユーザーの入力中にリアルタイム更新 |
| .blur | 入力欄からフォーカスアウトした際に更新 |
| .debounce.[時間]ms | 指定したミリ秒のデバウンスで更新(例:`.debounce.500ms`) |
Livewire Voltについて
Livewireはサーバー側のコンポーネントとViewをセットで使用しますが、これらを1つのファイルにまとめられるLivewire Voltという仕組みもあります。1ファイルに状態、処理、Viewをまとめる構成はReactやVue.jsの単一ファイルコンポーネントに近く、フロントエンドフレームワークに慣れた人にはわかりやすいかもしれません。
src/
├─ app/
│ └─ Providers/
│ └─ VoltServiceProvider.php # Voltコンポーネントの探索パスを登録
├─ resources/
│ └─ views/
│ ├─ livewire/
│ │ └─ volt-task-manager.blade.php # 状態・処理・画面を1ファイルにまとめた実装
│ └─ components/
│ ├─ layouts/
│ │ └─ comparison.blade.php # 比較画面共通レイアウト
│ └─ task-pagination.blade.php # ページネーション(wire:clickで切替)
└─ routes/
└─ web.php # Volt::route によるルート定義アプリ動作の比較
以降は、VoltをLivewireの実装バリエーションとして扱い、Blade、Inertia、Livewireの3方式を比較します。いずれも同じ画面と機能を実装していますが、内部の処理は異なります。特に違いがわかりやすい、バックエンドとの通信とレンダリングに着目して確認しました。
レンダリング範囲の確認には、Chrome DevToolsのペイント点滅機能を使用しました。F12で開発者ツールを表示し、Ctrl+Shift+Pでコマンドパレットを開きます。「レンダリングを表示」からレンダリングタブを開き、「ペイント点滅」をチェックすると、再描画された領域をハイライトできます。

検索の比較
| 比較項目 | Blade | Inertia | Livewire |
|---|---|---|---|
| 発火条件 | 検索ボタン押下 | デバウンス | デバウンス |
| 通信 | 同期 | 非同期 | 非同期 |
| 描画範囲 | ページ全体 | ページ内の一部 | ページ内の一部 |
Bladeのみではリアクティブな処理を実装できないため、ユーザーによるフォーム送信が必要です。また、検索結果として更新したいのはタスクリストだけですが、ページ全体のデータを再取得して表示し直す必要があります。
InertiaとLivewireはユーザーの入力を監視し、デバウンスによって非同期通信を行います。取得したデータでタスクリスト部分のみを更新するためページ全体のちらつきがなく、入力に応じて検索結果が自然に更新されます。Livewireは簡単な記述だけでJavaScriptを使った場合と同様の動きを実現できることに驚きました。



タスク入力時のリアルタイム文字数カウントの比較
| 比較項目 | Blade | Inertia | Livewire |
|---|---|---|---|
| 文字数カウントの実現 | Bladeのみでは不可 | 可能 | 可能 |
| 状態・処理の場所 | – | フロントエンド | バックエンド |
Bladeでユーザーの入力文字数をリアルタイムに数える場合は、JavaScriptを組み合わせる必要があります。InertiaとLivewireはいずれも実装可能ですが、Inertiaはフロントエンドだけで処理するのに対し、今回のLivewire実装では入力内容をバックエンドへ同期するため、サーバーとの通信が生じます。通信速度やサーバーの処理時間によっては、Inertiaに比べてわずかな遅延を感じる場合があります。
タスクの登録・削除など、もともとサーバーとの通信が必要な処理では、InertiaとLivewireに見た目上の大きな違いは感じられませんでした。一方、フロントエンドだけで完結する状態の更新、表示コンポーネントの切り替え、リアルタイムバリデーションなどを実装する場合は、Inertiaのほうが適していると感じました。


比較してみた感想とまとめ
BladeはLaravel標準のテンプレートエンジンであり、便利なディレクティブも用意されています。Bladeだけで要件を満たせるのであれば、最も早く、簡単に実装できると思います。リアクティブな要件が加わった場合は、JavaScriptを組み合わせるか、今回比較したInertiaまたはLivewireの導入を検討することになります。今回のTODOアプリを実装した範囲では、Inertiaのほうが要件に適していると感じました。
Inertiaの特徴
- Laravel側の処理とVue.js側の画面・状態管理を、役割ごとに分けて実装できる。
- View側はVue.jsように書き換える必要があるが、Controller側はBladeから移行しやすい。
- ページ全体の再読み込みを抑え、滑らかな操作感を実現しやすい。
- 画面の要件が複雑な場合でも、Vue.jsやnpmのエコシステムが充実しているため解決手段が豊富。
- ただしフロントエンドフレームワークのキャッチアップが必要。
Livewireの特徴
- サーバー側の状態・処理とViewをLivewireコンポーネントとしてセットで扱う。
- Controller、Viewに当たる部分はLivewire専用のコンポーネントに書き換える必要がある。
- 登録、削除などサーバー処理が必要な機能も少ない記述でリアクティブにできるが、使い方によっては頻繁なサーバーリクエストが発生し、遅延を感じる場合がある。
- npmのエコシステムと比べると選択肢が限られ、要件によっては解決策を探すのに時間がかかる可能性がある。
Livewireはサーバー主導でUIを更新する仕組みであり、クライアント側で状態を管理するVue.jsとは設計思想が異なります。そのため、フロントエンドだけで完結する頻繁な状態更新では、Vue.jsを利用するInertiaのほうが適しています。一方、次のようなケースではLivewireが有力な選択肢になると考えます。
- バックエンドのみの経験者が多いプロジェクト
- 規模が小さくスケール予定もない社内用プロジェクトや管理用サイト
- もともと高いリアクティブ性を求められていないサイト
いずれの方法にも長所と短所があります。今後も継続して情報を収集し、プロジェクトごとに採用可否を判断していきたいと思います。
株式会社ウイングドアは福岡のシステム開発会社です。
現在、私達と一緒に"楽しく仕事が出来る仲間"として、新卒・中途採用を絶賛募集しています!
ウイングドアの仲間達となら楽しく仕事できるかも?と興味をもった方、
お気軽にお問い合わせ下さい!