Parcelについてはこちら
dockerコンテナ内でParcelを使う際に詰まったので残しておきます。
症状
dockerコンテナ内にてparcelをwatchコマンド(監視モード)で動かすと、ブラウザ上で以下のエラーが出力されました。
Uncaught DOMException: Failed to construct 'WebSocket': The URL 'hoge://:33541/' is invalid.
dockerコンテナを起動して操作する際に入力したコマンドは以下の通りです。
docker run -it -v $(pwd):/app node bash # コンテナ内 npx parcel watch --public-url ./ index.html
解決策
まずdockerを起動時に-p
オプションでホストと共有するポートを設定します。ポート番号はすでに使ってあるもの以外なら何でも良いです。例として5050で起動します。
docker run -it -v $(pwd):/app -p 5050:5050 node bash
そしてparcel起動時に --hmr-port [docker起動時に指定したport番号]
オプションをつけます。先ほどと同様に5050で起動します。
また、hostも指定する必要があるのでhostnameを localhost
に指定しておきます。
npx parcel watch --hmr-port 5050 --hmr-hostname localhost --public-url ./ index.html
これで動くようになりました。
原因
watchモードではソースコードの変更を感知して以下の2つを行います。
- ビルド
- 変更した場所をブラウザに適応する(リロード無し)
変更箇所をブラウザに適応する機能はHot Module Replacement(HMR)と呼ばれており、内部でWebSocketの技術が使われています。
WebSocketはポートを一つ使って通信を行います。そしてこれはParcelの仕様なのかは把握していませんが、WebSocketを用いて通信をする際のポート番号が 起動する度に変わるようです(自分の環境では30000台で毎回変わりました)。
そしてdockerコンテナとホストでポートの共有はしていないため通信できずにエラーとなっていました。
--hmr-port
オプションでポート番号、 --hmr-hostname
でホスト名が指定できたので、dockerコンテナとうまく合わせることで動くようになりました。
おまけ
「いや……HMRとかいいです……もう毎回ブラウザリロードします」って人は--no-hmr
オプションで無効化できます。今回のエラーはこれでも解決します。
npx parcel watch --no-hmr --public-url ./ index.html