30
26

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.

VSCode の Remote Container で React開発環境を構築する

Last updated at Posted at 2022-04-11

VSCode の Remote Container で React を開発できればいいな、と。で、やってみたら create-react-app は激重だし、 Hot Reload もしない。 npm start, yarn start は遅い。こんなもの使いもんになるか!と思っていました。

でもポイントを押さえればローカル開発と遜色ないパフォーマンスで Hot Reload 可能な環境を作ることができます。しかもめっちゃ簡単です。ちょっと docker の知識は必要です。

環境

1. フォルダを作る

docker-compose を使用するので、フォルダ名が docker の images 名と関係があります。あまり適当な名前にはしないほうがいいです。プロジェクト名などがいいでしょう。

2. Dockerfile

作ったフォルダ直下に Dockerfile を作ります。Node.js の ver.16 をベースにします。

FROM node:16

ENTRYPOINT tail -f /dev/null

3. docker-compose.yml

同じく作ったフォルダ直下に docker-compose.yml を作ります。
services のすぐ下の react 、というのはサービス名です。好きに変えて構いませんが、この名前も image 名に関係があります。(フォルダ名_サービス名という image名になる)

docker-compose.yml
version: '3.8'
services:
  react:
    build: .
    ports:
      - 3000:3000
    volumes:
      - .:/workspace:cached
      - home:/home
volumes:
  home:

4. devcontainer.json

devcontainer.json というのは、リモート接続するための構成ファイルなのですが、手動で作成する必要はありません。
まずフォルダを VSCode で開き、画面左下の Remote アイコンをクリックします。もしアイコンがない場合はプラグインがインストールされていません。

image.png

インストールしましょう。
https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.vscode-remote-extensionpack

ダイアログが開くので、Add Development Container Configuration Files...を選択します。
image.png

From 'docker-compose.yml' を選択します。

image.png

devcontainer.json ファイルが自動的に生成されます。このファイルの "workspaceFolder" の値を次のように編集します。この編集は必須ではありませんが、これで Remote Container に接続時に開く既定のディレクトリは /home になります。やっておいたほうがいいです。

devcontainer.json
	"workspaceFolder": "/home",

5. 接続

準備完了です。Remote Container へ接続します。画面左下の Remote Container のアイコンをクリックします。
image.png

Reopen in Container を選択します。
image.png

しばらく待つと(最初は数分待ちます)、ステータスバーが次のように変わります。接続している状態です。

image.png

6. create-react-app を試す

ターミナルを開きましょう。/home が開くと思います。
早速 create-react-app で React アプリを作りましょう。私は yarn 派なので次のコマンドです。

yarn create react-app myapp --template typescript

ローカルで作るときと比べてそれほど変わらない時間で作成は完了すると思います。

実行します。

yarn start

ブラウザが立ち上がって、http://localhost:3000 でいつものように動きます。

image.png

適当にソースを変えて保存してみてください。いつものように自動的にReloadします。

- Learn React
+ Learn React !!!!!

image.png

7. この環境を使う時の注意

なぜ高速なのか

VSCode の Remote Container は既定でContainer 側の /workspace と、手順1で作ったフォルダを同期します。つまり、フォルダ内部に Explorer で何かファイルを作ると、Remote Container の /workspace でそれを参照・編集ができます。
これは docker の Bind Mount という機能です。この機能は大変便利ですがこのフォルダへの読み書きがすごく遅いのです。

そして既定の devcontainer.json のままの場合、remote 接続すると /workspace を既定の場所として接続します。そのため暗黙的に /workspace 配下に React アプリを作ってしまい、create-react-app が死ぬほど遅いのです。(私の環境では30分近くかかりました)

なのでこの手順では /workspace 配下ではなく、自然と /home に React プロジェクトを作るように devcontainer.json を修正しました。

node_modules を Bind Mount から外すことで高速化する手順を Web に Tips として見つけることができると思いますが、考え方はそれと同じです。しかしこの方法では Hot Reload ができないという問題が残ります。

なぜ Hot Reload できるのか

Web上を検索すると docker container 内の React を Hot Reload するための方法がいくつか紹介されています。主に環境変数を次のように設定する、という記載が見つかると思います。

CHOKIDAR_USEPOLLING=true

create-react-app が ver.5になってから、この設定では Hot Reload は動かなくなりました。原因は定かではありませんが、少なくとも私が確認した限りでは /workspace 配下に作った React App は ディレクトリの Watch が上手く動かないようです。Bind Mount が影響しているのだと思われます。
この手順では /home 配下に React プロジェクトを作っていますので、設定不要で Hot Reload ができます。

データの永続化

この手順では /home 配下は docker volume として永続化しています。(docker-compose.yml の Volumes の箇所)そのため、docker の image や container を作り直しても /home 配下のデータが消えることはありません。

もしこの環境が不要になり、 image と container を削除しても Volume は残り続けます。手動で削除が必要です。

docker volume の一覧

docker volume ls

docker volume の削除

docker volume rm <VOLUME NAME>

コンテナとの紐づけが無くなった docker volume をまとめて削除

docker volume prune

ソースがホストから見えないのは困る?

Remote Container で実装したソースは GitHub などの 外部リポジトリなどへ push することがほとんどだと思いますので、ホストからソースが見えなくても困ることはないと思います。

もしかしたら build した結果をホスト側で必要とする場合があるかもしれません。その場合は build 後に 結果を /workspace へコピーすれば良いです。
package.json の scripts に 1行追加します。

package.json
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "postbuild": "rm -rf /workspace/build/ && cp -r build /workspace/build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },

追加したのは postbuild の行です。このように postbuild という名前の key でスクリプトを定義すると build 後に実行されます。(prebuild という名前の key であれば build 前に実行します)

こうすれば build 実行後に build 結果が /workspace へコピーされます。
build します。

root@362aa11b8796:/home/myapp# yarn build
yarn run v1.22.18
$ react-scripts build
Creating an optimized production build...
Compiled successfully.

File sizes after gzip:

  46.21 kB  build/static/js/main.1ef0a932.js
  1.78 kB   build/static/js/787.d3befce1.chunk.js
  541 B     build/static/css/main.073c9b0a.css

The project was built assuming it is hosted at /.
You can control this with the homepage field in your package.json.

The build folder is ready to be deployed.
You may serve it with a static server:

  yarn global add serve
  serve -s build

Find out more about deployment here:

  https://cra.link/deployment

$ rm -rf /workspace/build/ && cp -r build /workspace/build
Done in 12.23s.

確認します。

root@362aa11b8796:/home/myapp# ls -al /workspace/build/
total 36
drwxr-xr-x 1 root root 4096 Apr 11 05:22 .
drwxrwxrwx 1 root root 4096 Apr 11 05:22 ..
-rw-r--r-- 1 root root  605 Apr 11 05:22 asset-manifest.json
-rw-r--r-- 1 root root 3870 Apr 11 05:22 favicon.ico
-rw-r--r-- 1 root root  644 Apr 11 05:22 index.html
-rw-r--r-- 1 root root 5347 Apr 11 05:22 logo192.png
-rw-r--r-- 1 root root 9664 Apr 11 05:22 logo512.png
-rw-r--r-- 1 root root  492 Apr 11 05:22 manifest.json
-rw-r--r-- 1 root root   67 Apr 11 05:22 robots.txt
drwxr-xr-x 1 root root 4096 Apr 11 05:22 static

Exploer からも確認します。build フォルダがあります。
image.png

build フォルダの中身です。
image.png

良さそうですね。

30
26
0

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
30
26

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?