Laravel 9 & ReactをInertiaを用いて接続する(Vite使用版)

本記事で作成するプロジェクトは[Githubのリポジトリ](https://github.com/ReiRev/laravel9-react-inertiajs)に置いてあります。是非ご覧ください。

また、ReactではなくVueと接続したいという方は、[こちらのQiitaの記事](https://qiita.com/reirev2913/items/b4505df08372eed9126d)をご覧ください。

## フロントエンドとバックエンドを接続するInertia.js

バックエンドフレームワークのLaravelとフロントエンドフレームワークのReactは、どちらも素晴らしいフレームワークだと思います。双方のメリットを活かしてウェブアプリケーションを作成したいと考えるのは当然でしょう。それを実現してくれるのがInertia.jsです。Inertiaを使用すると、それぞれ切り分けて開発されたLaravelとReactを接続することができます。非常に便利ですね。

ただ、バージョン9への移行に伴い、Laraevlはそれまで利用していたwebmixからviteを使用するようになり、既存の解説記事の手順ではInertiaを導入できなくなってしまいました。また、Inertiaのドキュメントが不足していることもあり、導入がそもそも自力で導入するのが難しいです。そこで、自分の備忘録という意味も含め、LaravelとReactを導入する方法をこの記事で説明します。

以下では、Laravel9, npm, composerはインストール済みであると仮定します。Laravel及びReactの知識があると理解しやすいかとは思いますが、なくても大丈夫です。

## 各種インストール

以下のコマンドでプロジェクトの作成を行います。プロジェクト名は"laravel9-react-inertiajs"としました。

```bash
composer create-project laravel/laravel laravel9-react-inertiajs
```

プロジェクトディレクトリに移動します。

```bash
cd laravel9-react-inertiajs
```

次に、各種必要なReact関連のパッケージをインストールします。

```bash
npm install --save-dev react-dom　react
npm install --save-dev @vitejs/plugin-react
npm install --save-dev @inertiajs/inertia-react
```

[vite](https://vitejs.dev/)は、ここではReactを高速にコンパイルするライブラリと捉えて差し支えありません。以前のLaravelでは使用されていたwebmixはviteに置き換わりました。Laravel9を使用していれば、`vite.config.js`というファイルがあり、以下のように記載されていると思います。

```javascript:vite.config.js
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';

export default defineConfig({
    plugins: [
        laravel({
            input: ['resources/css/app.css', 'resources/js/app.jsx'],
            refresh: true,
        }),
    ],
});
```

laravel.inputには、Laravelからvueに渡されるファイルを定義します。エントリポイントのファイルだけでよく、app.jsxがimportしているファイル全てをここに記載する必要はありません。SPAを作成していて、CSSをVue側で読み込む場合には、'resources/css/app.css'は削除して問題ありません。
app.js以外のファイルを使用する場合には、適宜名前を変更します。

ここで一つ注意が必要なのは、拡張子をapp.jsではなく、app.jsxにしなくてはならない点です。viteがうまく処理してくれなくなります。基本的に、viteを使う場合はjsx拡張子を使うのが良さそうです。

このvite.config.jsに、プラグインとして、vueを渡してあげます。vite.config.jsは以下のようになります。これによって、viteがうまくvueのコンパイルを行ってくれます。

```javascript:vite.config.js
import { defineConfig } from "vite";
import laravel from "laravel-vite-plugin";
import react from "@vitejs/plugin-react";

export default defineConfig({
    plugins: [
        laravel({
            input: ["resources/css/app.css", "resources/js/app.jsx"],
            refresh: true,
        }),
        react(),
    ],
});

```

## Inertiaの設定

まず、Inertiaをインストールしましょう。

```bash
composer require inertiajs/inertia-laravel
```

次に、Inertiaのミドルウェアを作成します。

```
php artisan inertia:middleware
```

これでミドルウェアが作成されました。

次に、app/Http/Kernel.phpに以下を追記します。

```
'web' => [
    // ...
    \App\Http\Middleware\HandleInertiaRequests::class,
],
```

## CreateInertiaAppの作成

次に、`resources/js/app.jsx`を編集します。vite.config.jsでは、このファイルをエントリポイントとしてコンパイルを行うようにしました。app.jsxの役割は、一言で言えばルーティングです。Laravelから渡されたrouteを基に、どのページを表示するかを決定します。app.jsxは以下のように記述します。(ここの情報、あまりまだネットに出回ってないですね...)

```javascript:app.jsx
import React from "react";
import { render } from "react-dom";
import { createInertiaApp } from "@inertiajs/inertia-react";
import { resolvePageComponent } from "laravel-vite-plugin/inertia-helpers";

createInertiaApp({
    resolve: (name) =>
        resolvePageComponent(
            `./Pages/${name}.jsx`,
            import.meta.glob("./Pages/**/*.jsx")
        ),
    setup({ el, App, props }) {
        render(<App {...props} />, el);
    },
});
```

createInertiaAppという関数に渡されたresolveに注目すると、`name`へのルーティングが`./Pages/$(name).jsx`へのルーティングとして処理されることがわかると思います。ここのフォルダは変えてしまっても問題ありませんが、拡張子は`.jsx`にしておかないとコンパイルエラーが出るようです。

### app.blade.phpとReactの連携

次に、`resources/views/app.blade.php`を作成します。これは、Reactでのindex.htmlを編集するようなものだと考えておけば大丈夫です。

```php: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" />
    @inertiaHead
    @viteReactRefresh
    @vite(['resources/css/app.css', 'resources/js/app.jsx'])
</head>

<body>
    @inertia
</body>

</html>
```

適宜、vite内の'resources/js/app.css'は削除してください。

1つ注意が必要なのは、Reactを用いる場合には、`@viteReactRefresh`ディレクティブが必要な点です。これは、Vueを使用する際には必要ありません。

## Routing

ルーティングの設定を行います。`routes/web.php`を開いてください。初期の状態では、以下のようになっていると思います。

```php:web.php
<?php

use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

Route::get('/', function () {
    return view('welcome');
});
```

このRoutingの部分でも、Inertiaとの接続が必要です。以下のように変更します。ここでは、インデックスページに来たリクエストに対して、`hello-world.vue`を表示するように設定します。ここは適宜変更してください。アプリケーションが大規模になる場合には、もちろんコントローラーにコードを移してください。

```php:web.php
<?php

use Illuminate\Support\Facades\Route;
use Inertia\Inertia;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

Route::get('/', function () {
    return Inertia::render('hello-world');
});
```

## Reactファイルの作成

いよいよReactファイルを作成してみます。`resources/js/Pages/hello-world.jsx`を作成します。ここではReactファイルが正しく表示されるかどうかだけを確認したいので、単純な以下のファイルを作成します。

```react:hello-world.jsx
export default function HelloWorld() {
    return (
        <div>
            <p>Hello World!</p>
        </div>
    );
}

```

## 動作確認

以上で準備は終了です。最後にターミナルを2つ開いて、以下のコマンドをそれぞれ実行して、正しく動作しているか確認してみましょう。

```
php artisan serve
```

```
npm install && npm run dev
```

Hello World！と表示されていれば成功です。

## デプロイ

デプロイする際には、以下のコマンドを実行すれば、publicフォルダ内にコンパイルされたcss, jsファイルが生成されます。あとは、通常のLaravelと同様にデプロイしてあげてください。