1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Docker+create-react-appで環境構築すると編集内容が更新されない

Last updated at Posted at 2022-04-30

発生した問題

Docker上でcreate-react-appを使用して環境構築を行ったところ、ソースコードを編集してもページが更新されない問題が発生しました。
また、ブラウザを更新しても編集内容はページに反映されません。

現時点(2022/4/29)では、日本語の記事で「Docker+Reactの環境構築でホットリロードが効かない場合、docker-compose.ymlと.envファイルで「CHOKIDAR_USEPOLLING=true」を設定すると解決する。」等、似たような問題が見つかりましたが、いずれも自分の環境では解決しませんでした。

使用した開発環境

開発に使用した環境は下記になります。

OS:               Windows10 Pro
エディタ:       VSCode
コンソール:      powershell
パッケージマネージャ:Yarn

その他、依存関係は下記になります。

Docker:          20.10.14
Docker Compose:  2.4.1
yarn:            1.22.18
create-react-app:5.0.1
react:           18.1.0
react-dom:       18.1.0
react-scripts:   5.0.1
typescript:      4.6.4

問題の発生手順

ホスト側で下記ディレクトリ構成のファイルを用意します。

project/
 ├ docker-compose.yml
 └ Dockerfile
docker-compose.yml
version: "3.8"

services:
  web:
    build: .
    volumes:
      - .:/usr/src/app
    command: sh -c "cd front && yarn start"
    ports:
      - 3000:3000
Dockerfile
FROM node:16.15.0
WORKDIR /usr/src/app

ホスト側のdocker-compose.ymlのあるディレクトリに移動し、下記コマンドでプロジェクトを生成します。

powershell
docker-compose run --rm web `
 sh -c "yarn create react-app front --template typescript"

プロジェクトが生成されたら、先ほどと同じ階層でwebコンテナを立ち上げる下記コマンドを実行します。

powershell
docker-compose up -d

webコンテナ上のサーバーの準備ができたらhttp://localhost:3000にアクセスできることを確認します。

次に、ホスト側のApp.tsxの内容を書き換えて保存してブラウザを更新しますが、編集内容は反映されません。

解決策

下記サイトを参考に、webpackのwatchOptionsの設定を上書きすることで解決したのでその手順を紹介します。
CRA 5.0 fails to hot-reload in a docker container built On shoulders of _____ #11879

setup.jsでwatchOptionsを上書きする手順

まずは、ホスト側のpackage.jsonにあるscriptsstartの定義を下記のように書き換えます。

package.json
"scripts": {
    "start": "node ./setup && react-scripts start",
...

CRA 5.0 fails to hot-reload in a docker container built On shoulders of _____ #11879より引用)

次に、ホスト側のfrontフォルダ直下にsetup.jsを作成し下記を記載します。

setup.js
const fs = require('fs');
const path = require('path');

if (process.env.NODE_ENV === 'development') {
  const webPackConfigFile = path.resolve('./node_modules/react-scripts/config/webpack.config.js');
  let webPackConfigFileText = fs.readFileSync(webPackConfigFile, 'utf8');

  if (!webPackConfigFileText.includes('watchOptions')) {
    if (webPackConfigFileText.includes('performance: false,')) {
      webPackConfigFileText = webPackConfigFileText.replace(
        'performance: false,',
        "performance: false,\n\t\twatchOptions: { aggregateTimeout: 200, poll: 1000, ignored: '**/node_modules', },"
      );
      fs.writeFileSync(webPackConfigFile, webPackConfigFileText, 'utf8');
    } else {
      throw new Error(`Failed to inject watchOptions`);
    }
  }
}

CRA 5.0 fails to hot-reload in a docker container built On shoulders of _____ #11879より引用)

ホスト側のdocker-compose.ymlのある階層で、webコンテナを立ち上げる下記コマンドを実行します。

powershell
docker-compose up -d

webコンテナ上のサーバーの準備ができたらhttp://localhost:3000にアクセスできることを確認します。

この時点で解決した報告がありますが、自分の場合はホスト側のApp.tsxの内容を書き換えてブラウザを更新しても編集内容は反映されませんでした。

原因は、setup.jsの実行時点ではprocess.env.NODE_ENVundefinedになり、if (process.env.NODE_ENV === 'development') {...}の条件式から抜けているためでした。
※下記のようにログを出力してsetup.jsの条件式に入る直前のprocess.env.NODE_ENVの状態を確認しました。

setup.js
const fs = require('fs');
const path = require('path');

console.log('process.env.NODE_ENV', process.env.NODE_ENV); //追加
...

なので、setup.jsを下記の通りコメントアウトしてみます。

setup.js
const fs = require('fs');
const path = require('path');

// if (process.env.NODE_ENV === 'development') {
  const webPackConfigFile = path.resolve('./node_modules/react-scripts/config/webpack.config.js');
  let webPackConfigFileText = fs.readFileSync(webPackConfigFile, 'utf8');

  if (!webPackConfigFileText.includes('watchOptions')) {
    if (webPackConfigFileText.includes('performance: false,')) {
      webPackConfigFileText = webPackConfigFileText.replace(
        'performance: false,',
        "performance: false,\n\t\twatchOptions: { aggregateTimeout: 200, poll: 1000, ignored: '**/node_modules', },"
      );
      fs.writeFileSync(webPackConfigFile, webPackConfigFileText, 'utf8');
    } else {
      throw new Error(`Failed to inject watchOptions`);
    }
  }
// }

次に、ホスト側のdocker-compose.ymlのある階層で、webコンテナを立ち上げる下記コマンドを実行します。

powershell
docker-compose restart

webコンテナ上のサーバーの準備ができたらhttp://localhost:3000にアクセスできることを確認します。

画面が表示されたら、App.tsxの内容を書き換えて保存すると、数秒遅れて画面が更新されることが確認できました。

一応、最終的なディレクトリ構成を載せておきます。

project/
 ├ front/
 │ ├ node_modules/
 │ ├ public/
 │ ├ src/
 │ ├ .gitignore
 │ ├ package.json
 │ ├ README.md
 │ ├ setup.js
 │ ├ tsconfig.json
 │ ├ yarn.lock
 ├ docker-compose.yml
 └ Dockerfile

参考

CRA 5.0 fails to hot-reload in a docker container built On shoulders of _____ #11879

1
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?