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

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

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

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

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

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

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

## 各種インストール

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

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

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

```bash
cd laravel9-vue3-inertiajs
```

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

```bash
npm install --save-dev vue
npm install --save-dev @vitejs/plugin-vue
npm install --save-dev @inertiajs/inertia-vue3
```

## viteの設定

[vite](https://vitejs.dev/)は、ここではVueを高速にコンパイルするライブラリと捉えて差し支えありません。以前の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.js'],
            refresh: true,
        }),
    ],
});
```

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

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

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

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

```

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

```javascript:app.js
import { createApp, h } from "vue";
import { createInertiaApp } from "@inertiajs/inertia-vue3";
import { resolvePageComponent } from "laravel-vite-plugin/inertia-helpers";

createInertiaApp({
    resolve: (name) =>
        resolvePageComponent(
            `./Pages/${name}.vue`,
            import.meta.glob("./Pages/**/*.vue")
        ),
    setup({ el, App, props, plugin }) {
        createApp({ render: () => h(App, props) })
            .use(plugin)
            .mount(el);
    },
});
```

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

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

次に、`resources/views/app.blade.php`を作成します。これは、Vueでの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
    @vite(['resources/css/app.css', 'resources/js/app.js'])
</head>

<body>
    @inertia
</body>

</html>
```

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

## 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');
});

```

## Vueファイルの作成

いよいよVueファイルを作成してみます。`resources/js/Pages/hello-world.vue`を作成します。ここではvueファイルが正しく表示されるかどうかを確認したいので、[Vueのチュートリアルにあるコード](https://vuejs.org/guide/scaling-up/sfc.html#introduction)を拝借します。

```vue:hello-world.vue
<script>
export default {
    data() {
        return {
            greeting: "Hello World!",
        };
    },
};
</script>

<template>
    <p class="greeting">{{ greeting }}</p>
</template>

<style>
.greeting {
    color: red;
    font-weight: bold;
}
</style>
```

## 動作確認

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

```
php artisan serve
```

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

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

## デプロイ

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