フロントエンド
webpack
laravelMix

Laravel Mixで作る良い感じのフロントエンドビルド環境

PHPのフレームワークLaravelに同梱されているビルドツールのLaravel Mixが、設定が楽ちんでSassやJs(ES2015記法)のビルドが簡単にできて良い感じだったので、少し手を加えて個人的にさらに良い感じの環境を作ってみました。

Laravel Mix自体はnpmのモジュールになっているので、単体でインストールしてLaravelを使わないプロジェクトでも使用可能です。

コードはGithubにあげてます。

https://github.com/KanDai/laravelmix-frontend


環境


  • OS: macOS Sierra

  • Node: 8.9.0


やったこと


ファイルをglobのワイルドカードで指定できるように

デフォルトではワイルドカードの指定が出来ないので、複数のファイルをビルドするときには下記のように書かないといけません。


webpack.mix.js

mix

.js('resources/assets/js/app.js', 'public/js')
.js('resources/assets/js/app2.js', 'public/js')
.sass('resources/assets/sass/app.scss', 'public/css')
.sass('resources/assets/sass/app2.scss', 'public/css');

これだと、生成したいファイルが増えるたびに足していかなければいけないので、globをインストールしてワイルドカードでファイル指定できるようにしました。


webpack.mix.js

const glob = require('glob')

// Compile all scss files directly under the sass directory
glob.sync('resources/sass/*.scss').map(function (file) {
mix.sass(file, 'public/assets/css')
})

// Compile all js files directly under the js directory
glob.sync('resources/js/*.js').map(function (file) {
mix.js(file, 'public/assets/js')
})


参考

https://qiita.com/katsunory/items/3585ab8072d74d234302


SASSのglob importを使う

Sass(SCSS)もglob importを使ってこんな感じで書きたいところ。


styles.scss

@import "base/*";

@import "modules/**/*";

webpack.mix.jsで mix.webpackConfig を呼んで、Webpackのオプションを拡張、 import-glob-loader を使う方法で動きました。


webpack.mix.js

mix.webpackConfig({

module: {
rules: [
{ // Allow .scss files imported glob
test: /\.scss/,
loader: 'import-glob-loader'
}
]
}
})

参考

https://qiita.com/kimama1997/items/f8f448ef6b14245e8a9d


PostCSSのプラグインを追加

PostCSSで拡張できるようだったので、何個かPostCSSのプラグインを追加してます。


  • CSS MQPacker → メディアクエリーの最適化

  • CSS Declaration Sorter → プロパティをソート


webpack.mix.js

mix.sass(file, 'public/assets/css')

.options({
processCssUrls: false,
postCss: [
require('css-mqpacker')(),
require('css-declaration-sorter')({
order: 'smacss'
})
],
autoprefixer: {
options: {
browsers: [
'last 2 versions',
]
}
}

autoprefixerは元々入ってますがここで設定も出来ます。


Prettierによるコード整形

最近話題のPrettierを導入してみました。

これもWebpackのオプションを拡張して prettier-loader を使っています。

prettierの設定もここに書いてます。jsでクォートはシングルクォート、行末のセミコロンをトル設定だけしてます。


webpack.mix.js

mix.webpackConfig({

module: {
rules: [
{ // JavaScript Prettier Setting
test: /\.js$/,
loader: 'prettier-loader',
options: { // Prettier Options https://prettier.io/docs/en/options.html
singleQuote: true,
semi: false
}
},
{ // Allow .scss files imported glob
test: /\.scss/,
loader: 'import-glob-loader'
},
{ // Sass Prettier Setting
test: /\.scss$/,
loader: 'prettier-loader',
options: {
parser: "postcss"
}
},
]
}
})

その他、元々入ってるBrowserSyncの設定や、通知、ソースマップの設定などもしてます(詳しくはREADMEに記載)。


コード全体


webpack.mix.js

// import .env / plugin

require('dotenv').config()
const mix = require('laravel-mix')
const glob = require('glob')

// Compile all scss files directly under the sass directory
glob.sync('resources/sass/*.scss').map(function (file) {
mix.sass(file, 'public/assets/css')
.options({
processCssUrls: false,
postCss: [
require('css-mqpacker')(),
require('css-declaration-sorter')({
order: 'smacss'
})
],
autoprefixer: {
options: {
browsers: [
'last 2 versions',
]
}
}
})
})

// Compile all js files directly under the js directory
glob.sync('resources/js/*.js').map(function (file) {
mix.js(file, 'public/assets/js')
})

mix
// Notification off
.disableNotifications()

// Setting browserSync
.browserSync({
// Using a vhost-based url
// proxy: process.env.MIX_SENTRY_DSN_PUBLIC || 'http://localhost:8080',
// Serve files from the public directory
server: {
baseDir: 'public',
index: 'index.html'
},
port: 8080,
proxy: false,
// Watch files
files: 'public/**/*'
})

// Added webpackConfig settings
.webpackConfig({
module: {
rules: [
{ // JavaScript Prettier Setting
test: /\.js$/,
loader: 'prettier-loader',
options: { // Prettier Options https://prettier.io/docs/en/options.html
singleQuote: true,
semi: false
}
},
{ // Allow .scss files imported glob
test: /\.scss/,
loader: 'import-glob-loader'
},
{ // Sass Prettier Setting
test: /\.scss$/,
loader: 'prettier-loader',
options: {
parser: "postcss"
}
},
]
}
})

// Generate sourcemap only for development environment
if (!mix.inProduction()) {
mix.sourceMaps()
}


実際、Laravel使ってるプロジェクトのフロントエンドで使ってますが、今のところ良い感じです。