1. Home
  2. PHP
  3. Laravel
  4. Laravel Mix(Webpack)を導入しsassやJavaScriptをコンパイル/minifyする

Laravel Mix(Webpack)を導入しsassやJavaScriptをコンパイル/minifyする

  • 公開日
  • 更新日
  • カテゴリ:Laravel
  • タグ:Laravel,JavaScript,Webpack,minify,Build,sass,node.js,NPM,LaravelMix
Laravel Mix(Webpack)を導入しsassやJavaScriptをコンパイル/minifyする

Laravel を使い WEB アプリを構築するということは、PHP に限らず HTML, CSS, そして JavaScript も使う事になります。 CSS に関しては、最近は sass や scss などで記述し、そこから CSS ファイルにビルドするという流れも今や主流です。

sass や scss を使う理由としては、記述をネストや変数でまとめられたり、よりプログラマティックに記述できたりと、エンジニアにとっては良い事ばかりですが、それらを使うには、sass ファイルや scss ファイルを、最終的に CSS ファイルにコンパイルしなければなりません。

コンパイル(compile)とは、ざっくり言うと「ソースコードを変換dする」という事です。ここで言う「sass → CSS 」「scss → CSS 」です。

もう一つ、ビルド(build)という言葉もあります。コンパイルとは少し意味が違い、こちらは単純にソースやファイルをまとめたりなど、いわゆる「組み立てる」部分を指しており、厳密にはコンパイルとは違う意味合いになります。

という事で今回は、Laravel にビルドツールである Laravel Mix(Webpack) を導入して、sass や JavaScript をコンパイル・ビルドしたり minify できる環境を構築します。

Contents

  1. 開発環境
  2. node.js と NPM の確認
  3. node.js と NPM のインストール
  4. Laravel Mix のインストール
  5. テストファイルの作成
  6. Laravel Mix の設定
  7. build と minify を行う
  8. ビルド・コンパイルに失敗する場合
    1. pngquant のビルドエラー
    2. Vagrant&Windows 環境のシンボリックリンクエラー

開発環境

今回の開発環境は以下の通りです。

  • Linux CentOS 7
  • Apache 2.4
  • PHP 7.1/7.2
  • Laravel 5.x

Laravel のバージョンについては 5.6/5.5 にて動作確認済みです。

Laravel のルートディレクトリを「laravel/」とします。

node.js と NPM の確認

Webpack を走らせる為には、「Node.js 」と「NPM 」が導入されている事が前提となります。

以下のコマンドを叩き、インストールされているか確認します。 バージョンが表示されていれば、導入されているという事になります。

# node.js の導入確認
node -v

# 実行結果
[demo@localhost ~]# node -v
-bash: node: command not found

# NPM の導入確認
npm -v

# 実行結果
[demo@localhost ~]# npm -v
-bash: npm: command not found

両方ともインストールされていませんでしたので、導入する必要がありそうです。

node.js と NPM のインストール

基本的に node.js をインストールすれば NPM も一緒にインストールされますので、node.js の導入を行っていきます。

最新版を入れようと思いますので、まずは、以下の yum コマンドを叩き、インストールできる Node.js のバージョンを確認します。

# インストールできる node.js の確認
yum list nodejs

# 実行結果
[root@localhost ~]# yum list nodejs                                                                                                                                  
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * base: download.nus.edu.sg
 * epel: mirrors.ustc.edu.cn
 * extras: ftp.tsukuba.wide.ad.jp
 * remi-safe: mirrors.mediatemple.net
 * updates: ftp.tsukuba.wide.ad.jp
Available Packages
nodejs.x86_64            1:6.11.3-1.el7            epel

この記事を書いている時点で最新(推奨)版は「8.9.0 」それに対してこの環境のリポジトリだと「6.11.3 」です。 ちょっと古いので、新しくしてからインストールします。

以下の curl コマンドを叩いて、リポジトリに 8 系を追加します。

# node.js の 8 系をリポジトリに追加
curl -sL https://rpm.nodesource.com/setup_8.x | bash -

# 実行結果
[root@localhost ~]# curl -sL https://rpm.nodesource.com/setup_8.x | bash -

## Installing the NodeSource Node.js 8.x repo...


## Inspecting system...

+ rpm -q --whatprovides redhat-release || rpm -q --whatprovides centos-release || rpm -q --whatprovides cloudlinux-release || rpm -q --whatprovides sl-release
+ uname -m

## Confirming "el7-x86_64" is supported...

+ curl -sLf -o /dev/null 'https://rpm.nodesource.com/pub_8.x/el/7/x86_64/nodesource-release-el7-1.noarch.rpm'

## Downloading release setup RPM...

+ mktemp
+ curl -sL -o '/tmp/tmp.JCXfssSPqQ' 'https://rpm.nodesource.com/pub_8.x/el/7/x86_64/nodesource-release-el7-1.noarch.rpm'

## Installing release setup RPM...

+ rpm -i --nosignature --force '/tmp/tmp.JCXfssSPqQ'

## Cleaning up...

+ rm -f '/tmp/tmp.JCXfssSPqQ'

## Checking for existing installations...

+ rpm -qa 'node|npm' | grep -v nodesource

## Run `yum install -y nodejs` (as root) to install Node.js 8.x and npm.
## You may also need development tools to build native addons:
##   `yum install -y gcc-c++ make`

追加したら、再度 yum コマンドを叩きます。

# 導入可能な node.js のバージョンを確認する
yum list nodejs

# 実行結果
[root@localhost ~]# yum list nodejs
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * base: ftp.tsukuba.wide.ad.jp
 * epel: ftp.riken.jp
 * extras: ftp.tsukuba.wide.ad.jp
 * remi-safe: mirror.innosol.asia
 * updates: ftp.tsukuba.wide.ad.jp
Available Packages
nodejs.x86_64         2:8.9.0-1nodesource         nodesource

これで、yum コマンドから 8.9 がインストールできるようになったので、以下のコマンドを叩いて、node.js をインストールします。

# node.js NPM 開発ツール をインストールする
yum -y install nodejs gcc-c++ make

インストールが完了したら、改めてバージョン確認のコマンドを叩いてみます。

# node.js のバージョンを確認する
node -v

# 実行結果
[root@localhost ~]# node -v
v8.9.0

# node.js のバージョンを確認する
npm -v

# 実行結果
[root@localhost ~]# npm -v
5.5.1

これで無事 node.js と NPM の導入が完了しました。

Laravel Mix のインストール

次に、Laravel Mix を走らせる為の依存パッケージのインストールを行います。

laravel ルートディレクトリへ移動し、以下のコマンドを叩きます。

# laravel ルートディレクトリへ移動
cd /path/to/laravel

# 依存パッケージのインストール
npm install

インストールが完了したら、Laravel Mix の導入は完了です。

もし Vagrant などの仮想環境を使っていて npm install がこける場合は --no-bin-links オプションを付けて実行してみてください。

# 仮想環境でエラーが出る場合は --no-bin-links オプションを付ける
npm install --no-bin-links

テストファイルの作成

ビルドが出来るようになりましたが、現時点ではまだビルドするものがないので、ここで作成しておきます。

厳密には、Laravel 側でデフォルトで指定されているものがあるので、ビルド自体は走ります。が、、それではあまり意味がない(なにより感動しない!)のでテストファイルを作りましょう。

まずはテストでビルドする為の sass ファイルと Javascript ファイルを作成します。
以下に記す位置に、それぞれのファイルを作成します。

laravel/resource/assets/sasstest1.scsstest2.scsslaravel/resource/assets/jstest1.jstest2.js ビルドの成果がわかりやすいように、2つずつファイルを作成しています。
ここで重要なのが、ビルドする為のファイルは public ディレクトリではなく、laravel/resource/assets/ に作成している点に注意してください。

それぞれのファイルの内容はこんな感じです。

laravel/resource/assets/sass/test1.scss

$background-color: #ffdab9;
$color: #000080;
$margin: 10px 20px 30px 40px;

body {
background-color: $background-color;
}

p {
color: $color;
}

.test-margin {
margin: $margin;
}

laravel/resource/assets/sass/test2.scss

.aaa {
padding: 10px;
}

.bbb {
  .button {
position: absolute;
    top: 0;
    padding: 10px 15px;
    cursor: pointer;
  }
  .button:hover {
color: #f7ecb5;
  }
}

.ccc {
display: block;
  text-indent: 30px;
  line-height: 30px;
  font-size: 12px;
  color: #999999;
  border: none;
}

laravel/resource/assets/js/test1.js

function test(string, number) {
var ret = '';
  ret = string + 'test';

  var num = '';
  num = number * 12;

  ret += ret + ' : ' + num;

  return ret;
}

laravel/resource/assets/js/test2.js

window.onload = function() {
test('ビルドのテスト', 24);
};

HTML に適用させるわけではないので内容に意味はありません。 今回は、この4つのファイルをビルドしていきます。

また、laravel/resource/assets/配下に「build 」というディレクトリを作成しておいてください。

最終的なファイル構造は以下になります。

laravel
├─ resources
│   ├─ assets
│   │   ├─ build // ← ココ
│   │   ├─ js
│   │   │   ├─ test1.js // ← ココ
│   │   │   └─ test2.js // ← ココ
│   │   └─ sass
│   │   │   ├─ test1.scss // ← ココ
│   │   │   └─ test2.scss // ← ココ

Laravel Mix の設定

次に、さきほど作成した4つのファイルをビルドするように指定していきます。

laravel/webpack.mix.js
にその設定を記述していくので、開きます。 初期段階では以下のようになっているはずです。

let mix = require('laravel-mix');

/*
 |--------------------------------------------------------------------------
 | 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.
 |
 */

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

これを、以下のように記述します。

let mix = require('laravel-mix');

/*
 |--------------------------------------------------------------------------
 | 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.
 |
 */

mix
  // ビルドしたsassをそれぞれ開発側buildディレクトリへ出力
  .sass('resources/assets/sass/test1.scss', '../resources/assets/build/css/')
  .sass('resources/assets/sass/test2.scss', '../resources/assets/build/css/')
  // buildディレクトリに出力したcssファイルを、app.cssというファイルに1つにまとめてpublicディレクトリへ出力する
  .styles(
    [
      'resources/assets/build/css/test1.css',
      'resources/assets/build/css/test2.css'
    ],
    'public/css/app.css'
  )
  // app.jsというファイルに1つにまとめてpublicディレクトリへ出力する
  .js(
    [
      'resources/assets/js/test1.js',
      'resources/assets/js/test2.js'
    ],
    'public/js/app.js'
  );

まず、開発を進めていく前提として sass ファイルにおいては

  1. ビルドした CSS ファイルを開発側の専用ディレクトリへ出力する
  2. ビルドされた CSS ファイルを1つにまとめ、公開ファイルとして public ディレクトリへ出力する

という流れで記述しています。
(js ファイルについてはワンクッション置くメリットがあまりないのでそのまま公開ディレクトリに出力しています)

記述によってはダイレクトに public ディレクトリへ出力も可能なのですが、きちんと開発していく事を考えた時には、この流れが個人的にはおすすめです。理由は

  • タイプや機能別に出力ファイルを分ける必要が出た場合に対応できる
  • 公開ファイルを minify した場合に、ビルドされていないファイルを開発側で保持しておける
  • AMP ページを生成する際にスタイルの再利用が出来る

などありますが、例えば最終的に、フロントと管理画面側で大きく2つにまとめた css ファイルを出力したいと考えた時に、build 側ではもう少し細かく分けた(機能別など)ファイルで出力しておき、公開ディレクトリへ出力する際に1つにまとめる。等の手段が取れるからです。
(とは言いつつこの辺は個人の好き好きあると思うので、慣れたら自身の最適をみつけていってください)

build と minify を行う

ではいよいよ実際にビルドを行っていきます。
Laravel Mix で予め定義されている build コマンドは2つです。

# build
npm run dev

# build & minify
npm run production

前者は、ビルドを行い、後者はビルドと同時に minify を行います。
minify というのは、ソースコードを最小の構成に再構築する事です。これによってファイルサイズが抑えられ、読み込みスピードのアップと転送量の縮小に貢献します。

※もしビルドが失敗する場合は、以下コマンドを叩いて cross-env と cross-spawn のグローバルインストールを行ってみてください。

# npm run dev でエラーになる場合は以下を叩いてグローバルインストールを行う
npm -g install cross-env cross-spawn

ビルドを行うと、それぞれ「webpack.mix.js 」に指定したディレクトリへファイルが出力されます。最終的には以下のファイル構成になります。

├─ public
│   ├─ css
│   │   └─ app.css // ← 公開ディレクトリへ出力された css ファイル
│   ├─ js
│   │   └─ app.js // ← 公開ディレクトリへ出力された js ファイル
│
├─ resources
│   ├─ assets
│   │   ├─ build
│   │   │   └─ css
│   │   │        ├─ test1.css // ← build によって生成された css ファイル
│   │   │        └─ test2.css // ← build によって生成された css ファイル
│   │   ├─ js
│   │   │   ├─ test1.js // ← 作成した js ファイル
│   │   │   └─ test2.js // ← 作成した js ファイル
│   │   └─ sass
│   │       ├─ test1.scss // ← 作成した sass ファイル
│   │       ├─ test2.scss // ← 作成した sass ファイル

ビルドを行った結果、ソースコードはどうなったかを、public ディレクトリに出力された css ファイルで確認してみます。

body {
background-color: #ffdab9;
}

p {
color: #000080;
}

.test-margin {
margin: 10px 20px 30px 40px;
}


.aaa {
padding: 10px;
}

.bbb .button {
position: absolute;
  top: 0;
  padding: 10px 15px;
  cursor: pointer;
}

.bbb .button:hover {
color: #f7ecb5;
}

.ccc {
display: block;
  text-indent: 30px;
  line-height: 30px;
  font-size: 12px;
  color: #999999;
  border: none;
}


2つのファイルが統合され、1つにまとめられたソースコードとして出力されている事が確認できます。

ちなみに、これが minify した(npm run production)ソースコードの場合は以下のようになります。

body{background-color:#ffdab9}p{color:navy}.test-margin{margin:10px 20px 30px 40px}.aaa{padding:10px}.bbb .button{position:absolute;top:0;padding:10px 15px;cursor:pointer}.bbb .button:hover{color:#f7ecb5}.ccc{display:block;text-indent:30px;line-height:30px;font-size:12px;color:#999;border:none}

改行やスペースが削除され、最小限のファイル容量になっています。

ビルド・コンパイルに失敗する場合

npm run dev を叩いた時に、エラーが出て失敗する場合は、エラーメッセージから原因を特定する必要がありますが、そのいくつかをここで紹介しておきます。

pngquant のビルドエラー

npm install 時のエラーメッセージに以下のようなエラーが出ていたら、pngquant のビルドエラーです。

> pngquant-bin@4.0.0 postinstall /path/to/laravel/node_modules/pngquant-bin
> node lib/install.js

  ⚠ The `/path/to/laravel/node_modules/pngquant-bin/vendor/pngquant` binary doesn't seem to work correctly
⚠ pngquant pre-build test failed
ℹ compiling from source
✔ pngquant pre-build test passed successfully
✖ Error: pngquant failed to build, make sure that libpng-dev is installed
    at Promise.all.then.arr (/path/to/laravel/node_modules/pngquant-bin/node_modules/bin-build/node_modules/execa/index.js:231:11)
    at <anonymous>
    at process._tickCallback (internal/process/next_tick.js:188:7)

この場合は、linux に libpng-devel が導入されていない為に pngquant がビルド出来ずエラーになっているので、これをインストールする事で解決します。

# libpng-devel のインストール
yum -y install libpng-devel

インストールできたら、再度 npm install を行います。

Vagrant&Windows 環境のシンボリックリンクエラー

そもそもシンボリックリンクが正しく動いていない場合があります。 以下の記述を Vagrantfile に記述し、vagrant reload した後、再度 npm install --no-bin-links を叩いてください。

config.vm.provider "virtualbox" do |v|
    v.customize ["setextradata", :id, "VBoxInternal2/SharedFoldersEnableSymlinksCreate/v-root", "1"]
end

まとめ

以上で作業は完了です。 Lravel Mix は webpack を包括したビルドシステムですが、非常に簡単に導入が行えるので、すぐにでも sass ファイルを用いた開発が行えます。

ちなみに、フレームワーク無しで webpack を導入しようと思うと、これよりも手間がかかります。

また、今回は sass を例にして解説を行いましたが、webpack は React をはじめ ES2015 ・ ES2016 等、Babel などのトランスパイラの必要な JS などに対してもコンパイルが行えますので、是非試してみてください。

Author

rito

  • Backend Engineer
  • Tokyo, Japan
  • PHP 5 技術者認定上級試験 認定者
  • 統計検定 3 級