{} CodeLift

Laravel + React Starter Kit を Docker で検証して改良した fork を公開

公式の laravel/react-starter-kit(Inertia + React 19 + shadcn/ui + Fortify)を Docker Desktop で動かし、本番運用に耐える形に書き直したフォークを公開する。テストは公式版の 40 passed をベースに 44 passed / 151 assertions まで増加。本記事は React / Inertia 固有の論点に絞って記録する。

公開 2026-04-19 検証 2026-04-19 更新 2026-04-19

検証環境

  • PHP 8.5.5
  • Laravel 13.5.0
  • Composer 2.9.7
  • Node 22.22.2
  • npm 10.9.7
  • Database SQLite (tests)
  • OS Docker Desktop (php:8.5-cli-bookworm)

Laravel + React Starter Kit を Docker で検証して改良した fork を公開

公式の laravel/react-starter-kit(Inertia + React 19 + shadcn/ui + Fortify)を Docker Desktop で動かし、本番運用に耐える形に書き直したフォークを公開する。テストは公式版の 40 passed をベースに 44 passed / 151 assertions まで増加。本記事は React / Inertia 固有の論点に絞って記録する。

backend 側の改修(.env.example / timezone / セキュリティヘッダ / HTTPS 強制 / レート制限 / 認証ログ)は React・Vue・Livewire の 3 fork で完全に同一なので、pillar 記事に集約した:

Laravel スターターキット共通 backend を本番化する 6 つの改修

本記事はその cluster(枝)として、React Starter Kit に固有の話だけを扱う。

対象の公式サンプル

項目
名前 Laravel + React Starter Kit
公式 URL https://github.com/laravel/react-starter-kit
改良版 fork https://github.com/codelift-dev/react-starter-kit/tree/improvements
スタック Laravel 13 + Inertia + React 19 + TypeScript + shadcn/ui + Fortify
元 / 改良版ライセンス MIT / MIT
検証日 2026-04-19
上流 commit laravel/react-starter-kit@2e22614

検証環境

pillar 記事と共通(Docker Desktop、PHP 8.5.5 / Laravel 13.x / Node 22.22.2)。再現は fork の codelift/Dockerfile + codelift/docker-compose.yml で行える。

git clone https://github.com/codelift-dev/react-starter-kit.git
cd react-starter-kit
git checkout improvements
docker compose -f codelift/docker-compose.yml build
docker compose -f codelift/docker-compose.yml run --rm app

React Starter Kit 固有の論点

A. composer install 前に npm run build するとビルドが不可解に失敗する

これは React / Vue 版に固有(Livewire 版にはない)。

症状: clone 直後に npm run build を先に走らせると、Vite ビルドが次のエラーで落ちる。

require(.../vendor/autoload.php): Failed to open stream: No such file or directory
in artisan on line 10

原因: vite.config.ts@laravel/vite-plugin-wayfinder プラグインが、ビルド中に php artisan wayfinder:generate を shell out する。Wayfinder は Laravel のルート定義から TypeScript の型付きルートヘルパーを生成する仕組みで、ビルド時に artisan を起動する。Composer 依存が未インストールだと artisanvendor/autoload.php を読めずに落ちる。

なぜ厄介か: エラーメッセージに composer install の文字が一切出ない。初見の開発者は Vite か Wayfinder のバグを疑い、見当違いの方向に時間を溶かす。vendor/autoload.php というパスから「Composer をまだ流していない」と即座に気付けるのは、Laravel に慣れた人だけ。

改修: README に Setup セクションを追加し、composer installnpm run build の順を明示。Wayfinder がビルド時に artisan を呼ぶ事実も併記して、なぜこの順序なのかを理解できるようにした。

React 19 + Inertia の初期 state と CSP

React Starter Kit は React 19 を使う。Inertia はサーバー側ルーティング + React コンポーネントを繋ぐ仕組みで、ページ遷移ごとにサーバーが JSON の「page object」を返し、React がそれを描画する。

問題は初回ロード。Inertia は初回 HTML に、ページコンポーネントと初期 props を埋め込む必要がある。これは <div id="app" data-page="{...エンコードされた props...}"> という形で root 要素の属性に入り、@inertia Blade ディレクティブが出力する。

この「初期 props を HTML に直接埋める」設計が、Content-Security-Policy を厳格化するときの障壁になる。'unsafe-inline' を完全に外して nonce ベースに移行するには、Inertia のレスポンスレンダリング(HandleInertiaRequests ミドルウェアや Inertia のレスポンスクラス)に手を入れて nonce を通す必要がある。

CodeLift の改良版では、CSP 自体は導入する(pillar 記事 finding D)が、script-src'unsafe-inline' を残す保守的な設定にとどめた。nonce 化は Inertia 側の改造を伴う独立テーマなので、別途 follow-up で扱う予定。

参考までに、Inertia を使わない Livewire 版では初期 state を inline script に埋めないため、'unsafe-inline' を外した nonce ベース CSP に移行できる。その手法は Livewire の CSP nonce 化記事に詳しい。

J. 設定エンドポイントのレート制限が password だけ

React Starter Kit の routes/settings.php は、明示的な throttle ミドルウェアを password 更新ルートにしか付けていない。

Route::patch('settings/profile', ...)->name('profile.update');         // throttle なし
Route::delete('settings/profile', ...)->name('profile.destroy');       // throttle なし
Route::put('settings/password', ...)->middleware('throttle:6,1')...;   // throttle あり

セッションが乗っ取られた場合、profile の連続書き換えやアカウント連続削除試行が、グローバルデフォルトの範囲で通ってしまう。

改修: React/Vue 版は設定変更が PATCH / DELETE という HTTP verb で素直に表現されているので、ルート定義に throttle ミドルウェアを足すだけで済む。

-    Route::patch('settings/profile', ...)->name('profile.update');
+    Route::patch('settings/profile', ...)->middleware('throttle:10,1')->name('profile.update');
-    Route::delete('settings/profile', ...)->name('profile.destroy');
+    Route::delete('settings/profile', ...)->middleware('throttle:3,1')->name('profile.destroy');

アカウント削除は terminal な操作なので 3 回 / 分と厳しめに絞った。(Livewire 版は Route::livewire 経由でコンポーネント内 AJAX なので、この修正がそのまま使えない — 詳細は Livewire 記事を参照。)

改良版の commit 構成

improvements ブランチに 8 commits:

commit finding 出典
README Setup A(React/Vue 固有) 本記事
.env.example コメント B pillar
timezone env 化 C pillar
URL::forceScheme E pillar
SetSecurityHeaders middleware + test D pillar
login rate limiter 2 段化 G pillar
auth log channel + subscriber + test I pillar
settings throttle J(本記事) 本記事

テストは公式版 40 passed → 改良版 44 passed / 151 assertions(SecurityHeaders 2 件・AuthLogging 2 件を追加、既存は全 pass)。

before / after(React 固有部分)

観点 公式版 改良版
php artisan test 40 passed / 136 assertions 44 passed / 151 assertions
ビルド順序のドキュメント なし(Wayfinder の落とし穴あり) README に明記
settings endpoints の throttle password のみ profile update / destroy にも

共通 backend 改修(6 件)の before / after は pillar 記事を参照。

どのケースで向くか

  • laravel/react-starter-kit をテンプレに本番プロダクトを立ち上げる予定で、最初に足回りを固めたい
  • React / Vue / Livewire のどれにするか検討中で、React を選んだ場合の production 化コストを把握したい → 結論は3 種比較記事に整理した(backend 改修コストは 3 つとも同じ)

再現と取り込み

git clone https://github.com/codelift-dev/react-starter-kit.git
cd react-starter-kit
git diff main improvements -- . ':!codelift'

各 commit は独立、cherry-pick 可能。

関連記事

ライセンス

元サンプル / 改良版とも MIT。検証結果は検証日時点のもの。

この記事を含む比較

関連記事