前編終了時点でのコード
前編の記事は以下からリンクできます。
Docker+Laravel+React+TypeScript構成のフルスタックパッケージを順を追って構築する【前編:サーバーサイド】
また、前編終了時のコードはGitHubで確認できます。
// 前編での最終形
fullstack-project/
├ src/
| └ (Laravelのコード)
├ docker/
│ ├ nginx/
│ │ ├ Dockerfile
│ │ └ default.conf
│ ├ php/
│ │ ├ Dockerfile
│ │ └ php.ini
│ └ mysql/
│ ├ Dockerfile
│ └ my.conf
└ docker-compose.yml
3. React環境構築
Laravelを使う場合、ReactやVueなどのフロントエンド開発を手軽に始めるためのパッケージが用意されています。
3-1. Node.jsとnpm
まずは、フロントエンド開発では必須のNode.jsとnpmをDockerコンテナに導入します。phpのDockerfileに記載します。
FROM php:8.1-fpm-alpine
# install composer
RUN curl -sS https://getcomposer.org/installer | php
RUN mv composer.phar /usr/local/bin/composer
# install packages
RUN apk update
RUN apk add git nodejs npm
# install php extensions
RUN docker-php-ext-install pdo pdo_mysql
apk installコマンドの値にnodejsとnpmを追加します。Dockerfileを編集したのでdocker-compose buildコマンドでビルドします。
docker-compose build app
docker-compose exec app node -v
v16.15.0
docker-compose exec app npm -v
8.10.0
node -vコマンドおよびnpm -vコマンドでインストールされていることが確認できたら成功です。
3-2. MixとUI
Laravel MixはLaravelにデフォルトでインストールされているパッケージで、 モジュールバンドラーのWebpackをラップするパッケージです。 Webpackの設定ファイルであるwebpack.config.jsは構造が複雑になりがちで苦労するのですが、 そのような設定作業に悩まされることなくフロントエンド開発を始めることができます。
Laravel MixはLaravelプロジェクトにあらかじめ導入されているのでインストールは不要です。
Laravel UI
Laravel UIはフロントエンドのスキャフォールディング(雛形作成)機能で、 ReactやVue、BootStrapの雛形をコマンド1つで作成してくれます。
docker-compose exec app composer require laravel/ui
Laravelには7.xまでLaravel UIに関するドキュメントがありますが、8.x以降は無くなっています。
JavaScript & CSS Scaffolding (7.x)
以下のコマンドを実行することでReactの雛形が作成されます。
docker-compose exec app php artisan ui react
コマンドを実行後、Laravelプロジェクトのあるsrc/resources配下にファイルがいくつか追加されます。
// php artisan uiコマンド実行後
fullstack-project/
├ src/
| └ resources/
| ├ js/
| | ├ components/
| | | └ Example.js
| | ├ app.js
| | └ bootstrap.js
| └ sass/
| ├ _variables.scss
| └ app.scss
├ docker/
└ docker-compose.yml
app.jsを確認すると、Example.jsコンポーネントを要求していることがわかります。
import React from 'react';
import ReactDOM from 'react-dom';
function Example() {
return (
<div className="container">
<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 example component!</div>
</div>
</div>
</div>
</div>
);
}
export default Example;
if (document.getElementById('example')) {
ReactDOM.render(<Example />, document.getElementById('example'));
}
jsを確認すると、Exampleコンポーネントの定義と、ExampleコンポーネントをidがexampleのDOM要素に対して描画していることがわかります。
JavaScriptビルド
npm run devコマンドでJavaScriptとCSSをビルドします。
docker-compose exec app npm run dev
...
Additional dependencies must be installed. This will only take a moment.
Running: npm install resolve-url-loader@^5.0.0 --save-dev --legacy-peer-deps
Finished. Please run Mix again.
初回は、上記のようなメッセージが表示されます。
もう一度npm run devコマンドを実行します。
docker-compose exec app npm run dev
...
Laravel Mix v6.0.49
✔ Compiled Successfully in 8145ms
Larvelプロジェクトのsrc/public配下にビルドされたファイルが追加されます。
// php artisan devコマンド実行後
fullstack-project/
├ public/
| ├ css/
| ├ └ app.css
| └ js/
| └ app.js
├ src/
├ docker/
└ docker-compose.yml
welcome.blade.php
src/views配下にあるwelcome.blade.phpを編集して、Reactコンポーネントを表示するように編集します。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Fullstack Project</title>
<link rel="stylesheet" href="{{ mix('/css/app.css') }}" />
</head>
<body>
<div id="example"></div>
<script src="{{ mix('/js/app.js') }}"></script>
</body>
</html>
link要素にビルドしたcssを、body要素の閉じタグ直前にビルドしたjsを、 そしてbody要素にはexampleをidに持つdiv要素を用意します。
mixメソッドを利用するとLaravelがファイルパスを自動的に指定してくれます。
ブラウザで確認してみる

ブラウザでlocalhost:8000にアクセスし、Exampleコンポーネントが確認できたら成功です。
4. TypeScript環境構築
Reactを用いる場合、同時にTypeScriptを導入することが多いです。 Laravel Mixをすでに導入している場合は、特に負担なくTypeScriptを利用することができます。
4-1. TypeScript
Exampleコンポーネントのファイル名をExample.tsxに変更します。
import React from 'react';
import ReactDOM from 'react-dom';
function Example(): React.ReactElement {
return (
<div className="container">
<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 example component!</div>
</div>
</div>
</div>
</div>
);
}
export default Example;
if (document.getElementById('example')) {
ReactDOM.render(<Example />, document.getElementById('example'));
}
webpack.mix.jsのmix.jsメソッドをmix.tsに変更します。
TypeScriptによる型を使用できるようになります。
const mix = require('laravel-mix');
/*
|--------------------------------------------------------------------------
| Mix Asset Management
|--------------------------------------------------------------------------
|
| Mix provides a clean, fluent API for defining some Webpack build steps
| for your Laravel application. By default, we are compiling the Sass
| file for the application as well as bundling up all the JS files.
|
*/
mix.ts('resources/js/app.js', 'public/js')
.react()
.sass('resources/sass/app.scss', 'public/css');
npm run devコマンドでJavaScriptとCSSをビルドします。
初回はTypeScriptに関連するnpmパッケージがインストールされます。
docker-compose exec app npm run dev
...
Additional dependencies must be installed. This will only take a moment.
Running: npm install ts-loader typescript --save-dev --legacy-peer-deps
Finished. Please run Mix again.
もう一度npm run devコマンドを実行します。
docker-compose exec app npm run dev
...
ERROR in ./resources/js/components/Example.tsx
[tsl] ERROR
TS18002: The 'files' list in config file 'tsconfig.json' is empty.
ERROR in ./resources/js/components/Example.tsx
Module build failed (from ./node_modules/ts-loader/index.js):
Error: error while parsing tsconfig.json
at Object.loader (/var/www/html/node_modules/ts-loader/dist/index.js:17:18)
webpack compiled with 2 errors and 1 warning
tsconfig.json
Laravel MixのTypescript Supportに記載のある通り、
tsconfig.jsonと型パッケージ(@types/*)が必要なので用意します。
{
"compilerOptions": {
"target": "ES2015",
"module": "commonjs",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"$schema": "https://json.schemastore.org/tsconfig",
"display": "Recommended"
}
さらにReactのJSXを対応できるようにし、さらにvendor配下の検証は除外します。
{
"compilerOptions": {
"target": "ES2015",
"module": "commonjs",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"jsx": "react"
},
"exclude": [
"vendor"
],
"$schema": "https://json.schemastore.org/tsconfig",
"display": "Recommended"
}
@types/*
関連する型パッケージをインストールします。
docker-compose exec app npm install @types/node @types/react @types/react-dom
ビルドして確認する
docker-compose exec app npm run dev
...
Laravel Mix v6.0.49
✔ Compiled Successfully in 10969ms
TypeScriptでのビルドができるようになりました。
完成
Docker+Laravel+React+TypeScript構成の環境が完成しました。
必要に応じてPHP静的解析ツールのphpcsやphpmd、JSのESLintやJS Standardなどを導入してください。
最終的な構成
// 最終的な構成(この記事で編集していないLaravelのファイルは省略)
fullstack-project/
├ docker/
│ ├ nginx/
│ │ ├ Dockerfile
│ │ └ default.conf
│ ├ php/
│ │ ├ Dockerfile
│ │ └ php.ini
│ └ mysql/
│ ├ Dockerfile
│ └ my.conf
├ src/
├ ├ public/
| | ├ css/
| | ├ └ app.css
| | └ js/
| | └ app.js
| ├ resources/
| | ├ js/
| | | ├ components/
| | | | └ Example.tsx
| | | ├ app.js
| | | └ bootstrap.js
| | └ sass/
| | ├ _variables.scss
| | └ app.scss
| ├ views/
| | └ welcome.blade.php
| ├ .env
| ├ tsconfig.json
| └ webpack.mix.js
└ docker-compose.yml