Help us understand the problem. What is going on with this article?

Laravel mix 始めました

More than 1 year has passed since last update.

導入

これは エキサイト Advent Calender 2018 の記事です。

弊社でもPHPのフレームワークとしてLaravelを使用することが多くなってきましたが、
まだ何故かLaravel Mixについては本格的に使用しているプロジェクトは少ないように思います。

そこで、今更ながらLaravel Mixの導入を紹介したいと思います。

以下、試したときの主なバージョン
(社内環境ではなく、僕のローカルVMですがなんか微妙に古い。。。)

$ php -v
PHP 7.1.8 (cli) (built: Aug  9 2017 13:20:06) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies
    with Zend OPcache v7.1.8, Copyright (c) 1999-2017, by Zend Technologies

$ node -v
v8.11.4

$ npm -v
5.6.0

$ npm ls --depth=1 | grep laravel-mix
laravel-mix@2.1.14

$ composer info | grep laravel
laravel/framework                     v5.5.44  The Laravel Framework.

Laravel Mix とは?

https://laravel.com/docs/5.7/mix
https://laravel-mix.com/

An elegant wrapper around Webpack for the 80% use case.

と公式サイトにある通り、
80%のユースケースカバーしたWebpackの良い感じのラッパー
です。

そのうたい文句の通り、ややとっつきにくい印象のあるWebpackの設定をほぼ意識せず

  • jsのモジュール分割
  • babelによるトランスパイル
  • vueコンポーネントの利用
  • scssのコンパイル
  • js&cssのMinify

等の機能が簡単に使えます。

使い始めるには?

LaravelのプロジェクトでなくてもLaravel Mix単独でも使えますが、
Laravelの場合はデフォルトで必要最低限のnpmパッケージが設定されたpackage.jsonが付いてくるので
これを使うとすんなりインストールできます。

composernpmは使える前提です!

# Install Laravel
composer create-project --prefer-dist laravel/laravel sample1
cd sample1/
# Install npm packages in package.json
npm i

ただしLaravel 5.5LTS系を使う場合は、package.jsonで指定してるパッケージのバージョンが古いので
npm iする前にpackage.json内のdevDependenciesを書き変えてあげたほうが良いです。

やりたいこと

フロントエンドのビルド処理で必要な処理と言えば

  • jsのモジュール分割
  • scssの利用
  • js, cssのMinify。ただし本番環境だけ。
  • eslint, stylelint によるjsとscssのsyntax check
  • ブラウザキャッシュ対策のクエリ生成
  • 共通モジュールのvendor.js化

あたりが挙げられると思いますが、上記を実現するためのLaravel Mixの設定や必要なファイルを
紹介したいと思います。
以下のファイルをコピって来れば、そのまま使い始められるはず!。。。

必要なファイル

下記のファイル達をプロジェクトルートに置くor修正してください。

  • package.json
    • 入れてるパッケージはこんな感じ。あとはbootstrapとかjqueryとかvueとか。
    • npm -i パッケージ名 -D とかで入れてください
    • (足りてなかったらごめんなさい。。。)
package.jsonのdevDependenciesに入れるパッケージ
laravel-mix-eslint
laravel-mix-stylelint
eslint
eslint-loader
eslint-plugin-vue
stylelint
stylelint-config-recommended-scss
stylelint-scss
stylelint-webpack-plugin
  • webpack.min.js
    • こんな感じにしてます
    • 各ページ毎にjsとcssを分離するため、複数のエントリポイントを設定してます。
    • エントリポイントに設定したjsとscssファイルがあるかを見て、ある場合はビルドします。
    • webpackConfigのresolveを↓のようにすると、resource/assets/ 以下のファイルがjsやscssの中から読み込みやすくなります。
      • scssの@importとかなら@import "~sass/variables"resource/assets/sass/_variables.scssを読み込める
      • jsのrequire()でファイル探索するルートディレクトリにresource/assets/が追加される
    • npm run watch でeslintとstylelintが走るようになってます。
    • jqueryとかの共通で使うモジュールについては別ファイルにまとめるようにしてます。
    • productionビルド時だけブラウザキャッシュ対策のクエリが付きます。
webpack.mix.js
const mix = require('laravel-mix');
const path = require('path');
const fs = require('fs');

require('laravel-mix-eslint');
require('laravel-mix-stylelint');

/*
 |--------------------------------------------------------------------------
 | Mix Asset Management
 |--------------------------------------------------------------------------
 |
 | Mix provides a clean, fluent API for defining some Webpack build steps
 | for your Laravel application. By default, we are compiling the Sass
 | file for the application as well as bundling up all the JS files.
 |
 */

const sassOptions = (mix.inProduction()) ?
    {outputStyle: 'compressed'} : {outputStyle: 'nested'};

// ページ毎のjs,scssのエントリポイントをここに追加する
const entryPoints = [
    'index',
    'home',
    'mypage/index',
    'common'
];

for (let ep of entryPoints) {
    // ↓はLaravel 5.5用のpathなのでそれ以降のバージョンの場合は適宜修正してください。
    let jsPath = `resources/assets/js/${ep}.js`,
        sassPath = `resources/assets/sass/${ep}.scss`;

    try {
        fs.accessSync(path.resolve(jsPath));
        mix.js(jsPath, 'public/js');
    } catch (err) {}
    try {
        fs.accessSync(path.resolve(sassPath));
        mix.sass(sassPath, 'public/css', sassOptions);
    } catch (err) {}
}

mix.webpackConfig({
        output: {
            publicPath: '/hogehoge/'
        },
        resolve: {
            modules: [
                path.resolve('./resources/assets/'),
                'node_modules'
            ]
        }
    })
    .eslint()
    .stylelint({configFile: './.stylelintrc.js', files: ['**/*.scss']})
    .extract(['jquery', 'bootstrap', 'vue']);

if (mix.inProduction()) {
    mix.version();
}
  • .eslintrc.js
    • laravel-mix-eslint用
    • ルールはゆるめ。。。
.eslintrc.js
let rules = {
    "no-unused-vars": ["warn", {"vars": "local", "args": "none"}],
    "no-undef": "warn",
    "no-redeclare": "warn",
    "no-debugger": "warn",
    "no-console": "warn",
    "no-empty": "warn"
};
if (process.env.NODE_ENV == "production") {
    rules["no-debugger"] ="error";
    rules["no-console"] ="error";
}

module.exports = {
    extends: [
        "eslint:recommended",
        "plugin:vue/essential" // vue.js使ってなくてもlaravel-mix-eslintの仕様上必要
    ],
    env: {
        browser: true,
        es6: true,
        amd: true,
        jquery: true
    },
    parserOptions: {
        ecmaVersion: "2018"
    },
    rules
};
  • .stylelintrc.js
    • 推奨設定だけ。。
.stylelintrc.js
module.exports = {
    "extends": "stylelint-config-recommended-scss"
};

主なコマンド

Laravelの場合、package.jsonにデフォルトでscriptsが設定されているので
下記コマンドが使えます。
https://github.com/laravel/laravel/blob/master/package.json

開発時にファイルを監視して自動でビルドしてくれる

npm run watch

開発で1回だけビルドする

npm run dev

本番環境用にビルドする

npm run prod

テンプレート側

Laravel Mixでビルドしたアセットファイルを使う時はbladeテンプレート側でmix()ヘルパーを使います。
(productionビルド時のクエリとかを勝手に付けてくれる)

hoge.blade.php
<link href="{{ mix('/css/hello.css') }}" rel="stylesheet" type="text/css"/>
<script src="{{ mix('/js/hello.js') }}" type="text/javascript"></script> 

みたいな。

所感

まさに

An elegant wrapper around Webpack for the 80% use case.

↑その通り!と言った感じで、よく使うパターンのWebpackの設定が簡単に書けるようにラップされてて良く出来てるなぁと思いました。
(entryとloaderの概念がうまくまとまってるところとか。)

80%と言ってる通り、めっちゃ細かくWebpackの設定を詰めてたいとか、必ず最新のパッケージで揃えたい、みたいな場合だと
ちょっと物足りないかもしれませんが、
プラグインも割と簡単に書けそうなのでだいたいは事足りる気がします。

現状の感想としては、なにはなくともjs&cssはwebpack通すようにしたほうが色々便利なので
そういう場合にLaravel Mixならサクッと簡単な設定で導入できるので、新規でも既存プロジェクトでもおすすめです!

やり残したこと

  • もうちょっとplugin追加したい。。
  • tips. とか書ければよかった。。

長くなるし、力尽きたのでここで終わりにします。

明日のエキサイトAdvent Calenderもよろしくお願いします!

maa_bp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした