Inertiaを使ったLaravel SPA開発

SPA開発する際、フロントエンドとバックエンドを分離して管理することが多いです。
技術選定の自由度や拡張性などの利点はあるものの、運用・管理のコストがかかります。

そこで、同一アプリケーション内で完結するような構成にできないか調査したところ、[Inertia](https://inertiajs.com/)がその役割を担ってくれることがわかりました。

今回は、Inertiaの説明と導入まで紹介します。

## Inertiaとは
https://inertiajs.com/

公式から引用してどんな役割をするのか見ていきます。

> Build single-page apps, without building an API.
>
> Create modern single-page React, Vue, and Svelte apps using classic server-side routing. Works with any backend — tuned for Laravel.

APIを構築する必要がなく、従来のサーバールーティングを利用して、React、Vue、およびSvelteアプリを作成することが可能です。
LaravelであればBladeテンプレートと同じような感覚で開発できます。

:::note warn
InertiaはSymfonyやRoRなど、他のフレームワークでも使用可能です。
ですが、Laravel用にチューニングされています。
:::


> JavaScript apps the monolith way
>
> Inertia is a new approach to building classic server-driven web apps. We call it the modern monolith.

Inertiaはモノリス構造であることが書かれています。
モノリスとは、一枚岩という意味です。複数の機能が一つのアプリケーションに集約されている状態です。

> Not a framework
>
> Inertia isn't a framework, nor is it a replacement for your existing server-side or client-side frameworks. Rather, it's designed to work with them. Think of Inertia as glue that connects the two. Inertia does this via adapters. We currently have three official client-side adapters (React, Vue, and Svelte) and two server-side adapters (Laravel and Rails).

Inertiaはフレームワークではありません。また、既存のクライアントサイドやサーバーサイドのフレームワークを置き換えるものでもありません。
アダプターとしてそれら二つを連携させるための設計がなされています。

## メリット・デメリット
ここでInertia導入のメリット・デメリットをまとめます。
導入の一基準として参考になればと思います。

### メリット
- 同一アプリケーション上に構築できるので、運用・管理が容易になる。
- SPA開発の特徴でもあるページ遷移高速化、UXの向上が見込める。
- Viteを使用した高速のコンパイルによって、開発体験の向上が見込める。

### デメリット
- エラーが発生した場合、発生源が特定しにくくなる。
- システムが密に関わっているため、一つの修正が全体に響く可能性が高い。

## 導入方法
公式に沿って導入します。 Laravelをインストールしている前提で進めます。
ここではLaravel Breezeを使用して構築を行います。

https://readouble.com/laravel/10.x/ja/starter-kits.html#:~:text=%E3%81%A6%E3%81%8F%E3%81%A0%E3%81%95%E3%81%84%E3%80%82-,Breeze%E3%81%A8React%EF%BC%8FVue,-Laravel%20Breeze%E3%81%AF

使用する環境バージョン情報は以下のとおりです。
| 項目名    | バージョン |
| --------- | ----------- |
| Composer | 2.4.4 |
| php | ^8.1 |
| laravel/framework    | ^10.0 |
| laravel/breeze | ^1.20 |
| inertiajs/inertia-laravel | ^0.6.3 |

はじめに、Laravel Breezeをインストールします。
```shell
composer require laravel/breeze --dev
```

次にフロントエンド環境をインストールします。
今回はReactを採用します。
```shell
php artisan breeze:install react
```

環境が整ったので、サーバーを立ち上げましょう。
```shell
# フロントエンド
npm run dev
# バックエンド
php artisan serve
```

`localhost:8000`にアクセスし、以下のように表示されていれば問題ありません。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2882125/241e0958-e463-721b-4b95-6c6feb804fcb.png)

ここからInertiaの機能をいくらか紹介します。

### ルーティング
Bladeテンプレートでは`Route::view`関数を使用していましたが、`Inertia::render`関数を使用するようになります。
```php
Route::get("/dashboard", function () {
    return Inertia::render("Dashboard");
})->middleware(["auth", "verified"])->name("dashboard");
```

### データの受け渡し
コントローラーからコンポーネントへのデータ渡しも、propsとして受け取ることができます。
例えば、`TestController`からwelcomeページへデータを送る時には以下のようになります。
```php:TestController
use Inertia\Inertia;

class TestController extends Controller
{
    public function index() {
        $payload = ["name" => "test"];
        return Inertia::render("Welcome", $payload);
    }
}
```

```php:web.php
Route::get('/test', [TestController::class, 'index'])->name('test.index');
```

```jsx:Welcome.tsx
export default function Welcome({ name }) {
    console.log(name) // test
    ...
```

### ページ遷移
画面リロードを行わず、SPA特有のページ遷移を行います。
```jsx
import { Link } from '@inertiajs/react'

<Link href="/">Home</Link>
```

### フォーム
Inertiaにはフォームヘルパーが含まれています。
これらを使用することで、より簡単にフォーム値を管理・送信することが可能です。

```jsx
import { useForm } from '@inertiajs/react'

const { data, setData, post, processing, errors } = useForm({
  email: '',
  password: '',
  remember: false,
})

function submit(e) {
  e.preventDefault()
  post('/login')
}

return (
  <form onSubmit={submit}>
    <input type="text" value={data.email} onChange={e => setData('email', e.target.value)} />
    {errors.email && <div>{errors.email}</div>}
    <input type="password" value={data.password} onChange={e => setData('password', e.target.value)} />
    {errors.password && <div>{errors.password}</div>}
    <input type="checkbox" checked={data.remember} onChange={e => setData('remember', e.target.checked)} /> Remember Me
    <button type="submit" disabled={processing}>Login</button>
  </form>
)
```
`useForm`フックには例以外に多くのメソッドを提供しています。詳しくは公式で確認してください。

https://inertiajs.com/forms

## まとめ
Inertiaを使用することで、アプリケーション管理の容易になることや、SPA開発として素早い開発ができることがわかりました。
しかし、規模が大きいシステム開発や、チーム開発でそれぞれの役割が明確に決まっている場合は、フロントエンド・バックエンドと分けて管理した方がいいです。

一長一短なので、各自の開発環境に合わせて導入を検討してみてください。

## 最後に
**GoQSystemでは一緒に働いてくれる仲間を募集中です！**
ご興味がある方は以下リンクよりご確認ください。

https://goqsystem.recruit.site/?qiita=ebdb3d592d143eefef06