laravel + inertia + react のbootcampを見る (その1: セットアップまで)
これは chirper というアプリケーションを作成する例である。簡易ツイッター的なものだ。BladeとInertiaの2つから選択できる。Laravelの初心者はBladeからやった方がいいかもしれない、が、ここではInertiaを取り上げる。
Inertiaとは何なのかという説明は敢えてしないが、Laravelの機能をふんだんに使いつつvueやらreactやらを使う(それも非同期で)というものになっている。まあ何を言っているのかとかいうのはともあれ使ってみよう。
Projectを開始する
https://bootcamp.laravel.com/inertia/installation
まず、いきなりだがここでの読者の想定は先述したようにある程度Laravelでのアプリケーション開発の経験がある人を対象にしているから、使い出しまでの細かい説明は行わない。
そして、上記の記事ではcomposerでprojectを作成し、artisan serveで確認しているものと、docker(sail)で行うものとあるが。ここではdocker + laravel sail一択とする。しがたってコマンド等は全てsailで表記するが、経験があれば別段nativeのserveとかその辺でも動かせると思うし、別にdockerを使う必要もないかもしれない。
projectを作る
https://bootcamp.laravel.com/inertia/installation#installation-via-docker
Installation via Dockerを参照。
とりあえずmysqlだけあればいいので以下のようなコマンドを展開する
curl -s "https://laravel.build/chirper?with=mysql" | bash
システムに合わせて最適なバージョンが選択されると思うが、ここではlaravel10が入る(2023/8/4)。projectが展開されると chirper というディレクトリが作成されるからcdしておく。
sailをupする前に
適当なgitレポジトリにつっこんでおく事を想定する。
その際、.env.exampleと.envでちょっと設定が変わっているから、開発版
DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=example
DB_USERNAME=sail
DB_PASSWORD=password
とかのDB設定にしておくといいかも。あと、どっちにしてもwebアプリとして開発するパターンがほとんどなので
APP_NAME=Chirper
APP_ENV=local
APP_KEY=
APP_DEBUG=true
APP_URL=http://localhost
APP_PORT=8000
こんな感じでAPP_PORTも設定しておくといいかもしれない。そうすればそのポートで待ち受けるようになる(localhost:8000とか)
これはdocker-compose.ymlで参照されるから、そこに設定がある。あと、APP_NAMEも変更した。
sail upする
./vendor/bin/sail up
あるいはsail up -dオプション
migrate可能な事(ようするにDBと通信できているか)を確認しておく
% ./vendor/bin/sail artisan migrate
INFO Preparing database.
Creating migration table ......................................... 37ms DONE
INFO Running migrations.
2014_10_12_000000_create_users_table ............................. 63ms DONE
2014_10_12_100000_create_password_reset_tokens_table ............. 86ms DONE
2019_08_19_000000_create_failed_jobs_table ....................... 57ms DONE
2019_12_14_000001_create_personal_access_tokens_table ............ 89ms DONE
cloneした場合はartisan key:generateとかも必要かもしれない。
いずれにせよ、これでlaravelのトップが見えてくるはずだ
laravel breezeのセットアップ
Laravel Breezeは、Laravelの認証機能(ログイン、登録、パスワードリセット、メール確認、パスワード確認)をシンプルに実装したテンプレート一式である。実際ここまでは、まだBladeに行く事も可能であるが、ここではinertiaとreactで実装するので、そちらの方向に向かっていく事にする。
composer require laravel/breeze --dev
を入力してみる。以下はsailでの出力である。
% ./vendor/bin/sail composer require laravel/breeze --dev
./composer.json has been updated
Running composer update laravel/breeze
Loading composer repositories with package information
Updating dependencies
Nothing to modify in lock file
Installing dependencies from lock file (including require-dev)
Package operations: 1 install, 0 updates, 0 removals
- Downloading laravel/breeze (v1.22.0)
- Installing laravel/breeze (v1.22.0): Extracting archive
Generating optimized autoload files
> Illuminate\Foundation\ComposerScripts::postAutoloadDump
> @php artisan package:discover --ansi
INFO Discovering packages.
laravel/breeze ........................................................ DONE
laravel/sail .......................................................... DONE
laravel/sanctum ....................................................... DONE
laravel/tinker ........................................................ DONE
nesbot/carbon ......................................................... DONE
nunomaduro/collision .................................................. DONE
nunomaduro/termwind ................................................... DONE
spatie/laravel-ignition ............................................... DONE
82 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
> @php artisan vendor:publish --tag=laravel-assets --ansi --force
INFO No publishable resources for tag [laravel-assets].
No security vulnerability advisories found
Using version ^1.22 for laravel/breeze
そしたら続いて以下のコマンドを入力する
php artisan breeze:install react
以下はsailでの出力
% ./vendor/bin/sail artisan breeze:install react
./composer.json has been updated
Running composer update inertiajs/inertia-laravel laravel/sanctum tightenco/ziggy
Loading composer repositories with package information
Updating dependencies
Lock file operations: 2 installs, 0 updates, 0 removals
- Locking inertiajs/inertia-laravel (v0.6.9)
- Locking tightenco/ziggy (v1.6.0)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 2 installs, 0 updates, 0 removals
- Downloading inertiajs/inertia-laravel (v0.6.9)
- Downloading tightenco/ziggy (v1.6.0)
0/2 [>---------------------------] 0%
2/2 [============================] 100%
- Installing inertiajs/inertia-laravel (v0.6.9): Extracting archive
- Installing tightenco/ziggy (v1.6.0): Extracting archive
0/2 [>---------------------------] 0%
2/2 [============================] 100%
Generating optimized autoload files
> Illuminate\Foundation\ComposerScripts::postAutoloadDump
> @php artisan package:discover --ansi
INFO Discovering packages.
inertiajs/inertia-laravel ............................................. DONE
laravel/breeze ........................................................ DONE
laravel/sail .......................................................... DONE
laravel/sanctum ....................................................... DONE
laravel/tinker ........................................................ DONE
nesbot/carbon ......................................................... DONE
nunomaduro/collision .................................................. DONE
nunomaduro/termwind ................................................... DONE
spatie/laravel-ignition ............................................... DONE
tightenco/ziggy ....................................................... DONE
83 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
> @php artisan vendor:publish --tag=laravel-assets --ansi --force
INFO No publishable resources for tag [laravel-assets].
No security vulnerability advisories found
INFO Installing and building Node dependencies.
added 173 packages, and audited 174 packages in 19s
29 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
npm notice
npm notice New minor version of npm available! 9.7.1 -> 9.8.1
npm notice Changelog: https://github.com/npm/cli/releases/tag/v9.8.1
npm notice Run npm install -g npm@9.8.1 to update!
npm notice
> build
> vite build
vite v4.4.8 building for production...
✓ 217 modules transformed.
public/build/manifest.json 6.75 kB │ gzip: 0.80 kB
public/build/assets/app-719ee526.css 29.89 kB │ gzip: 5.80 kB
public/build/assets/InputLabel-f2ea45d1.js 0.21 kB │ gzip: 0.18 kB
public/build/assets/TextInput-e7b330e7.js 0.48 kB │ gzip: 0.33 kB
public/build/assets/GuestLayout-44108184.js 0.50 kB │ gzip: 0.32 kB
public/build/assets/PrimaryButton-0d68d1ff.js 0.50 kB │ gzip: 0.34 kB
public/build/assets/Dashboard-8e530bd5.js 0.65 kB │ gzip: 0.37 kB
public/build/assets/ForgotPassword-4b0e9a33.js 1.14 kB │ gzip: 0.64 kB
public/build/assets/Edit-8c868c75.js 1.14 kB │ gzip: 0.52 kB
public/build/assets/ConfirmPassword-30bae1b5.js 1.19 kB │ gzip: 0.64 kB
public/build/assets/VerifyEmail-9cc6c6f8.js 1.25 kB │ gzip: 0.69 kB
public/build/assets/ResetPassword-ebc284e8.js 1.78 kB │ gzip: 0.70 kB
public/build/assets/Login-1056b871.js 2.11 kB │ gzip: 0.94 kB
public/build/assets/UpdateProfileInformationForm-5a9adf8d.js 2.29 kB │ gzip: 1.00 kB
public/build/assets/Register-522f8f02.js 2.30 kB │ gzip: 0.84 kB
public/build/assets/UpdatePasswordForm-c33224ca.js 2.34 kB │ gzip: 0.86 kB
public/build/assets/ApplicationLogo-129c0e69.js 3.12 kB │ gzip: 1.33 kB
public/build/assets/AuthenticatedLayout-aa6a8e79.js 5.78 kB │ gzip: 1.86 kB
public/build/assets/transition-ecfd9599.js 13.29 kB │ gzip: 5.16 kB
public/build/assets/Welcome-ad683f6d.js 15.88 kB │ gzip: 4.44 kB
public/build/assets/DeleteUserForm-44deb104.js 27.32 kB │ gzip: 9.76 kB
public/build/assets/app-f89f8aba.js 247.66 kB │ gzip: 82.14 kB
✓ built in 4.39s
INFO Breeze scaffolding installed successfully.
さて、これでbreeze + reactでlaravelの画面が書き変わっている。確認してみよう。
このようにログインやら登録やらのリンクが貼りこまれている。
ログインを押すとこのような認証フォームが描画されるはずだ。これはreact(とtailwind cssとか)で記述されている。実態はresources/js/Pages/Auth/Login.jsxである
import { useEffect } from 'react';
import Checkbox from '@/Components/Checkbox';
import GuestLayout from '@/Layouts/GuestLayout';
import InputError from '@/Components/InputError';
import InputLabel from '@/Components/InputLabel';
import PrimaryButton from '@/Components/PrimaryButton';
import TextInput from '@/Components/TextInput';
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,
});
useEffect(() => {
return () => {
reset('password');
};
}, []);
const submit = (e) => {
e.preventDefault();
post(route('login'));
};
return (
<GuestLayout>
<Head title="Log in" />
{status && <div className="mb-4 font-medium text-sm 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="block mt-4">
<label className="flex items-center">
<Checkbox
name="remember"
checked={data.remember}
onChange={(e) => setData('remember', e.target.checked)}
/>
<span className="ml-2 text-sm text-gray-600">Remember me</span>
</label>
</div>
<div className="flex items-center justify-end mt-4">
{canResetPassword && (
<Link
href={route('password.request')}
className="underline text-sm text-gray-600 hover:text-gray-900 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
>
Forgot your password?
</Link>
)}
<PrimaryButton className="ml-4" disabled={processing}>
Log in
</PrimaryButton>
</div>
</form>
</GuestLayout>
);
}
もちろん、これはここを書き換えただけで反映されるものではない、たとえばLog in のところを以下のように書き換えてみよう。
<PrimaryButton className="ml-4" disabled={processing}>
ログイン
</PrimaryButton>
これだけでは何も起きない。npm run buildする必要がある
% ./vendor/bin/sail npm run build
> build
> vite build
vite v4.4.8 building for production...
✓ 217 modules transformed.
public/build/manifest.json 6.75 kB │ gzip: 0.81 kB
public/build/assets/app-719ee526.css 29.89 kB │ gzip: 5.80 kB
public/build/assets/InputLabel-cc46406f.js 0.21 kB │ gzip: 0.18 kB
public/build/assets/TextInput-ee89aca1.js 0.48 kB │ gzip: 0.34 kB
public/build/assets/GuestLayout-2b290bdb.js 0.50 kB │ gzip: 0.32 kB
public/build/assets/PrimaryButton-5d500b20.js 0.50 kB │ gzip: 0.34 kB
public/build/assets/Dashboard-3a6532cd.js 0.65 kB │ gzip: 0.38 kB
public/build/assets/ForgotPassword-f3867354.js 1.14 kB │ gzip: 0.64 kB
public/build/assets/Edit-ee2edd03.js 1.14 kB │ gzip: 0.52 kB
public/build/assets/ConfirmPassword-ad923438.js 1.19 kB │ gzip: 0.64 kB
public/build/assets/VerifyEmail-dc4cb09a.js 1.25 kB │ gzip: 0.69 kB
public/build/assets/ResetPassword-ab6d2221.js 1.78 kB │ gzip: 0.70 kB
public/build/assets/Login-1bca5ec2.js 2.11 kB │ gzip: 0.97 kB
public/build/assets/UpdateProfileInformationForm-92a1bb0f.js 2.29 kB │ gzip: 1.00 kB
public/build/assets/Register-8018aaba.js 2.30 kB │ gzip: 0.84 kB
public/build/assets/UpdatePasswordForm-aaa65a0a.js 2.34 kB │ gzip: 0.86 kB
public/build/assets/ApplicationLogo-3e2530be.js 3.12 kB │ gzip: 1.32 kB
public/build/assets/AuthenticatedLayout-376e8b9b.js 5.78 kB │ gzip: 1.86 kB
public/build/assets/transition-5d54f17e.js 13.29 kB │ gzip: 5.17 kB
public/build/assets/Welcome-9d0bcab8.js 15.88 kB │ gzip: 4.44 kB
public/build/assets/DeleteUserForm-cedfa812.js 27.32 kB │ gzip: 9.76 kB
public/build/assets/app-1fb36539.js 247.66 kB │ gzip: 82.14 kB
✓ built in 4.36s
ホットリロード
ただ、これだとかなり開発が面倒くさいので、ホットリロードを行うようにする。これはvite.config.jsで行う
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import react from '@vitejs/plugin-react';
const host = 'localhost';
export default defineConfig({
server: {
hmr: { host },
},
plugins: [
laravel({
input: 'resources/js/app.jsx',
refresh: true,
}),
react(),
],
});
サーバーがlocalhostじゃなかったらもちろんlocalhost以外にするんだけども、これでnpm run devすると
VITE v4.4.8 ready in 580 ms
こんな感じで待ち受けるようになるから先程のログインフォームなんかを書き換えてただしくホットリロードできるか確認する。
前段階完了
webプログラミングはセットアップが結構面倒くさいのが難点ではあるが、ここまでやってようやくプログラミングに入っていく事ができる。次回以降は実際にこのbootcampのコード記述していく。(要するにchirper を作る)
に続く