【Laravel11 + Inertia + Vue3】環境構築

Laravel

手動で Laravel に Inertia を導入する方法の解説です。

Laravel - The PHP Framework For Web Artisans
Laravel is a PHP web application framework with expressive, elegant syntax. We???ve already laid the foundation ??? free...
Inertia.js - The Modern Monolith
Inertia.js lets you quickly build modern single-page React, Vue and Svelte apps using classic server-side routing and co...

Inertiaは、Breeze や Jetstream インストール時に併せて自動インストールできますが、ここでは、Breeze や Jetstream は入れないで Inertia だけ独立してインストールする方法を解説していきます。

Inertiaってオイシイの?

「Inertia」(イナーシャ)は「不活性、惰性、慣性」といった意味の英単語です。

特徴としては、

  • サーバー駆動型(Javascript)WEBアプリのアプローチ(モダンモノリス)
  • クライアント側ルーティング不要
  • API作成不要(サーバー側でデータ取得しSPAへ渡す)
  • サーバー側フレームワークとクライアント側フレームワークを結びつける接着剤
  • サーバー側公式アダプター: Laravel / Rails / Phoenix
  • クライアント側公式アダプター: React / Vue / Svelte
  • 他フレームワークはコミュニティアダプターでサポート

といったところでしょうか。

API不要、クライアント側ルーティング不要、Laravel用に調整されている、設定が簡単、という点が筆者にとっては魅力です。

Inertia の使い方のイメージ

使い方としては、サーバー側でコントローラーを作成し、

コントローラーから Inertia アダプターを呼び出して、

ビューにデータを渡します。

ビュー側ではコントローラーから受け取ったデータを使ってJavascriptに振る舞いをさせます。

▼コントローラーの例「app/Http/Controllers/TodoController.php」

use Inertia\Inertia;

class TodoListController extends Controller
{
    public function index()
    {
        return Inertia::render('TodoList', [
            'user' => User::find(auth()->user()->id),
            '_token' => session()->token(),
        ]);
    }
}

▼ビューの例「resources/js/Pages/TodoList.vue」

<script setup>
import AppLayout from '@/Layouts/AppLayout.vue';
import TodoList from '@/Components/TodoList.vue';

defineProps({
    user: {
        type: Object
    },
});
</script>

<template>
    <AppLayout title="TodoList">
        <div id="todolist" class="py-12">
            <div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
                <div class="bg-white overflow-hidden shadow-xl sm:rounded-lg">
                    <TodoList
                        :user="user"
                    />
                </div>
            </div>
        </div>
    </AppLayout>
</template>

フォルダ構成としては次のような感じになります。

[プロジェクト]/
 ├─ app/ サーバーサイドファイル群
 │ ├─ Http/
 │ │ ├─ Controllers/
 │ │ │ ├─ Controller.php
 │ │ │ ├─ IndexController.php
 │ │ │ ├─ ・・・
 │ │ └─ Middleware/
 │ │   └─ HandleInertiaRequests.php
 │ ├─ ・・・
 ├─ ・・・
 ├─ resources/ クライアントサイドファイル群
 │ ├─ css/
 │ ├─ js/
 │ │ ├─ Components/ コンポーネント
 │ │ │ ├─ ButtonGeneral.vue
 │ │ │ ├─ ・・・
 │ │ ├─ Layouts/ レイアウト
 │ │ │ ├─ AppLayout.vue
 │ │ │ ├─ ・・・
 │ │ ├─ Pages/ ページ
 │ │ │ ├─ MyPage/
 │ │ │ │ ├─ Profile.vue
 │ │ │ │ ├─ ・・・
 │ │ │ ├─ Dashboard.vue
 │ │ │ ├─ Index.vue
 │ │ │ ├─ ・・・
 │ │ ├─ ・・・
 │ └─ views/
 │   └─ app.blade.php ルートテンプレート
 ├─ ・・・

前提条件

  • Laravel11を使っていきます
  • PHP8.2以降インストール済(Laravel11対応バージョン)
  • Composerインストール済
  • Vue3を使います
  • Ubuntu上で作業していきます

新規プロジェクト作成

新規プロジェクト「inertia-app」を作成していきます。

composer create-project laravel/laravel:^11 inertia-app

プロジェクトフォルダに入ります。

cd inertia-app

サーバー側の設定

次のコマンドでアダプターをインストールします。

composer require inertiajs/inertia-laravel

次にルートテンプレートを設置します。

「resouces/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" />
    @vite('resources/js/app.js')
    @inertiaHead
  </head>
  <body>
    @inertia
  </body>
</html>

次に、Inertia Middleware のセットアップをします。

php artisan inertia:middleware

「app/Http/Middleware/HandleInertiaRequests.php」が設置されます。

これを「bootstrap/app.php」に追記します。

※冒頭に追記

use App\Http\Middleware\HandleInertiaRequests;

※「withMiddleware()」内に追記

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

クライアント側の設定

Viteプラグインをインストールします。

npm install @vitejs/plugin-vue

「vite.config.js」を編集します。

import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import vue from '@vitejs/plugin-vue'; // ←追記

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

クライアント側のInertiaアダプターをインストールします。

npm install @inertiajs/vue3

「resources/js/app.js」を編集します。

import './bootstrap';

import { createApp, h } from 'vue'
import { createInertiaApp } from '@inertiajs/vue3'

createInertiaApp({
  resolve: name => {
    const pages = import.meta.glob('./Pages/**/*.vue', { eager: true })
    return pages[`./Pages/${name}.vue`]
  },
  setup({ el, App, props, plugin }) {
    createApp({ render: () => h(App, props) })
      .use(plugin)
      .mount(el)
  },
})

レイアウト作成

続いて、レイアウトを準備します。

「resources/js/Layouts/AppLayout.vue」を新規作成します。

<script setup>
import { Link } from '@inertiajs/vue3'
</script>

<template>
  <main>
    <header>
      <Link href="/">Home</Link>
      <Link href="/about">About</Link>
      <Link href="/contact">Contact</Link>
    </header>
    <article>
      <slot />
    </article>
  </main>
</template>

Pages 作成

「resources/js/Pages/Welcome.vue」を新規作成します。

<script setup>
import AppLayout from '@/Layouts/AppLayout.vue';
import { Head } from '@inertiajs/vue3';

defineProps({ user: Object });
</script>

<template>
  <AppLayout>
    <Head title="Welcome" />
    <h1>Welcome</h1>
    <p>Hello {{ user.name }}, welcome to your first Inertia app!</p>
  </AppLayout>
</template>

コントローラー作成

「WelcomeController.php」を作成します。

php artisan make:controller WelcomeController

「app/Http/Controllers/WelcomeController.php」を編集します。

<?php

namespace App\Http\Controllers;

use Inertia\Inertia;

use Illuminate\Http\Request;

class WelcomeController extends Controller
{
    public function index()
    {
        return Inertia::render('Welcome', [
            'user' => [
                'name' => 'Hoge',
            ],
        ]);
    }
}

ルーティング

「routes/web.php」を編集します。

<?php

use App\Http\Controllers\WelcomeController;
use Illuminate\Support\Facades\Route;

Route::get('/', [WelcomeController::class, 'index']);

ビルトインサーバー起動

Laravelのビルトインサーバーを起動します。

php artisan serve

Viteを起動します。

npm run dev

ブラウザで確認

WEBブラウザで http://localhost:8000/ にアクセスします。

コンテンツが正常に出力されました。

ユーザー名「Hoge」も差し込みされています。

以上です。

  • 0
  • 0
  • 0
  • 0

コメント

タイトルとURLをコピーしました