RitoLabo

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

  • 公開:
  • 更新:
  • カテゴリ: PHP Laravel
  • タグ: Laravel,JavaScript,Webpack,5.5,minify,Build,sass,node.js,NPM,LaravelMix,5.6

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できる環境を構築します。

アジェンダ
  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.js8系をリポジトリに追加
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/sass
test1.scss
test2.scss
laravel/resource/assets/js
test1.js
test2.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-envcross-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などに対してもコンパイルが行えますので、是非試してみてください。