2022-06-20 投稿

Docker+Laravel+React+TypeScript構成のフルスタックパッケージを順を追って構築する【後編:フロントエンド】

Webアプリ開発に慣れない人にとって環境構築は大きなハードルです。 この記事ではサーバーサイドはDockerとLaravel、フロントエンドではReactとTypeScriptを使ったフルスタックパッケージを、ひとつづつ手順を確認しながら構築していきます。 後編ではフロントエンドのReact+TypeScriptの構築を行います。

前編終了時点でのコード

前編の記事は以下からリンクできます。

Docker+Laravel+React+TypeScript構成のフルスタックパッケージを順を追って構築する【前編:サーバーサイド】

また、前編終了時のコードはGitHubで確認できます。

1// 前編での最終形
2fullstack-project/
3  ├ src/
4  |   └ (Laravelのコード)
5  ├ docker/
6  │   ├ nginx/
7  │   │   ├ Dockerfile
8  │   │   └ default.conf
9  │   ├ php/
10  │   │   ├ Dockerfile
11  │   │   └ php.ini
12  │   └ mysql/
13  │       ├ Dockerfile
14  │       └ my.conf
15  └ docker-compose.yml

3. React環境構築

Laravelを使う場合、ReactやVueなどのフロントエンド開発を手軽に始めるためのパッケージが用意されています。

3-1. Node.jsとnpm

まずは、フロントエンド開発では必須のNode.jsとnpmをDockerコンテナに導入します。phpのDockerfileに記載します。

1FROM php:8.1-fpm-alpine
2
3# install composer
4RUN curl -sS https://getcomposer.org/installer | php
5RUN mv composer.phar /usr/local/bin/composer
6
7# install packages
8RUN apk update
9RUN apk add git nodejs npm
10
11# install php extensions
12RUN docker-php-ext-install pdo pdo_mysql

apk installコマンドの値にnodejsとnpmを追加します。Dockerfileを編集したのでdocker-compose buildコマンドでビルドします。

docker-compose build app

1docker-compose exec app node -v
2v16.15.0
3
4docker-compose exec app npm -v
58.10.0

node -vコマンドおよびnpm -vコマンドでインストールされていることが確認できたら成功です。

ここまでのコード(GitHub)

3-2. MixとUI

Laravel MixはLaravelにデフォルトでインストールされているパッケージで、 モジュールバンドラーのWebpackをラップするパッケージです。 Webpackの設定ファイルであるwebpack.config.jsは構造が複雑になりがちで苦労するのですが、 そのような設定作業に悩まされることなくフロントエンド開発を始めることができます。

Compiling Assets (Mix)

Laravel MixはLaravelプロジェクトにあらかじめ導入されているのでインストールは不要です。

Laravel UI

Laravel UIはフロントエンドのスキャフォールディング(雛形作成)機能で、 ReactやVue、BootStrapの雛形をコマンド1つで作成してくれます。

Laravel UI (GitHub)

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配下にファイルがいくつか追加されます。

1// php artisan uiコマンド実行後
2fullstack-project/
3  ├ src/
4  |  └ resources/
5  |     ├ js/
6  |     |  ├ components/
7  |     |  |  └ Example.js 
8  |     |  ├ app.js
9  |     |  └ bootstrap.js
10  |     └ sass/
11  |        ├ _variables.scss
12  |        └ app.scss
13  ├ docker/
14  └ docker-compose.yml

app.jsを確認すると、Example.jsコンポーネントを要求していることがわかります。

1import React from 'react';
2import ReactDOM from 'react-dom';
3
4function Example() {
5  return (
6    <div className="container">
7      <div className="row justify-content-center">
8        <div className="col-md-8">
9          <div className="card">
10            <div className="card-header">Example Component</div>
11
12            <div className="card-body">I'm an example component!</div>
13          </div>
14        </div>
15      </div>
16    </div>
17  );
18}
19
20export default Example;
21
22if (document.getElementById('example')) {
23    ReactDOM.render(<Example />, document.getElementById('example'));
24}

jsを確認すると、Exampleコンポーネントの定義と、ExampleコンポーネントをidがexampleのDOM要素に対して描画していることがわかります。

JavaScriptビルド

npm run devコマンドでJavaScriptとCSSをビルドします。

1docker-compose exec app npm run dev
2
3...
4Additional dependencies must be installed. This will only take a moment.
5 
6Running: npm install resolve-url-loader@^5.0.0 --save-dev --legacy-peer-deps
7
8Finished. Please run Mix again.

初回は、上記のようなメッセージが表示されます。 もう一度npm run devコマンドを実行します。

1docker-compose exec app npm run dev
2...
3Laravel Mix v6.0.49                         
4✔ Compiled Successfully in 8145ms

Larvelプロジェクトのsrc/public配下にビルドされたファイルが追加されます。

1// php artisan devコマンド実行後
2fullstack-project/
3  ├ public/
4  |  ├ css/
5  |  ├  └ app.css
6  |  └ js/
7  |     └ app.js
8  ├ src/
9  ├ docker/
10  └ docker-compose.yml

welcome.blade.php

src/views配下にあるwelcome.blade.phpを編集して、Reactコンポーネントを表示するように編集します。

1<!DOCTYPE html>
2<html lang="ja">
3<head>
4    <meta charset="UTF-8">
5    <title>Fullstack Project</title>
6    <link rel="stylesheet" href="{{ mix('/css/app.css') }}" />
7</head>
8<body>
9    <div id="example"></div>
10    <script src="{{ mix('/js/app.js') }}"></script>
11</body>
12</html>

link要素にビルドしたcssを、body要素の閉じタグ直前にビルドしたjsを、 そしてbody要素にはexampleをidに持つdiv要素を用意します。

mixメソッドを利用するとLaravelがファイルパスを自動的に指定してくれます。

ブラウザで確認してみる

fig1

ブラウザでlocalhost:8000にアクセスし、Exampleコンポーネントが確認できたら成功です。

ここまでのコード(GitHub)

4. TypeScript環境構築

Reactを用いる場合、同時にTypeScriptを導入することが多いです。 Laravel Mixをすでに導入している場合は、特に負担なくTypeScriptを利用することができます。

4-1. TypeScript

Exampleコンポーネントのファイル名をExample.tsxに変更します。

1import React from 'react';
2import ReactDOM from 'react-dom';
3
4function Example(): React.ReactElement {
5  return (
6    <div className="container">
7      <div className="row justify-content-center">
8        <div className="col-md-8">
9          <div className="card">
10            <div className="card-header">Example Component</div>
11
12            <div className="card-body">I'm an example component!</div>
13          </div>
14        </div>
15      </div>
16    </div>
17  );
18}
19
20export default Example;
21
22if (document.getElementById('example')) {
23    ReactDOM.render(<Example />, document.getElementById('example'));
24}

webpack.mix.jsmix.jsメソッドをmix.tsに変更します。 TypeScriptによる型を使用できるようになります。

1const mix = require('laravel-mix');
2
3/*
4 |--------------------------------------------------------------------------
5 | Mix Asset Management
6 |--------------------------------------------------------------------------
7 |
8 | Mix provides a clean, fluent API for defining some Webpack build steps
9 | for your Laravel application. By default, we are compiling the Sass
10 | file for the application as well as bundling up all the JS files.
11 |
12 */
13
14mix.ts('resources/js/app.js', 'public/js')
15    .react()
16    .sass('resources/sass/app.scss', 'public/css');

npm run devコマンドでJavaScriptとCSSをビルドします。
初回はTypeScriptに関連するnpmパッケージがインストールされます。

1docker-compose exec app npm run dev
2
3...
4Additional dependencies must be installed. This will only take a moment.
5 
6Running: npm install ts-loader typescript --save-dev --legacy-peer-deps
7
8Finished. Please run Mix again.

もう一度npm run devコマンドを実行します。

1docker-compose exec app npm run dev
2
3...
4ERROR in ./resources/js/components/Example.tsx 
5[tsl] ERROR
6      TS18002: The 'files' list in config file 'tsconfig.json' is empty.
7
8ERROR in ./resources/js/components/Example.tsx
9Module build failed (from ./node_modules/ts-loader/index.js):
10Error: error while parsing tsconfig.json
11    at Object.loader (/var/www/html/node_modules/ts-loader/dist/index.js:17:18)
12
13webpack compiled with 2 errors and 1 warning

tsconfig.json

Laravel MixのTypescript Supportに記載のある通り、 tsconfig.jsonと型パッケージ(@types/*)が必要なので用意します。

1{
2  "compilerOptions": {
3    "target": "ES2015",
4    "module": "commonjs",
5    "strict": true,
6    "esModuleInterop": true,
7    "skipLibCheck": true,
8    "forceConsistentCasingInFileNames": true
9  },
10  "$schema": "https://json.schemastore.org/tsconfig",
11  "display": "Recommended"
12}

さらにReactのJSXを対応できるようにし、さらにvendor配下の検証は除外します。

1{
2  "compilerOptions": {
3    "target": "ES2015",
4    "module": "commonjs",
5    "strict": true,
6    "esModuleInterop": true,
7    "skipLibCheck": true,
8    "forceConsistentCasingInFileNames": true,
9    "jsx": "react"
10  },
11  "exclude": [
12    "vendor"
13  ],
14  "$schema": "https://json.schemastore.org/tsconfig",
15  "display": "Recommended"
16}

@types/*

関連する型パッケージをインストールします。

docker-compose exec app npm install @types/node @types/react @types/react-dom

ビルドして確認する

1docker-compose exec app npm run dev
2
3...
4Laravel Mix v6.0.49   
5                         
6✔ Compiled Successfully in 10969ms

TypeScriptでのビルドができるようになりました。

ここまでのコード(GitHub)

完成

Docker+Laravel+React+TypeScript構成の環境が完成しました。
必要に応じてPHP静的解析ツールのphpcsやphpmd、JSのESLintやJS Standardなどを導入してください。

完成形のコード(GitHub)

最終的な構成

1// 最終的な構成(この記事で編集していないLaravelのファイルは省略)
2fullstack-project/
3  ├ docker/
4  │  ├ nginx/
5  │  │  ├ Dockerfile
6  │  │  └ default.conf
7  │  ├ php/
8  │  │  ├ Dockerfile
9  │  │  └ php.ini
10  │  └ mysql/
11  │     ├ Dockerfile
12  │     └ my.conf
13  ├ src/
14  ├  ├ public/
15  |  |  ├ css/
16  |  |  ├  └ app.css
17  |  |  └ js/
18  |  |     └ app.js
19  |  ├ resources/
20  |  |  ├ js/
21  |  |  |  ├ components/
22  |  |  |  |  └ Example.tsx
23  |  |  |  ├ app.js
24  |  |  |  └ bootstrap.js
25  |  |  └ sass/
26  |  |     ├ _variables.scss
27  |  |     └ app.scss
28  |  ├ views/
29  |  |  └ welcome.blade.php
30  |  ├ .env
31  |  ├ tsconfig.json
32  |  └ webpack.mix.js
33  └ docker-compose.yml