クイック エンジニアリングブログ

株式会社クイック Web事業企画開発本部のエンジニアリングチームが運営する技術ブログです。

LaravelでSPA開発環境をサクッと作る

こんにちは、ソフトウェアエンジニアのやぎーです。

みなさんローカル開発環境の構築してますか。

ちょっとした検証や、思いつきでアプリを作ろうと思った時にサクッと作りたいことがあります。

しかし、設定やらエラーやらにつまづき、また時間ある時に...と挫折してしまう人も多いのではないでしょうか。

最新のLaravelでSailを使ってサクッと構築する手順を簡単にご紹介します。

環境

Laravel

PHPのフレームワーク。 バージョン11ではディレクトリ構成が変更されているのでご注意ください。

Inertia.js

フロントエンド・バックエンドを繋ぐためのアダプター。
Laravel用に調整されているが、Railsなどにも対応している。

React

JavaScript ライブラリ。
コンポーネントベースでSPA(Single Page Application)と相性が良い。

Vite

ビルドツール。
HMR(Hot Module Replacement)で修正分のみを適用してくれるため高速。

構築手順

Laravelインストール・起動

何はともあれ、まずはLaravel本体をインストールしていきます。
※Docker Desktopを使用します

プロジェクトを作成したいディレクトリに移動し、下記を実行します。

curl -s "https://laravel.build/inertia-react" | bash

本体のインストールが終わったら、sailを起動します。

cd inertia-react && ./vendor/bin/sail up -d

docker psでコンテナが起動していることを確認します。

CONTAINER ID   IMAGE                           COMMAND                  CREATED         STATUS                   PORTS                                                      NAMES
d7a37822a7ba   sail-8.3/app                    "start-container"        2 minutes ago   Up 2 minutes             0.0.0.0:80->80/tcp, 0.0.0.0:5173->5173/tcp, 8000/tcp       inertia-react-laravel.test-1
d2d689647a27   redis:alpine                    "docker-entrypoint.s…"   2 minutes ago   Up 2 minutes (healthy)   0.0.0.0:6379->6379/tcp                                     inertia-react-redis-1
e2960d4a5a25   mysql/mysql-server:8.0          "/entrypoint.sh mysq…"   2 minutes ago   Up 2 minutes (healthy)   0.0.0.0:3306->3306/tcp, 33060-33061/tcp                    inertia-react-mysql-1
dd78e09916ab   axllent/mailpit:latest          "/mailpit"               2 minutes ago   Up 2 minutes (healthy)   0.0.0.0:1025->1025/tcp, 0.0.0.0:8025->8025/tcp, 1110/tcp   inertia-react-mailpit-1
d46113a1e304   getmeili/meilisearch:latest     "tini -- /bin/sh -c …"   2 minutes ago   Up 2 minutes (healthy)   0.0.0.0:7700->7700/tcp                                     inertia-react-meilisearch-1
15c6cd20bd9f   seleniarm/standalone-chromium   "/opt/bin/entry_poin…"   2 minutes ago   Up 2 minutes             4444/tcp, 5900/tcp                                         inertia-react-selenium-1

起動が確認できたらマイグレーションを実行します。

sail php artisan migrate

http://localhostにアクセスするとwelcome画面が表示できるようになります。

ライブラリのインストール ひとまず最低限必要なものだけインストールします。

# Reactとvite関連
sail npm install @vitejs/plugin-react @inertiajs/react react-dom

# Inertia
sail composer require inertiajs/inertia-laravel

ファイル・設定 SPAとして動かすために必要な設定を行います。

Middlewareを追加

sail php artisan inertia:middleware

webのルーティングでmiddlewareが適用されるよう設定。
Laravel11からMiddlewareの指定方法が下記のように変更されていますので注意。

// bootstrap/app.php

->withMiddleware(function (Middleware $middleware) {
    $middleware->web(append: [
        HandleInertiaRequests::class
    ]);

    $middleware->api(prepend: []);
})

Inertiaを使うようにbladeを変更

<!-- resources/views/app.blade.php -->

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
        <title>Sample SPA</title>
        @viteReactRefresh
        @vite('resources/js/app.jsx')
        @inertia
    </head>

    <body style="margin: 0">
    @inertia
    </body>

</html>

Inertiaを使うようにapp.jsxを変更

// resources/js/app.jsx

import "./bootstrap";

import { createInertiaApp } from "@inertiajs/react";
import { createRoot } from "react-dom/client";

createInertiaApp({
    resolve: name => {
        const pages = import.meta.glob("./Pages/**/*.jsx", { eager: true });
        return pages[`./Pages/${name}.jsx`];
    },
    setup({ el, App, props }) {
        createRoot(el).render(<App {...props} />);
    }
});

Pagesフォルダに表示するコンポーネントの作成

// resources/js/Pages/Index.jsx

const Index = () => {
    return <>Index Page</>;
};
export default Index;

ルーティング設定

// routes/web.php

Route::inertia('/', 'Index');

ビルドを実行

sail npm run dev

配置したコンポーネントが表示されていれば完了です。

Laravel・Reactの接続

通常ですと、ここからLaravelにAPIを実装しReactから取得を行う実装が必要になると思いますが、Inertiaを使うことでReactへの接続がbladeっぽくできるようになります。

コントローラー

// app/Https/Controllers/SampleController.php

<?php

namespace App\Http\Controllers;

use App\Models\SampleLists;
use Illuminate\Http\Request;
use Inertia\Inertia;

class SampleController extends Controller
{
    public function index(Request $request) {
     // サンプルデータが入ったtableから10件取得
        $sampleList = SampleLists::query()
            ->limit(10)
            ->get();

     // Inertia::renderにコンポーネント名とデータを渡す
        return Inertia::render('Sample', [
            'sampleList' => $sampleList,
        ]);
    }
}

ルート設定

// routes/web.php

<?php

use Illuminate\Support\Facades\Route;

Route::get('/sample', 'App\Http\Controllers\SampleController@index');

受け取ったデータを一覧で取得するコンポーネント

// resources/js/Pages/Sample.jsx

// リスト作成
const createList = (list) => {
    return list.map(col => {
        return <li key={`key-${col.id}`}>{col.value}</li>
    });
}

// Controllerで渡したデータをPropsで受け取れる
const Sample = ({ sampleList }) => {

    return (<>
        <h2>サンプル一覧</h2>
        <ul>{createList(sampleList)}</ul>
    </>);
};
export default Sample;

Laravelで渡したデータが表示されればOKです。

まとめ

細かな設定はさておき、ローカル動作環境を用意する手順としてはかなり手軽ではないでしょうか。

Inertiaの登場で、Laravel・React間の接続がとても簡単に作れるようになり、SPAでの開発を行うハードルは以前より確実に低くなっているように感じます。

日々更新される情報をキャッチし、よりスピード感のある開発をしていきたいと思います!

最後までお読みいただきありがとうございました。


\\『真のユーザーファーストでマーケットを創造する』仲間を募集中です!! //

919.jp