こんにちは!のせっちです。
今回は、laravel-mixを使った、マークアップ環境の構築を解説します。
当ブログでは、gulp x webpackを使ったマークアップ環境の構築方法を解説していますが、今回はlaravel-mixのみで構築します。
laravel-mixとはいえ、laravelは不要で単独で使うことができます。
当記事で解説した内容はgithubリポジトリを公開しております。ご自由にどうぞ。
内容が微妙に違う場合は、githubが最新です。
laravel-mixとは?
ざっくり説明すると、
- アセットをコンパイル、バンドルするツール。
- Laravelのためのツールだが、単独で使うことも可能。
- webpackのラッパーで、webpackより簡単に書ける。
以下のような方にはピッタリなツールです。
- Gulp環境を持っているが、更新されていないパッケージが多いのが気になる。
- webpackで環境構築したいが、複雑でよくわからない。
- Gulp x webpackの組み合わせではエラー対処なのが複雑になるので一本のツールで完結したい。
- とにかく簡単に構築できるものをちょうだい!
公式のドキュメントでとても簡潔に説明されていますが、実はgithubのreadmeを参考にするのがオススメです。(npm scirptあたりでエラーでます。)
本記事のゴール
下記の環境を設定します。
- SCSSのコンパイル
- jsのバンドル
- jQuery($)を使えるようにする
- ローカルサーバーを起動
早速作ってみる
前提として、nodeが必要です。
『推奨版』をダウンロードしましょう。
node.jsがダンロードできたら、
ターミナルを開いて、下記を入力します。
mkdir my-app && cd my-app
npm init -y
npm install laravel-mix --save-dev
簡単に解説すると、
mkdir my-app && cd my-app
my-appというディレクトリを作成(mkdir)し、my-appに移動(cd)
npm init -y
package.jsonができます。
npm install laravel-mix --save-dev
laravel-mixをインストールします。
次に、設定ファイル(webpack.mix.js)を作ります。
ターミナルに下記を入力してください。
touch webpack.mix.js
こういうディレクトリ構成になります。
では、jsのコンパイルをやってみましょう。
src/app.jsからdist/bundle.jsにコンパイルします。
webpack.mix.jsに下記を記述します。
const mix = require('laravel-mix');
mix.setResourceRoot('dist');
mix.js('src/app.js', 'dist');
src/app.jsから、distフォルダに書き出す設定を書きました。
src/app.jsを作成して、試しにスクリプトを書きます。(なんでもOK)
alert('hello');
ここまでできたら、ターミナルで下記を実行します。
npx mix
そうすると、dist/app.jsができました。たったこれだけで、コンパイルできるんですね。
mix-manifest.jsonというファイルもできますが、今回は使いません。
SCSSのコンパイル設定をしていく
scssファイルのコンパイルも簡単です。
const mix = require('laravel-mix');
mix.setResourceRoot('dist');
mix
.js('src/js/app.js', 'dist/js'); // パスを変更しています。
// 下記を追加
mix
.sass('src/scss/app.scss', 'dist/css/')
.options({
processCssUrls: false,
autoprefixer: {
options: {
grid: true,
}
},
});
一気に書きました。下記のような設定になっています。
- src/scss/app.scssからコンパイルし、dist/css/app.cssを作成
- processCssUrls: false でurl()の変換をさせない
- autoprefixerでベンダープレフィックスを付与。(grid: trueでIE11でのgrid使用できるように)
autoprefixerの設定(browserslist)は、webpack.mix.jsに書かず(非推奨なので)package.jsonか、.browserslistrcに記述します。お好きな方でどうぞ。
書き方が微妙に違います。
last 1 version,
IE 11,
Android >= 6
"browserslist": [
"last 1 version",
"IE 11",
"Android >= 6"
]
では、コンパイルしてみましょう。
ベンダープレフィックスが付きそうなものを書いてみます。
.hoge{
transform: translate(50%, 50%);
}
そしてnpxコマンド
npx mix
結果、
.hoge {
-webkit-transform: translate(50%, 50%);
transform: translate(50%, 50%);
}
よさそうです。
足りないライブラリを勝手にインストールしてくれる。
npx mixをしたときにSCSSのコンパイルに必要なライブラリを勝手にインストールしてくれたと思います。エラーを返さずに勝手に解決してくれるので便利ですよね!
ダウンロードされなかった場合は、ターミナルで下記を入力します。
npm i -D sass-loader postcss
おまけ:laravel-mixで使うnpxコマンド3種
npxはnodeをインストールすると自動で使えるようになるコマンドです。
laravel-mixでは下記を使います。
- npx mix : developmentモードでコンパイル
- npx mix -p : productionモードでコンパイル
- npx mix watch : watchモード(後ほど設定します)
SCSSを更に便利に(PostCssオプションを使う)
PostCssオプションを使って、SCSSのコンパイルを更に便利にしていきます。
今回の例では、下記を設定してみましょう。
- 任意の順番に並べる(css-declaration-sorter)
- メディアクエリ をまとめる(css-mqpacker)
- カスタム変数を使えるように(postcss-custom-properties)
今回はパッケージを先にインストールします。
npm i -D css-mqpacker css-declaration-sorter postcss-custom-properties
npm i -Dはnpm install –save-devと同じです。
webpack.mix.jsにPostCssオプションを追加します。
const mix = require('laravel-mix');
mix.setResourceRoot('dist');
mix
.js('src/js/app.js', 'dist/js');
mix
.sass('src/scss/app.scss', 'dist/css/')
.options({
processCssUrls: false,
autoprefixer: {
options: {
grid: true,
}
},
// 下記を追加
postCss: [
require('css-mqpacker')(),
require('css-declaration-sorter')({
order: 'alphabetical' // smacss, concentric-css
}),
require('postcss-custom-properties')({
preserve: false
})
]
});
ローカルサーバーを起動
ローカルサーバーを起動して、更新がある度に自動でリロードしてくれる機能を追加します。
これも数行追加するだけなので簡単です。
const mix = require('laravel-mix');
mix.setResourceRoot('dist');
// 下記を追加
mix.browserSync({
server: {
baseDir: '.',
index: 'index.html'
},
port: 8081,
proxy: false,
files: '**/*'
});
// 省略
では、早速起動します。
index.htmlを用意して、何か適当に書いておいてください。
npx mix watch
はい、また足りないパッケージを勝手にインストールしてくれました。
その後、もう一度npx mix watchでローカルサーバーが起動します。
ダウンロードされなかった場合は、ターミナルで下記を入力します。
npm i -D browser-sync-webpack-plugin browser-sync
sourcemapsを作る
下記を追加するだけです。
const mix = require('laravel-mix');
mix.setResourceRoot('dist');
mix.setPublicPath('dist');
mix.webpackConfig({ devtool: "source-map" }); // 追加
mix
.js('src/app.js', 'dist/js')
.sourceMaps(); // 追加
mix
.sass('src/scss/app.scss', 'dist/css/')
.sourceMaps() // 追加
// 省略
laravel-mixの標準機能なので、パッケージは不要です。
@importを手軽に
通常@importはファイル名まで指定しないといけないのですが、ワイルドカードを使って一気に読み込めるようにします。
npm i -D import-glob-loader
設定を追加します。
const mix = require('laravel-mix');
mix.setResourceRoot('dist');
mix.setPublicPath('dist');
mix.webpackConfig({ devtool: "source-map" });
mix.webpackConfig({
devtool: "source-map",
// 下記を追加
module: {
rules: [
{
test: /\.scss/,
loader: 'import-glob-loader'
}
]
}
});
// 省略
これでscssファイルを一気に読み込めるようになりました。(下記のような感じ)
@import "setting/**";
@import "foundation/**";
@import "mixin/**";
@import "layout/**";
@import "component/**";
@import "project/**";
@import "utility/**";
@import "external/**";
こういう系で何かやりたいことを調べるときは、普通にググるよりもGithubの issueを調べるのはかなりオススメです。サクッと解決策が書かれていたりします。
import-glob-loaderについてもGithub issueから見つけました。
https://github.com/JeffreyWay/laravel-mix/issues/241
jQueryの$を使用可能にする。
下記を追加します。
const mix = require('laravel-mix');
mix
.js('src/js/app.js', 'dist/js/')
// 下記を追加
.autoload({
jquery: ['$', 'window.jQuery']
})
// 省略
折角なのでjQueryを書いてみる。(飛ばしてOK)
折角なので、npmからjQueryをインストールして使えるようにしちゃいましょう。
npm i jquery
これで、jQueryを使う準備ができました。
何か書いてみましょう。
src/js/module/jquery.jsを作って、src/js/app.jsで読み込んでみます。
$(window).on('load', () => {
console.log('hello');
});
$を使いたかっただけなので特に意味のないコードです。
これを、src/js/app.jsにimportします。
import './module/jquery';
では、サーバーを立ち上げてみて確認します。
npx mix watch
検証ツールからコンソールを開くと「hello」と表示されているはずです。
おまけ:mix-manifest.jsonを出力したくない場合
mix-manifest.jsonはcash busting時に使えるのですが、基本的にlaravel環境でないと使えない(mix関数が必要)ので、laravel外の環境では使わないかもしれません。
mix関数を自分で定義して使う方法があるようです。
(試したのですが、うまくできなかったのでわかる人はコッソリ教えてください… m(_ _)m )
https://github.com/JeffreyWay/laravel-mix/issues/1635
使わない人にとっては不要なので、mix-manifest.jsonを出力しない方法をご紹介します。
const mix = require('laravel-mix');
const fs = require('fs'); // 追加
mix
.js('src/app.js', 'dist/js')
.sourceMaps()
// 下記を追加
.then(() => {
fs.unlinkSync('mix-manifest.json');
});
mix-manifest.jsonを消して、もう一度npx mixしてみましょう!
rm -rf mix-manifest.json
npx mix
mix-manifest.jsonは書き出されなくなります。
最終的な設定ファイル
最終的にこうなりました。
const mix = require('laravel-mix');
const fs = require('fs');
mix.setResourceRoot('dist');
mix.webpackConfig({
devtool: "source-map",
module: {
rules: [
{
test: /\.scss/,
loader: 'import-glob-loader'
}
]
}
});
mix.browserSync({
server: {
baseDir: '.',
index: 'index.html'
},
port: 8081,
proxy: false,
files: '**/*'
});
mix
.js('src/app.js', 'dist/js')
.autoload({
jquery: ['$', 'window.jQuery']
})
.sourceMaps()
.then(() => {
fs.unlinkSync('mix-manifest.json');
});
mix
.sass('src/scss/app.scss', 'dist/css/')
.sourceMaps()
.options({
processCssUrls: false,
autoprefixer: {
options: {
grid: true,
}
},
postCss: [
require('css-mqpacker'),
require('css-declaration-sorter')({
order: 'alphabetical'
}),
require('postcss-custom-properties')({
preserve: false
})
]
});
{
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"devDependencies": {
"browser-sync": "^2.26.13",
"browser-sync-webpack-plugin": "^2.2.2",
"css-declaration-sorter": "^6.0.2",
"import-glob-loader": "^1.1.0",
"css-mqpacker": "^7.0.0",
"laravel-mix": "^6.0.10",
"postcss": "^8.2.4",
"postcss-custom-properties": "^11.0.0",
"sass": "^1.32.4",
"sass-loader": "^8.0.2"
},
"dependencies": {
"jquery": "^3.5.1"
},
"browserslist": [
"last 1 version",
"IE 11",
"Android >= 6"
]
}
余計な記述は消しておきました。
設定は以上です。お疲れ様でした。
追記:object-fitのpolyfill付与を自動化する方法を解説しました。
下記の記事で、object-fitのpolyfillを自動付与する方法を解説しました。合わせてどうぞ!
object-fitはとても便利なcssですが、IEには対応していませんので、polyfillの設定が必要です。
まとめ
・laravel-mixを使うと短い記述でマークアップ環境を構築できる。
・説明はよくわからなかったけど使いたい、という人はgithubリポジトリをどうぞ。