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
下記設定を追記する。
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を指定していることと同じ事になるので注意してください。
蛇足: 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はどうなの?という気もしますし…