laradockでLaravel-MixのHMR(Hot Module Replacement)を使う場合の設定

Webpack Dev ServerのHMR(Hot Module Replacement)は超便利。
更新するとすぐに反映してくれるしブラウザリロードも自動でしてくれます。
Laravelでは下記のコマンドで使えます。
※jsを埋め込む部分で関数mix()を使う必要があります。（後述）

```
npm run hot
```

ただし、仮想環境で実行した場合、ホストマシン側の書き込みが拾えず反映されません。
そういう環境用だと思いますが

```
npm run watch-poll
```

の様なタスクも用意されています。(内部的にはwebpackのwatch-pollオプション使用)
しかし、watchだとHMRに比べると即反映される感がないです。

ブラウザリロードしてみたらビルドが終わって無くて修正前のコードで動いて
それに気付かずに・・・なんてことも

しかし、最近HMRの場合でもpollingする方法を知ったので設定方法を紹介します。
今回、仮想環境はdocker-compose(laradock)を使用します。

# 環境の用意

## まず普通にLaravelプロジェクト作成

```shell
composer create-project --prefer-dist laravel/laravel hmr-laradock-example 5.5.*

cd hmr-laradock-example
```

## Laradock追加

```shell
git init
git submodule add https://github.com/Laradock/laradock.git
```

## Laradockをとりあえず動かす

初回は結構時間がかかる

```shell
cd laradock
cp env-example .env
docker-compose up -d nginx workspace
```

`http://localhost/` を開くととりあえずLaravelが動いている

## Laradockのworkspaceを作り直す

このままだとnpmも入ってないのでworkspaceを作り直す

```
docker-compose down
```

`.env`を書き換えてNode.jsをインストールさせる

```diff:laradock/.env
- WORKSPACE_INSTALL_NODE=false
+ WORKSPACE_INSTALL_NODE=true
```

このままでもいいがLTSのバージョンをインストールしてほしいので下記も修正

```diff:laradock/.env
- WORKSPACE_NODE_VERSION=stable
+ WORKSPACE_NODE_VERSION=lts/*
```

※もし特定バージョンが良ければバージョン番号を指定

```
- WORKSPACE_NODE_VERSION=stable
+ WORKSPACE_NODE_VERSION=v6.12.3
```

追加設定ファイルを読むように修正

```diff:laradock/.env
- COMPOSE_FILE=docker-compose.yml:docker-compose.dev.yml
+ COMPOSE_FILE=docker-compose.yml:docker-compose.dev.yml:../docker-compose.laradock.yml
```

HMR用にポート割り当て ※docker-compose.laradock.yml はLaravelプロジェクトルートに

```yaml:docker-compose.laradock.yml
version: "2"

services:

### Workspace Utilities Container ###########################

    workspace:
      ports:
        - "8080:8080"
```

upし直す

```shell
cd laradock
# buildしてからでもOK
# docker-compose build workspace
docker-compose up -d nginx workspace
```

# Laravel Mixの設定を修正

これがメインです。

## webpack.mix.jsの修正

ポートはdocker-compose.laradock.ymlで指定したもの
ポーリング間隔はとりあえず2000msに

```diff:webpack.mix.js
+ 
+ mix.webpackConfig({
+     devServer: {
+         host: '0.0.0.0',
+         port: 8080
+     },
+     watchOptions: {
+         poll: 2000,
+         ignored: /node_modules/
+     }
+ });
```

## workspaceコンテナからHMR実行

```shell
docker-compose exec --user=laradock workspace bash
# Windowsの場合はwinptyというのを使う必要があるらしい
# winpty docker-compose exec --user=laradock workspace bash

npm install
npm run hot
```

以上で設定は完了です。

# ためしてみる

トップページで試してみます。
Laravelプロジェクト生成時に作成されているExampleComponentを使用します。
※jsファイルを指定する際に使用する関数は`asset()`ではなく`mix()`です。

```diff:resources/views/welcome.blade.php
    <body>
+        <div id="app" class="flex-center position-ref full-height">
+            <example-component></example-component>
+        </div>
+        <script src="{{ mix('js/app.js') }}"></script>
```

http://localhost を開くと `resources/assets/js/components/ExampleComponent.vue` の内容が表示されます。

`resources/assets/js/components/ExampleComponent.vue`をいじってみると

![hmr-laradock-example.gif](https://qiita-image-store.s3.amazonaws.com/0/21396/e07ed973-5c23-39fa-9341-1659cee3b696.gif)


すぐに反映されます！

- ソース
  - https://github.com/boushi-bird/hmr-laradock-example

- 参照リンク
  - https://github.com/webpack/webpack-dev-server/issues/155
  - https://github.com/JeffreyWay/laravel-mix/blob/master/docs/quick-webpack-configuration.md