Laravel 5.4 から採用されたフロントスクリプトのビルドツール、 Laravel Mix では、Webpack の HMR (Hot Module Replacement) がデフォルトで利用できます。
(HMRは)画面の再描画すること無しにJSの変更をブラウザに適用してくれる開発ツールです。
Hot Module Replacementの設定と仕組みを理解する – Qiita
Laravel でこれを利用すると、たとえば Vue コンポーネントの変更がリロード無しに反映できます。
もくじ
Install
Laravel 5.4 の新規プロジェクトを作成した場合、Mix やその HMR は npm install
を行えばデフォルトで利用できます。
※ もし cross-env あたりの参照でエラーが発生した場合、package.json を最新のものにあわせる(とくにscriptsを)ことで解決する場合があります。(mixや依存関係に破壊的変更があったため)
Laravel 5.3 以前からアップグレードした場合の導入手順は下記エントリーが参考になります。
HMR を利用した場合 mix でコンパイルしたアセットについては、 HMR 利用中は Laravel をホストしているサーバー(built-in serverやApache HTTPD, Nginx など) ではなく Webpack dev seerver からサーブされます。このため以下のような制約が生じます。
- 当該スクリプトの読み込みを
asset()
からmix()
に変える必要がある mix()
では HMR アセットは決め打ちで http://localhost:8080/ 以下からサーブされるため他で 8080 番ポートを使用していない必要がある開発環境がhttps
だと利用できないネットワークの他の端末を繋いで使えない- Laravel 5.5.33以降、かつLaravel-mix 2.0 以降でこれらの制約は回避が可能になりました。詳しくは記事末尾Q&Aへ。
※ 一時的に HTTP にするなりポートフォワーディングするなりで対処する手もあります。
Webpack dev server の起動
npm install
をして npm run hot
を実行すると、Webpack dev server が起動します。http://localhost:8080
で起動していることを確認してください。(上記の通り決め打ちで見に行くのでそれ以外で起動してしまっているとアセットが読み込めません)
また、レイアウト内等のスクリプトの読み込み先が mix()
で指定されていることを確認してください。
ブラウザで当該プロジェクトを開くとコンソールに WDS や HMR 関連のログが表示されているはずです。
例えばこの状態でVewコンポーネントを編集すると保存時にビルドが走り、当該コンポーネントのみが置換されます。それ以外のJS(たとえばapp.js)のようなfileを編集すると HMR で置換できないため、ページ自体がリロードされるものもあります。
この状態で HMR を止めてしまうとアセットが参照できずにフロントが死ぬので、npm run dev
など、ほかのビルドコマンドを走らせましょう。アセットの参照先が戻ります。
HMR の様子を軽く動画にしました。ご覧ください。
動画ではテンプレート内を編集していますが、ほかにコンポーネントのJSやスタイルとかだってもちろん HMR で即座に読み込まれます。
HMR を使用すればコンポーネントを微調整する度にいちいちリロードをし直す必要はありません。Mix で Vue を使用する場合は是非使用してください。文法エラーにも気付きやすいし。
[追記] Q&A
Q. Laravel Mix 0.8.8+ で HMR がうまく動きません
エラー例:
1 2 3 4 5 6 7 8 9 10 11 |
[HMR] Update failed: Error: Failed to execute 'open' on 'XMLHttpRequest': Invalid URL at XMLHttpRequest.open (http://localhost:3000/_debugbar/assets/javascript?v=1487955146:1150:25) at http://localhost:8080/js/app.js:28:22 at hotDownloadManifest (http://localhost:8080/js/app.js:22:19) at Object.hotCheck [as check] (http://localhost:8080/js/app.js:224:19) at check (http://localhost:8080/js/app.js:13901:14) at EventEmitter.<anonymous> (http://localhost:8080/js/app.js:13935:4) at EventEmitter.emit (http://localhost:8080/js/app.js:15101:17) at reloadApp (http://localhost:8080/js/app.js:13873:14) at Object.ok (http://localhost:8080/js/app.js:13802:3) at SockJS.sock.onmessage (http://localhost:8080/js/app.js:26879:22) |
(引用元:HMR Failed to execute ‘open’ on WIndwos 10 – Mix 0.8.8 #507)
A. デフォルトオプションで指定されている output.publicPath
の末尾スラッシュが本来必要なのが不足しているため。PR #624 で修正できてるはずなのでマージされてほしい。
マージされるまでの間はオプションを付けたして凌げる。
1 2 3 4 5 6 7 |
mix.webpackConfig({ output: { publicPath: 'http://localhost:8080/' }, }) .js('resources/assets/js/app.js', 'public/js') ... |
Q. 構文・コンパイルエラーをブラウザ上に表示したい
A. これもオプションで可能。
1 2 3 4 5 6 7 |
mix.webpackConfig({ devServer: { overlay: true, }, }) .js('resources/assets/js/app.js', 'public/js') ... |
Webpack dev server のオーバーレイを表示できる。
Q. https や任意のドメイン・ポートを指定したい
A. 上記の通り、Laravel 5.5.33以降、かつLaravel-mix 2.0 以降であればオプションで設定可能。
任意のポート・ドメイン
上記バージョンであれば
1 2 3 4 5 6 |
mix.options({ hmrOptions: { host: '10.1.1.2', port: '3030' } }); |
のようにオプションでホストとポートを指定できる、はず。
- mix#1246 Support for HMR on different hosts and ports
- laravel/framework#22826 [5.5] Supporting Laravel-Mix PR #1246, HMR w/ different Hosts and Ports
現時点ではドキュメントからは消されたままだが、当該PRは何れもリリース済みなので利用できる、はずだけどコードを見る限り少し怪しいような……
https
こちらについては Laravel 5.4.20+ (#18943) で既に利用可能になっていた模様。mixのバージョンは関係ない。(多分)
1 2 3 |
"scripts": { "hot": "NODE_ENV=development webpack-dev-server --inline --hot --https", } |
のように
--https をwebpack-dev-server の引数に追加することでhttpsでlistenする。(デフォルトでは自己署名証明書が利用される。Chromeで chrome://flags/#allow-insecure-localhost
でlocalhost の自己署名証明書を許可している場合はこれでもエラーは出ずにHMRできるようになるはず)
あるいは、
1 |
"hot": "NODE_ENV=development webpack-dev-server --inline --hot --https --key /path/to/server.key --cert /path/to/server.crt --cacert /path/to/ca.pem", |
のように任意の証明書を指定することも出来る。
詳しくはmixのドキュメントに掲載されている他、私のブログでも以前に紹介しているので参照。
“Laravel-Mix で HMR を利用する” への1件の返信