shinke1987.net
雑多な備忘録等のはず。
他のカテゴリ・タブ
目次
PR

DockerでLaravel11 + React(Vite) の開発環境構築

2024-05-30 2024-05-30

環境

macOS:Sonoma 14.5

DockerDesktop:4.30.0

目的

Laravel11 + React(Vite)(TS)の開発環境を構築する。

CSSフレームワーク・ライブラリとして、tailwindcssとdaisyUIとIconifyを使えるようにする。

フロントエンドとバックエンドを疎結合にしたいので、Inertiaは使わない。

前提

Laravelが稼働しているコンテナ内でコマンドを実行する。

下記内容は構築済みとする。

参考

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 の内容

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 の内容

/** @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ブラウザから確認」を実施すれば良い。

同一カテゴリの記事