💭

inertia.js2.0を速攻試してみよう

2024/12/22に公開

必要なもの

linux的なものの環境とdocker。まあmacでもいけるんじゃないでしょうかね?windowsは頑張ってもらうとして。

https://bootcamp.laravel.com/inertia/installation

基本的にはこの記事に従ってやれば大体チュートリアルは完了するのではありますが。

プロジェクトの作成

ここではチュートリアルに従ってchirperという名前にしている

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

なお、これを行うと

  • mysql
  • redis
  • meilisearch
  • mailpit
  • selenium

これだけのサービスが起動されて、てんこ盛りになるので、mysqlのみとする場合は

curl -s "https://laravel.build/chirper?with=mysql" | bash

とする。ここはどちらでもok

ガイドにあるように

Get started with: cd chirper && ./vendor/bin/sail up

で起動する。ポートを変更したい場合は

APP_PORT=8000

とかを .env に書き込んでおく

gitをつかう場合、ここでリポジトリに登録するのがおすすめ。.env.exampleの内容を.envをコピーして登録するとよい(ただしもちろんkeyはcommitしない)

migration

laravel11はとりわけsessionをdbに保存するのでmigrationしないと起動すらしない

./vendor/bin/sail artisan migrate:fresh --seed

とかでうまいことやる

% ./vendor/bin/sail artisan migrate:fresh --seed

   INFO  Preparing database.

  Creating migration table .............................................................................. 36.53ms DONE

   INFO  Running migrations.

  0001_01_01_000000_create_users_table ................................................................. 189.28ms DONE
  0001_01_01_000001_create_cache_table .................................................................. 71.74ms DONE
  0001_01_01_000002_create_jobs_table .................................................................. 163.63ms DONE


   INFO  Seeding database.

このように

  • user
  • cache
  • jobs

という3つのmigrationが実行される。実際のtableは以下のようになるが

% ./vendor/bin/sail mysql
show tabshow tablReading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 14
Server version: 8.0.32 MySQL Community Server - GPL

Copyright (c) 2000, 2023, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show tables;
+-----------------------+
| Tables_in_laravel     |
+-----------------------+
| cache                 |
| cache_locks           |
| failed_jobs           |
| job_batches           |
| jobs                  |
| migrations            |
| password_reset_tokens |
| sessions              |
| users                 |
+-----------------------+
9 rows in set (0.00 sec)

こんな感じで起動してくる

breezeのinstall

./vendor/bin/sail composer require laravel/breeze --dev

でパッケージを導入し

./vendor/bin/sail artisan breeze:install

とする。するとインタラクティブに決定していくモードになる

% ./vendor/bin/sail artisan breeze:install

 ┌ Which Breeze stack would you like to install? ───────────────┐
 │   ○ Blade with Alpine                                        │
 │   ○ Livewire (Volt Class API) with Alpine                    │
 │   ○ Livewire (Volt Functional API) with Alpine               │
 │ › ● React with Inertia                                       │
 │   ○ Vue with Inertia                                         │
 │   ○ API only                                                 │
 └──────────────────────────────────────────────────────────────┘

ここではReact with Inertiaとした

 ┌ Would you like any optional features? ───────────────────────┐
 │ › ◻ Dark mode                                                │
 │   ◻ Inertia SSR                                              │
 │   ◻ TypeScript                                               │
 │   ◻ ESLint with Prettier                                     │
 └──────────────────────────────────────────────────────────────┘
  Use the space bar to select options.
 ┌ Which testing framework do you prefer? ──────────────────────┐
 │ › ● Pest                                                     │
 │   ○ PHPUnit                                                  │
 └──────────────────────────────────────────────────────────────┘

の辺はdefaultで

するとパッケージが導入される

inertia.jsの情報を確認する

12/20の時点でinstallされたパッケージ情報composer.jsonには

    "require": {
        "php": "^8.2",
        "inertiajs/inertia-laravel": "^2.0",
        "laravel/framework": "^11.31",
        "laravel/sanctum": "^4.0",
        "laravel/tinker": "^2.9",
        "tightenco/ziggy": "^2.0"
    },
    "require-dev": {
        "fakerphp/faker": "^1.23",
        "laravel/breeze": "^2.3",
        "laravel/pail": "^1.1",
        "laravel/pint": "^1.13",
        "laravel/sail": "^1.26",
        "mockery/mockery": "^1.6",
        "nunomaduro/collision": "^8.1",
        "pestphp/pest": "^3.7",
        "pestphp/pest-plugin-laravel": "^3.0"
    },

と書いてあり、version2.0になっているのがわかる

参考までに古いの

    "require": {
        "php": "^8.2",
        "diglactic/laravel-breadcrumbs": "^9.0",
        "http-interop/http-factory-guzzle": "^1.2",
        "inertiajs/inertia-laravel": "^1.0",

これは1.0になっているのでパッケージをアップデートする場合はこの辺を弄らないといけない。ただまあそこまで大幅にいろいろ変わるわけじゃないのでアップデートは比較的問題にならずに通過するレベルと思う

この画面は既にreactになっており

resources/js/Pages/Auth/Login.jsx で描画されている

import Checkbox from '@/Components/Checkbox';
import InputError from '@/Components/InputError';
import InputLabel from '@/Components/InputLabel';
import PrimaryButton from '@/Components/PrimaryButton';
import TextInput from '@/Components/TextInput';
import GuestLayout from '@/Layouts/GuestLayout';
import { Head, Link, useForm } from '@inertiajs/react';

export default function Login({ status, canResetPassword }) {
    const { data, setData, post, processing, errors, reset } = useForm({
        email: '',
        password: '',
        remember: false,
    });

    const submit = (e) => {
        e.preventDefault();

        post(route('login'), {
            onFinish: () => reset('password'),
        });
    };

    return (
        <GuestLayout>
            <Head title="Log in" />

            {status && (
                <div className="mb-4 text-sm font-medium text-green-600">
                    {status}
                </div>
            )}

            <form onSubmit={submit}>
                <div>
                    <InputLabel htmlFor="email" value="Email" />

                    <TextInput
                        id="email"
                        type="email"
                        name="email"
                        value={data.email}
                        className="mt-1 block w-full"
                        autoComplete="username"
                        isFocused={true}
                        onChange={(e) => setData('email', e.target.value)}
                    />

                    <InputError message={errors.email} className="mt-2" />
                </div>

                <div className="mt-4">
                    <InputLabel htmlFor="password" value="Password" />

                    <TextInput
                        id="password"
                        type="password"
                        name="password"
                        value={data.password}
                        className="mt-1 block w-full"
                        autoComplete="current-password"
                        onChange={(e) => setData('password', e.target.value)}
                    />

                    <InputError message={errors.password} className="mt-2" />
                </div>

                <div className="mt-4 block">
                    <label className="flex items-center">
                        <Checkbox
                            name="remember"
                            checked={data.remember}
                            onChange={(e) =>
                                setData('remember', e.target.checked)
                            }
                        />
                        <span className="ms-2 text-sm text-gray-600">
                            Remember me
                        </span>
                    </label>
                </div>

                <div className="mt-4 flex items-center justify-end">
                    {canResetPassword && (
                        <Link
                            href={route('password.request')}
                            className="rounded-md text-sm text-gray-600 underline hover:text-gray-900 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
                        >
                            Forgot your password?
                        </Link>
                    )}

                    <PrimaryButton className="ms-4" disabled={processing}>
                        Log in
                    </PrimaryButton>
                </div>
            </form>
        </GuestLayout>
    );
}

次回以降新機能を中心にコードを組んでみよう

Discussion