React Hot Loaderで開発をさらに加速する

こんにちは! Webエンジニアの吉田です。

先月16日にReact.js meetup × React Native meetupという180人ものエンジニアが集まる大規模なReact関連のイベントにてLT枠トップバッターで発表を行いました。

その時行った発表の「React Hot Loaderの導入」についてこれから詳しく説明します。

React Hot Loaderとは

従来のフロントエンド開発においてはBrowsersyncが一般的に用いられてきました。 Browsersyncはファイルの変更を監視して、自動でブラウザリロードを行い変更を反映させることができます。

しかしReact Hot Loaderはその利便性をさらに一歩前に進めます。

React Hot Loaderはファイル変更を監視して、stateを保持したままReactコンポーネントの変更をブラウザリロード無しで即座に反映する強力なロードモジュールです。

GitHub.io:React Hot Loader  

stateを保持したままReactコンポーネントの変更を反映をするということがピンと来ないかもしれませんので、まずは以下のデモ動画をご覧ください。

テキストボックスに入力した文字をstateに設定し、その下に表示するだけのシンプルなReactアプリケーションです。

左側のブラウザでテキストボックスに文字を入力した後、右側のエディターでcomponentを修正して保存します。

するとブラウザリロードが発生せずに即座に変更が反映されていることが分かります。 かつテキストボックス下の文字列は残ったままなので、stateの情報は保持されています。
もう一つデモをご覧ください。

今度は親コンポーネントが二つの子コンポーネントを持った状態で、色々とコンポーネントを変更してみます。

stateが保持されているので、子コンポーネントを一旦削除した後復元してもテキストボックスに入力した内容が表示されています。

このようにReact Hot Loaderはstateに依った処理を修正する際に非常に便利です。

なぜならブラウザをリロードすれば当然stateの内容は消えてしまうので、修正した箇所をテストする為にまずstateに設定するための手順を踏まなければいけません。

複数のパターンで修正をして確認したい時は余計に時間が掛かります。

React Hot Loaderを使用すればその手順は不要になるので、よりスピーディーに開発することが出来ます。

React Hot Loaderを導入してみよう

では実際に導入してみましょう。

前述したようにReact Hot Loaderはあくまでロードモジュールです。 従ってWebpackなどのビルドツールでロードして使用することが前提となります。

今回紹介するのはgulp+Webpack+Browsersyncを組み合わせて実現する一例です。

GitにReact Hot Loaderのサンプルプロジェクトを挙げましたので、こちらのソースをcloneしてください。

https://github.com/endam/react-hot-loader-sample
sample1とsample2は上記のデモ動画で使用したReactアプリケーションです。 違いはsrcディレクトリ下のコンポーネントだけでその他の設定は全く同じです。

まずはsample1ディレクトリ直下に移動してnpmもしくはyarnでパッケージをインストールしましょう。

react-hot-loaderもパッケージの一つなので併せてインストールします。 次にgulpでファイル監視+自動更新用のタスクを追加します。  

ポイントとしてBrowsersyncのmiddlewareの設定で webpack-dev-middlewarewebpack-hot-middlewareが必要となります。

またwebpack-dev-middlewareとwebpack-hot-middlewareそれぞれに webpack.config.jsに基づいて作ったwebpackのbundlerを渡さなければいけません。

webpack-dev-middlewareのpublicPathの設定はwebpack.config.jsのoutput.publicPathと同じにして構いませんので そちらのパスを参照しています。

そして一番肝となるwebpack.config.jsです。

entryではエントリーポイントとなるjsの他にwebpack/hot/dev-serverwebpack-hot-middleware/clientを設定してください。

modulesでReact Hot Loaderのモジュールをロードする設定を忘れないようにしましょう。

もう一つ忘れがちなのがpluginsの設定。 ここでnew webpack.HotModuleReplacementPlugin()の設定をしないと正常に動きませんのでご注意を。

ここまで設定したら後は動かすだけです。 gulp watchでgulpタスクを起動してReact Hot Loaderが機能していることを確認しましょう。

実践編

これまで説明したのは最も基本的なReact Hot Loaderの設定です。 しかし実際の現場での開発は、この設定だけでは足りない場合があると思います。

最も想定されるのは次の二つのケースです。

  • 複数のエントリポイントに対応したい
  • DockerやVagrant等の仮想環境で動かしたい

これらのケースの対応方法について説明します。

複数のエントリポイントに対応する

複数のエントリポイントに対応する為には少し特殊な書き方をします。

このようにエントリポイントごとに配列で webpack-dev-middlewarewebpack-hot-middlewareを設定しなければいけません。 (まさかエントリポイントごとに設定するとは思わなかったので、調査した時はかなりハマってしまいました汗)
ただ2,3個のエントリポイントであればこの書き方でもまだ良いですが、多数のエントリポイントがあった場合あまりに冗長的になってしまいます。
そのような場合は例えば以下のようにentry設定用のオブジェクトを動的に生成する関数を用意することをお勧めします。  

DockerやVagrant等の仮想環境で動かす

Dockerの場合

Docker for Mac/Windowsを使用する場合、設定はシンプルです。

例えばこのようにホストの3006番ポートからゲストの同じく3006番ポートにフォワーディングしているコンテナがあるとします。

BrowsersyncではDockerコンテナのポートフォワーディングを行っている3006番のポート番号を設定します。

設定はこれだけです。 後はDockerコンテナ内で同じ様にgulpタスクを実行してブラウザのhttp://localhost:{フォワーディングしているポート番号}にアクセスして確認してみてください。

Vagrant(VirtualBoxやVmware)の場合

Vagrantと言うよりはプロバイダのVirtualBoxやVmwareの仮想マシンで環境を作成したい場合ですね。 この場合はプロキシを設定する必要があります。

最初にhttp-proxy-middlewareというパッケージを新たにインストールします。
npm install http-proxy-middleware -D or yarn add http-proxy-middleware -D

次にgulpタスクでのBrowsersync設定を変更します。

http-proxy-middlewareをimportして、プロキシの設定を行います。

const proxy = proxyMiddleware('/', {target: 'http://{ゲストOSのIPアドレス}'); の行で{ゲストOSのIPアドレス}の部分を変更してください。

生成したproxyオブジェクトをBrowsersyncのmiddlewareに設定します。

さらに重要なのがwebpack-dev-middlewareのwatchOptionでpollオプションを有効にしてポーリングを行うようにします。

この設定が無いとVirtualBoxではファイル変更を検知してくれません。

実践編の内容はsample3にまとめています。

sample3のデフォルトはDocker環境を想定した設定となっていますが、VirtualBox等の仮想マシンで動かす場合はgulpfile.babel.jsでコメントアウトしている箇所を外した上でゲストOSのIPアドレスを設定して頂くと動作しますので宜しくお願いします。

最後に

React Hot Loaderは私の現場で今年2月頃に導入したばかりですが、やはり開発がよりスムーズになったので導入して良かったと思いました。

React.js meetup × React Native meetupで発表した時はご存知の方もまだ多くなかったので、これから他の現場でも徐々に使われるんじゃないかと期待をしています。

現場でReactを使用している方はぜひ使用してみてください。

それでは良いReact開発ライフを!