作成する開発環境は「Laravel-sail+React+React-router」を想定している。
LaravelならVueでしょ!という意見もあると思いますが、Reactで作成するほうが大規模開発のような雰囲気があるのと、コンポーネントの考え方のほうが再利用もしやすいと思うからです。
React-routerはReactでページを切り替えて動作するようなサイトを作成するためのモジュールです。
Reactアプリケーションでのルーティングを管理するための人気のあるライブラリです。React Routerを使用すると、SPA(Single Page Application)内で複数のビュー間を切り替えることができます。
私の環境ではWindows11 + WSL2+DockerDesktop環境で作成しています。
そのためWSLでUbuntuの導入までは済んでいるものとします。
laravel sail 環境の作成
curl -s "https://laravel.build/sample_app?with=mysql,redis" | bash
※withを付けて必要なアプリを指定。付けないと自動でmailpit,meilisearch,mysql,selenium,redisがインストールされます。
Reactの導入
# sailの起動
sail up -d
# nodeのVersion確認
sail node --version
# npmのVersion確認
sail npm --version
Reactの必要モジュールの導入
# Laravelアプリケーションのスターターキット導入
# 詳しくは https://readouble.com/laravel/10.x/ja/starter-kits.html
$ sail composer require laravel/breeze --dev
$ sail php artisan breeze:install react
$ sail npm install -D react-router-dom
# 必要ならtypescripの導入
# $ sail npm install -D typescript @types/react @types/react-dom @types/react-router-dom
# $ sail npx tsc --init --jsx react-jsx
# Sassの導入
$ sail npm install -D sass
初期表示のためのページ作成
Laravelのルーティング設定
routes/web.php
use Illuminate\Support\Facades\Route;
Route::get('{any}', function () {
return view('index');
})->where('any','.*');
laravelで最初に読み込まれるBradeファイル
resources/views/index.blade.php
<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- CSRF Token -->
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>{{ config('app.name', 'Laravel') }}</title>
<!-- Fonts -->
<link rel="dns-prefetch" href="//fonts.gstatic.com">
<!-- bootstrap5 -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
<!-- Scripts -->
@viteReactRefresh
@vite(['resources/js/app.css', 'resources/js/app.jsx'])
</head>
<body>
<div id="app"></div>
</body>
</html>
Reactで実行されるルーティングの設定
resources/js/route.jsx
import React from 'react';
import { createRoot } from 'react-dom/client';
import { BrowserRouter, Route, Routes } from 'react-router-dom';
import Home from './Pages/Home';
import Example from './Pages/Example';
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/example" element={<Example />} />
</Routes>
</BrowserRouter>
);
}
const container = document.getElementById('app');
const root = createRoot(container);
root.render(<App />);
app.jsxにrouteを追加
resources/js/app.jsx
import './bootstrap';
import '../css/app.css';
import './route'; // この行を追加
import { createRoot } from 'react-dom/client';
import { createInertiaApp } from '@inertiajs/react';
import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers';
const appName = import.meta.env.VITE_APP_NAME || 'Laravel';
createInertiaApp({
title: (title) => `${title} - ${appName}`,
resolve: (name) => resolvePageComponent(`./Pages/${name}.jsx`, import.meta.glob('./Pages/**/*.jsx')),
setup({ el, App, props }) {
const root = createRoot(el);
root.render(<App {...props} />);
},
progress: {
color: '#4B5563',
},
});
ホームページ
resources/js/Pages/Home.jsx
import React from 'react';
import { Link } from 'react-router-dom';
function Home() {
return (
<div className="container mt-5">
<div className="row justify-content-center">
<div className="col-md-8">
<div className="card">
<div className="card-header">Home Component</div>
<div className="card-body">I'm an home component!</div>
<Link to={'/example'} className="btn btn-primary">
Exampleへ遷移
</Link>
</div>
</div>
</div>
</div>
);
}
export default Home;
Exampleページ
resources/js/Pages/Example.jsx
import React from 'react';
import { Link } from 'react-router-dom';
function Example() {
return (
<div className="container mt-5">
<div className="row justify-content-center">
<div className="col-md-8">
<div className="card">
<div className="card-header">Example Component</div>
<div className="card-body">I'm an home component!</div>
<Link to={'/'} className="btn btn-primary">
ホームへ戻る
</Link>
</div>
</div>
</div>
</div>
);
}
export default Example;
実行方法
ターミナルから実行
$ sail npm run dev
http://localhost にアクセスし、動作を確認する