Laravel Turboを使ってみた。(NextJSと比較してみる)
Laravel Turbo がいい感じと聞いたので、使ってみました。
claude codeに指示を出しながら軽く触ってみた感じなので、ブログの全般を書いてもらいました。
最後の個人的な感想部分のみ自分で書いています。

環境
- Laravel 12
- PHP 8.3
- PostgreSQL 16
- Laravel Reverb(WebSocketサーバー)
- Tailwind CSS (CDN)
Node.jsを使わずに、Laravel Turbo Streamsでリアルタイムな画面更新を実現するチャットアプリケーションを作ってみました。
Laravel Turboの実装でやったこと
基本構成
Room(部屋)とMessage(メッセージ)のシンプルなモデル構成で、/room/{id}でアクセスできるチャット機能。
リアルタイム通信の仕組み
Laravel Turbo Streamsと Laravel Reverbを組み合わせて、以下の流れでリアルタイム更新を実現:
- メッセージ送信: フォーム送信でMessageController経由でDBに保存
- ブロードキャスト:
MessageCreatedイベントをWebSocketで配信 - 画面更新: 受信側でTurbo Streamを適用して部分的にDOM更新
// MessageControllerでのブロードキャスト
broadcast(new MessageCreated($message));
// EventクラスでTurbo StreamのHTMLを配信
public function broadcastWith(): array
{
$html = view('rooms._message', ['m' => $this->message])->render();
return ['html' => $html];
}
フロントエンド側では、Pusher.jsを使ってWebSocketを受信し、Turbo.renderStreamMessage()でDOM更新を行います。
つまずいたこと・解決方法
1. Laravel Echoのコンストラクタエラー
最初はLaravel EchoライブラリでWebSocket接続を試みましたが、「Echo is not a constructor」エラーが発生。直接Pusher.jsを使用することで解決しました。
2. Pusherバージョン互換性問題
Pusher.js v8系で「cluster must be provided」エラーが発生。Laravel Reverbではclusterが不要なため、v7.6.0にダウングレードして解決。
3. 重複メッセージ表示問題
送信者が自分のメッセージを2回見る問題が発生: - 1回目:フォーム送信の即時表示 - 2回目:WebSocket経由での受信
解決策として、送信者もWebSocket経由でのみメッセージを受信するよう変更。フォーム送信は非同期化し、JSON応答のみ返すようにしました。
// 非同期フォーム送信 document.getElementById('messageForm').addEventListener('submit', async function(e) { e.preventDefault(); const response = await fetch(this.action, { method: 'POST', body: new FormData(this) }); if (response.ok) { messageInput.value = ''; } });
Next.jsなどのJSフレームワークとの比較
Laravel Turboの利点
制約・課題
- リッチなUI: 複雑なインタラクティブ要素は実装が困難
- クライアントサイド状態管理: Reactのような状態管理ライブラリがない
- エコシステム: JavaScriptエコシステムほど豊富ではない
使ってみた感想
個人的にはLaravel Turboかなりいいと感じました。ただ、Reactを使った時はコンポーネントによるUI側の整理などもできるため、システムが大きくなってくるとReact側がいいのかな?と思いました。
一部分だけでbroadcastさせたい時のシステム開発はLaravelだけで足りる可能性がありそうだなと感じたし、開発環境がシンプルになるので、個人的には好きだな〜と思いました。
まとめ
Laravel Turboはとてもいい。