環境
macOS:Sonoma 14.5
DockerDesktop:4.30.0
目的
Laravel11 + React(Vite)(TS)の開発環境を構築する。
CSSフレームワーク・ライブラリとして、tailwindcssとdaisyUIとIconifyを使えるようにする。
フロントエンドとバックエンドを疎結合にしたいので、Inertiaは使わない。
前提
Laravelが稼働しているコンテナ内でコマンドを実行する。
下記内容は構築済みとする。
- httpsでの通信ができている。
- LaravelのWelcomeページを表示できる。
参考
nvm をインストール
下記コマンドを実行する。
# curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.5/install.sh | bash
# source ~/.bashrc
Node.js をインストール
下記コマンドを実行する。(今回はバージョンを指定しているが、適宜変更すると良い)
※ もしnvmが見つからない旨のエラーが表示されたら、シェルを再起動すれば良い。
# nvm install --lts 20.14.0
React関連をインストール
下記コマンドを実行する。(動作確認用でIconifyのアイコンを1種類インストールしている)
※ dependencies と devDependencies は必要になったら分割すれば良い。
※ 1行目でLaravelのプロジェクトルートへ移動している。
# cd /var/www/html
# npm install --save-dev react react-dom @vitejs/plugin-react
# npm install --save-dev tailwindcss postcss autoprefixer daisyui@latest @iconify/tailwind @iconify-json/material-symbols
# npm install --save-dev typescript @types/react-dom @types/react glob
# npx tsc --init
# npx tailwindcss init -p
React関連を設定
tsconfig.json の内容
{
"compilerOptions": {
"target": "ES2022",
"useDefineForClassFields": true,
"lib": ["ES2022", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedIndexedAccess": true,
"exactOptionalPropertyTypes": true,
"noImplicitReturns": true,
"noImplicitOverride": true
},
"include": [
"resources/tsx/*.tsx",
"resources/tsx/**/*.tsx",
],
}
vite.config.js の内容
- plugins.laravel.input
- tailwindCSSの設定を行う、resources/css/app.css を追加。
- resources/tsx/entryディレクトリ内の、拡張子がtsxである、Reactのコンポーネントファイルを全て追加。
- server
- host
- 全てのIPアドレスからの接続を待つよう設定。
- port
- React用の開発サーバのポート番号を設定。
- https
- key
- SSL/TLS証明書の秘密鍵を設定。
- cert
- SSL/TLS証明書を設定。
- key
- hmr.host
- 更新する際の接続先を設定。
- host
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import react from '@vitejs/plugin-react';
import fs from 'fs';
import { glob } from 'glob';
export default defineConfig({
plugins: [
react(),
laravel({
input: [
'resources/css/app.css',
...glob.sync('resources/tsx/entry/*.tsx')
],
views: [
'resources/views/*.blade.php',
],
refresh: true,
}),
],
server: {
host: '0.0.0.0',
port: 5173,
https: {
key: fs.readFileSync('/etc/ssl/private/private.key'),
cert: fs.readFileSync('/etc/ssl/certs/apache.crt'),
},
hmr: {
host: 'Webサイトのドメイン',
},
},
});
tailwind.config.js の内容
- tailwindCSSのプラグインとして、daisyUIとIconifyを使えるように設定。
- tailwindCSSの対象となるファイルを設定。
/** @type {import('tailwindcss').Config} */
const { addDynamicIconSelectors } = require('@iconify/tailwind');
export default {
content: [
"./resources/tsx/*.tsx",
"./resources/tsx/**/*.tsx",
],
theme: {
extend: {},
},
plugins: [
// daisyUI
require('daisyui'),
// Iconify
addDynamicIconSelectors(),
],
}
動作確認用コードを作成
resources/css/app.css の内容
@tailwind base;
@tailwind components;
@tailwind utilities;
Reactのコンポーネント
※ resources/tsxディレクトリ以下は初期状態では無いので作成する。
resources/tsx/entry/Test1.tsx の内容
import React from 'react';
import ReactDOM, { Container } from 'react-dom/client';
import Component from '../Component.tsx';
ReactDOM.createRoot(document.getElementById('root') as Container).render(
<React.StrictMode>
<div>
Test1.tsx
</div>
<Component/>
</React.StrictMode>,
);
resources/tsx/entry/Test2.tsx の内容
import React from 'react';
import ReactDOM, { Container } from 'react-dom/client';
import Component from '../Component.tsx';
ReactDOM.createRoot(document.getElementById('root') as Container).render(
<React.StrictMode>
<div>
Test2.tsx
</div>
<Component />
</React.StrictMode>,
);
resources/tsx/Component.tsx の内容
import { ReactNode, useEffect } from 'react';
function Component (): ReactNode {
useEffect(() => {
console.log('Component.tsx useEffect');
}, []);
return (
<>
<div>
Component.jsx
</div>
<div>
<button
type="button"
className="btn btn-primary"
>
Primary Button
</button>
</div>
<div>
<span className="icon-[material-symbols--add-circle]"/>
</div>
</>
);
}
export default Component;
resources/viewsフォルダ内のビューファイル
resources/views/test1.blade.php の内容
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>test1.blade.php</title>
@vitereactrefresh
@vite('resources/tsx/entry/Test1.tsx')
@vite('resources/css/app.css')
</head>
<body>
<div>
test1.blade.php
</div>
<div id="root"/>
</body>
</html>
resources/views/test2.blade.php の内容
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>test2.blade.php</title>
@vitereactrefresh
@vite('resources/tsx/entry/Test2.tsx')
@vite('resources/css/app.css')
</head>
<body>
<div>
test2.blade.php
</div>
<div id="root"/>
</body>
</html>
動作確認
ビルドせず確認
開発中はこのやり方で確認する。
開発サーバ起動
Laravelのプロジェクトルートへ移動し、次のコマンドを実行する。
$ npm run dev
Webブラウザから確認
https://Webサーバのドメイン/test1 へアクセスし、
test1.blade.php や Test1.tsx の文字列と
daisyUIのボタンとIconifyのアイコンの表示の確認と、
Chromeのデベロッパーツールのコンソールで
「Component.tsx useEffect」と表示されていることを確認すれば良い。
https://Webサーバのドメイン/test2 へアクセスし、同様に確認すれば良い。
ビルドして確認
開発サーバを起動せずに、デプロイ時の状態を確認するにはReactをビルドする必要があるので、
次のコマンドを実行する。
$ npm run build
ビルドが完了すると、public/buildディレクトリが作成される。
この状態で再度上記の「Webブラウザから確認」を実施すれば良い。