Laravel-mixでReact, sass, bootstrap4環境を用意してみました。

Larave-mixとは

Githubに書いてあるように、 80%くらいのユースケースで使えるWebpackのエレガントなラッパーです。

“An elegant wrapper around Webpack for the 80% use case.”
https://github.com/JeffreyWay/laravel-mix

Webpackは非常に人気があり便利です。 npm trends でもwebpackの人気がわかります。 が、設定が結構大変だったりします。 (まあ、gulpやbrowserifyなども凝った設定をすれば大変なのでwebpackだけに限ることではないですが)

Laravel-mixを使えば、今時のツール群を簡単に使えます。 babelによるトランスパイル、vueやreactのビルド、sassのコンパイルなどなど。

使い方

詳細は公式ドキュメントを参照。

webpack.mix.jsに設定ファイルを記述していくことになります。 文法が洗練されているだけでなく、 難しいことは内部で隠蔽してくれているので、 結構直感的に使えます。

仕組み

内部で以下のことをやっています。(ざっくり)

  1. webpack.mix.jsを読み込む
  2. 必要なパッケージのインストール
  3. webpack用の設定ファイルの生成

詳しくは今度記事にまとめようと思います。

例1. React, sassのビルド

1. npm設定

npm init -y

# 必須のパッケージ
npm install laravel-mix cross-env --save-dev

# Reactインストール、sassのコンパイルにnode-sassを使用するのでインストール
npm install react react-dom

参考: https://github.com/JeffreyWay/laravel-mix/blob/master/docs/installation.md

2. webpack.mix.js作成

// webpack.mix.js
const mix = require('laravel-mix');

mix
    .setPublicPath('public')
    .js('js/common.js', 'public/js')
    .react('js/app.jsx', 'public/js')
    .sass('sass/app.scss', 'public/css')
    .sourceMaps();

setPublicPath
ビルド先をpublicフォルダに設定。

.js(js/common.js, public/js)
第一引数のcommon.jsをビルドし、public/jsに入れてくれます。
この時、babelでトランスパイルしてくれます。

.react('js/app.jsx', 'public/js')
同様に、第一引数のapp.jsxをビルドし、public/jsに入れてくれます。
reactメソッドのため、内部ではbabelのpresetとしてreactが設定され、ビルドに必要なbabel-preset-reactを勝手にインストールしてくれます。

.sass('sass/app.scss', 'public/css')
sass/app.sassをビルドし、public/cssへ入れてくれます。

.sourceMaps()
Production環境でない場合、ソースマップを生成してくれます。

3. package.json編集

package.jsonが、以下の状態になっているはずです。

{
  "name": "laravel-mix-test",
  "version": "1.0.0",
  "description": "",
  "main": "webpack.mix.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "cross-env": "^5.1.5",
    "laravel-mix": "^2.1.11"
  },
  "dependencies": {
    "react": "^16.3.2",
    "react-dom": "^16.3.2"
  }
}

scripts欄に以下を書きます。(laravelのpackage.jsonを参考)

{
  "name": "laravel-mix-test",
  "version": "1.0.0",
  "description": "",
  "main": "webpack.mix.js",
  "scripts": {
    "dev": "NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
    "watch": "NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
    "hot": "NODE_ENV=development webpack-dev-server --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
    "production": "NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "cross-env": "^5.1.5",
    "laravel-mix": "^2.1.11"
  },
  "dependencies": {
    "react": "^16.3.2",
    "react-dom": "^16.3.2"
  }
}

そして以下のコマンド実行。

npm run watch

そうすると、reactのビルドに必要なbabel-preset-reactを自動でインストールし、ビルドしてくれます。 (babel-preset-reactが増えてます)

{
  "name": "laravel-mix-test",
  "version": "1.0.0",
  "description": "",
  "main": "webpack.mix.js",
  "scripts": {
    "dev": "NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
    "watch": "NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
    "hot": "NODE_ENV=development webpack-dev-server --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
    "production": "NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "babel-preset-react": "^6.24.1",
    "cross-env": "^5.1.5",
    "laravel-mix": "^2.1.11"
  },
  "dependencies": {
    "react": "^16.3.2",
    "react-dom": "^16.3.2"
  }
}

例2. React, sass, bootstrap4のビルド

bootstrap4はjquery, popper.jsが必要なので、インストールします。

npm install --save bootstrap jquery popper.js

bootstrapのcssをimpotする必要があります。 以下のパスをインポートします。

// app.scss
@import "node_modules/bootstrap/scss/bootstrap";

これでビルドできます。

npm run watch

例3. ブラウザキャッシュ

versionメソッドを呼ぶことで、ビルドしたファイルのmd5を計算して、mix-manifest.jsonに書き出してくれます。

// webpack.mix.js
const mix = require('laravel-mix');

mix
    .setPublicPath('public')
    .js('js/common.js', 'public/js')
    .react('js/app.jsx', 'public/js')
    .sass('sass/app.scss', 'public/css')
    .version()
    .sourceMaps();

こんな感じのものができます。

{
    "/js/common.js": "/js/common.js?id=38218e7107c8e94de3ca",
    "/css/app.css": "/css/app.css?id=248e71c659bfbb9472f2",
    "/js/app.js": "/js/app.js?id=8be389eed1c24eab832f",
    "/js/manifest.js": "/js/manifest.js?id=7c0a19fb1a3afbe0a6cb"
}

mix-manifest.jsonにある名前を利用することで、ブラウザキャッシュを効率的に利用できます。
(更新していないものは、名前が変わりません)

例4. 外部ライブラリをまとめる

extractメソッドの引数に、外部ライブラリの配列を渡すことで、ビルド時にvendor.jsにまとめてくれます。 これにより頻繁に更新する(キャッシュをクリアする)他のjavascriptのサイズが小さくなります。

// webpack.mix.js
const mix = require('laravel-mix');

mix
    .setPublicPath('public')
    .js('js/common.js', 'public/js')
    .react('js/app.jsx', 'public/js')
    .sass('sass/app.scss', 'public/css')
    .extract([
        'bootstrap',
        'popper.js',
        'jquery',
        'react',
        'react-dom',
    ])
    .version()
    .sourceMaps();