Laravel(Laravel Mix) で JavaScript を良い感じに取り扱う
はじめに
Laravel で JavaScript を使うときのあれこれを調べた。
- 機能やページ単位で JS ファイルを作成した場合、どのように取りまとめや読み込みを行う?
- 本番環境向けのバージョニングはどうすればよい?
などなど。
TL;DR
- Laravel Mix を使うと JS などのアセットを良い感じに扱える
webpack.mix.js
でmix.js()
,mix.version()
,mix.browserSync()
などを使う- Blade では
mix('path/to/js')
で読み込んだり、@push
と@stack
で個別 JS を読み込むようにする
目次
環境・条件
1 | $ grep -i pretty /etc/os-release |
詳細
Laravel Mix, webpack について
まず前提として Laravel には Laravel Mix という JS や CSS(や SCSS/etc) を簡単に扱うための仕組みが用意されている。
参考: アセットのコンパイル(Mix) 5.7 Laravel
npm run dev
, npm run watch
, npm run prod
などを実行すると、依存関係の解決やバンドルなど良きに計らってくれる。
Input/Output の設定
webpack.mix.js
に Laravel Mix で処理して欲しいファイルや設定を記述する。JS の場合は mix.js()
で指定する。
参考: JavaScriptの操作
1 | // 以下に出力される |
上記のように書くと、各ファイルの依存関係解決などした上で、第2引数のディレクトリにファイルが出力される。
バージョニング
本番環境向け(ブラウザキャッシュ対策)としてハッシュを付けるには mix.version()
を実行すれば良い。以下のように編集する。読み込み側の話は後述。
参考: バージョン付け/キャッシュ対策
1 | mix.js('resources/js/app.js', 'public/js') |
ブラウザの自動リロード
開発環境で、ファイル編集したらブラウザの自動リロードが動作するようにしておくと良い。mix.browserSync()
を設定すれば良い。ドメイン('localhost'
の部分)は適宜設定。
参考: Browsersyncリロード
1 | mix.js('resources/js/app.js', 'public/js') |
mix.browserSync()
を書いておくと、npm run watch
でブラウザが起動するようになり、PHP や JS などを編集した場合に自動でリロードしてくれるようになる。
コンパイル済みアセットの読み込み(共通)
コンパイルされた JS などを読み込む場合は、Blade で mix('/path/to/file')
を使う。
共通的なファイルは、レイアウトファイルにそのまま記述すれば OK。
1 | ... |
開発環境(npm run dev
や npm run watch
)は /js/app.js
として、本番環境(npm run prod
)は /js/app.js?id=1234abcd...
として読み込んでくれる。
なお、?id=xxxx
はブラウザのキャッシュ対策として付くハッシュ値。実際に出力されるファイルの名前は npm run dev
でも npm run prod
でも変わらない(public/js/app.1234abcd...js
とかで出力されるわけではない)ので注意。
※勘違いしててしばらくハマった。
コンパイル済みアセットの読み込み(個別)
特定のページでしか動作させたくない JS を読み込みたい場合は、@push
と @stack
を使う。
参考: スタック
まずは個別 view ファイルを編集、@push
, @endpush
内で JS を読み込ませる。
1 |
|
@push('key')
の内容は、@stack('key')
で読み込まむことができる。レイアウトファイルに @stack('scripts')
を記述することで、各 view に @push
があれば読み込んでくれるようになる。
1 | ... |
JS をひとまとめにする
先ほどの例では、依存関係の解決などは行うが、JS ファイル自体は複数にわかれる方式になっている。
app.js
にひとまとめにしても問題ない(全てのページで JS が読み込まれても、他には影響を及ぼさない)のであれば、resources/js/app.js
で require
や import
で読み込ませる形にすると良い。
1 | require('./asset/xxxx'); |
その場合は webpack.mix.js
には app.js
と resources/js/app.js
で読み込んでない分だけを記述
1 | // xxxx, yyyy は resources/js/app.js で読み込ませているので、zzzz だけ記述 |
なお「全てのページで JS が読み込まれても、他には影響を及ぼさない」の記述の通り、JS 側でガード処理がない場合は、他ページで意図しない挙動になるかもしれないので注意。
1 | // NG |
1 | // OK (他にもっと良い方法あるかも) |
まとめ
- Laravel Mix を使うと JS などのアセットを良い感じに扱える
webpack.mix.js
でmix.js()
,mix.version()
,mix.browserSync()
などを使う- Blade では
mix('path/to/js')
で読み込んだり、@push
と@stack
で個別 JS を読み込むようにする
参考文献
- アセットのコンパイル(Mix) 5.7 Laravel
- Bladeテンプレート 5.7 Laravel
- Laravel Mix
- Laravel mix事始め - Qiita
- Versioning does not work - mix.version() · Issue #1751 · JeffreyWay/laravel-mix
- webpack.config の黒魔術をとく - Qiita
関連記事
- Laravel で Vue を利用する際の Tips/メモ
- Laravel で現在の URL 取得方法まとめ
- Laravel で Cookie を使う(参照/設定/削除)
- Laravel で PDF ファイルをブラウザで開く
- Laravel で withCount と having を使って絞り込み
- Laravel で「開始日時 < 終了日時」であることをバリデーションする
- JavaScript で URL のクエリパラメータを操作する方法
- jQuery Select2 で、初期値の設定と選択状態のクリア