Windowsだとlaravel-mixのhotが動かないんです＞＜

Windows上で`yarn hot`したけど、うまくいかない場合の対処方法。

- 環境(2019/05/05前後でインストールした):
  - laravel-mix: 4.0.7
  - webpack-dev-server: ^3.1.14
  - laravel: 5.8
  - node: 10.13
  - docker for windows使いつつ、jsはwindows上でビルド

# TL;DR 

下記設定を追記する。

```webpack.mix.js
if (Mix.isUsing('hmr')) {
    mix.webpackConfig({
        output: {
            path: '/',
        },
        // webpackで生成してるもの以外をlaravelに取りに行く
        devServer: {
            proxy: {
                    '/':'http://localhost:8000/'
            },
        },
    });
}
```

# 説明

原因は生成先をwin絶対パスで指定したときに、dev-serverはwinパスで参照するが
webpackはposixパスに出力して、齟齬が出ているため。
なので、posixな絶対パスを指定して揃えて対応しています。

# 設定についての説明

`output.path`は保存場所の基準となるパスです。
laravel-mixのデフォルトでは`./public`の絶対パス(例:`C:\work\laravel\public`)や`C:\` (HMR時)が設定されます。
これにより、`mix.js('resources/js/app.js', 'js')`と書いたら`/js/app.js`に出力されることになります。
(なお、先頭のpublicは無視されるため`mix.js('resources/js/app.js', 'public/js')`と書いても同じ場所に出力されます)

ただ、このままだと`yarn dev`した時に意図しないところに保存されるので、HMR時のみ有効化しています。

その判別に使ってる`Mix.isUsing('hmr')`はコマンドライン↓の`--hot`の有無をチェックしています。
`"hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",`

正体はこれ↓です。
laravel-mix/src/config.js
https://github.com/JeffreyWay/laravel-mix/blob/ac70a860efd1f548582de97fca017d49113aa0ed/src/config.js#L17
なお、ここで使っている`Mix`は明示的にインポートしてる`mix`とは違って、
インポート元がグローバルに定義してしまっているので使えてしまっているものです。

ちなみに、`mix.webpackConfig()` はlaravel-mixで生成したwebpack.config.jsの内容を上書きしてくれるものです。

Readouble カスタム設定のマージ
https://readouble.com/laravel/5.8/ja/mix.html#custom-webpack-configuration

## 細かい話と改変する際の注意事項

### proxyについて

本件とは全く関係ないですが、「webpack-dev-serverはphpを解釈してくれないから変わりにindex.htmlを置くのだ―」という記事をどこかで見かけたので、念の為記載しました。

### devServer.writeToDisk は設定しても動かない

devServer.writeToDisk
https://webpack.js.org/configuration/dev-server/#devserverwritetodisk-

実ファイルも生成してくれるようにするオプションですが、今回、出力場所を変えている都合上、期待した場所とは違う場所にファイルが作られることになります。
なお、laravel-mix標準でも出力場所変更を行っているので、やはりうまく行きません。

laravel-mix/src/builder/WebpackConfig.js
https://github.com/JeffreyWay/laravel-mix/blob/ac70a860efd1f548582de97fca017d49113aa0ed/src/builder/WebpackConfig.js#L53-L73

### devServer.port は変えるな

devServer.port
https://webpack.js.org/configuration/dev-server/#devserverport

初回読み込み時は問題ないんですが、HMRで差分を取りに行ったときに、localhost:8080に読みに行こうして、動かなくなります。多分バグな気がします。

蛇足ですが、`hmrOptions`を設定していると、このdevServer.portを指定していることと同じ事になるので注意してください。

https://larapet.hinaloe.net/2017/03/12/hmr-laravel-mix/#i

### 蛇足: bladeファイルを編集したのに更新されない！

HMRはjsの話なのでbladeの変更には追従しません。
多分このあたりの設定で完全リロードがされると思います。
https://webpack.js.org/configuration/dev-server/#devserverwatchcontentbase

### うまく動かない環境があるかも

変更差分を取りに行くパスがちょっとおかしいです。具体的には↓のように`//`が入ります。
`http://localhost:8080//js/app.8f71ce5aef303e29563a.hot-update.js`

現状誰かが吸収してくれてるみたいなので、問題なく動いていますが
ブラウザ、もしくはwebpack-dev-serverのバージョンによってはうまく動かないかもしれません。

# もうちょっと詳しい状況説明

laravel-mixが`output.path`を決めている場所がここ↓なのですが、
`path.resolve`で(そのプラットフォームの)絶対パスを指定してしまっています。

laravel-mix/src/builder/webpackConfig.js
https://github.com/JeffreyWay/laravel-mix/blob/ac70a860efd1f548582de97fca017d49113aa0ed/src/builder/WebpackConfig.js#L61-L62

そして、Windowsな絶対パスを指定されるとdev-server側がうまく動作しないようです。
具体的には、webpackがlinuxパスの`/js/app.js`に出力し、
dev-serverがwinパス？の`C:\js/app.js`に取り行こうとして失敗している感じです。

本件とあまり関係ない気がしますが、このあたり胡散臭いです。
`path.posix.join`を使ってるので、`C:\js/app.js`みたいなゴッチャになったものを出力していますし…
ただ、ここをwin32に変えてもダメそう。

webpack-dev-middleware/lib/util.js
https://github.com/webpack/webpack-dev-middleware/blob/6d191d02f391fbac885e29f2520dcfc899e4c662/lib/util.js#L106

多分、dev-server側のパス処理をwebpack側に寄せれば良いと思います。
が、Windowsのパスで渡してるのに、linuxなパスに変換して書き込んでるwebpackはどうなの？という気もしますし…