イントロダクション

Laravel Elixir(エリクサー:万能薬)は、Laravelアプリケーションのための基本的なGulpタスクを定義しており、美しくスラスラかけるAPIを提供しています。ElixirはSassWebpackのような、一般的なCSSとJavascriptプリプロセッサーをサポートしています。メソッドのチェーンを使用し、Elixirでアセットパイプラインを流暢に定義できます。例を見てください。

elixir(function(mix) {
    mix.sass('app.scss')
       .webpack('app.js');
});

Gulpやアセットのコンパイルを始めようとして、混乱と圧倒を感じているならLaravel Elixirを気に入ってもらえるでしょう。しかし、アプリケーションの開発時に必要だというわけではありません。どんなアセットパイプラインツールを使用してもかまいませんし、使わなくても良いのです。

インストールと準備

Nodeのインストール

Elixirを始める前、最初にNode.jsとNPMを開発機にインストール済みであることを確認してください。

node -v
npm -v

Laravel Homesteadならデフォルトのままでも必要なものが全部そろっています。しかし、Vagrantを使っていなくても、ダウンロードページを読めば、NodeとNPMは簡単にインストールできます。

Gulp

次にGulpをグローバルNPMパッケージとして取得します。

npm install --global gulp-cli

Laravel Elixir

残っているステップはElixirのインストールだけです。新しくLaravelをインストールすると、ルートディレクトリにpackage.jsonがあることに気づくでしょう。PHPの代わりにNodeの依存パッケージが定義されている所が異なりますが、composer.jsonファイルと同じようなものだと考えてください。以下のコマンドで、依存パッケージをインストールしてください。

npm install

Windowsシステムで開発を行っている場合、もしくはWindowsをホストとして仮想マシンを実行しているときは、--no-bin-linksを有効にしてnpm installコマンドを実行してください。

npm install --no-bin-links

Elixirの実行

ElixirはGulp上に構築されていますので、端末でgulpコマンドを実行するだけでElixirタスクを走らせることができます。コマンドに--productionフラッグを付けることで、ElixirにCSSとJavaScriptファイルを圧縮するように指示できます。

// 全タスク実行
gulp

// 全タスクを実行し、全CSSとJavaScriptを圧縮
gulp --production

コマンド実行中は、その時点のイベントのサマリーを示す、きれいにフォーマットされた一覧が表示されます。

アセットの変更監視

gulp watchコマンドは、端末で動き続け、アセットの変更を監視し続けます。watchコマンド実行中にアセットを更新すれば、Gulpは自動的に再コンパイルします。

gulp watch

スタイルシート操作

プロジェクトルートにあるgulpfile.jsファイルに全Elixirタスクを構成します。Elixirタスクはアセットをどのようにコンパイルするか実際に定義するためにチェーンでつなげます。

Less

LessをCSSへコンパイルするにはlessメソッドを使用します。lessメソッドはLessファイルがresources/assets/lessに保存されていることを想定しています。コンパイルされたCSSはデフォルトでpublic/css/app.cssへ保存します。

elixir(function(mix) {
    mix.less('app.less');
});

さらに複数のLessファイルを一つのCSSファイルへ結合できます。この結果のCSSもpublic/css/app.cssとして保存します。

elixir(function(mix) {
    mix.less([
        'app.less',
        'controllers.less'
    ]);
});

コンパイル済みのCSSの出力先をカスタマイズしたい場合は、lessメソッドに第2引数で指定します。

elixir(function(mix) {
    mix.less('app.less', 'public/stylesheets');
});

// 出力ファイル名を指定する…
elixir(function(mix) {
    mix.less('app.less', 'public/stylesheets/style.css');
});

Sass

sassメソッドはSassをCSSへコンパイルします。Sassファイルはresources/assets/sassへ保存されていると想定します。このメソッドは次のように使用します。

elixir(function(mix) {
    mix.sass('app.scss');
});

lessメソッドと同様に複数のSassファイルを一つのCSSファイルへまとめることができ、結果のCSSを出力するディレクトリもカスタマイズできます。

elixir(function(mix) {
    mix.sass([
        'app.scss',
        'controllers.scss'
    ], 'public/assets/css');
});

パスのカスタマイズ

Laravelデフォルトのアセットディレクトリを使用することをお勧めしますが、異なるベースディレクトリを使う必要があるなら、ファイルパスを./から初めて指定してください。この指定により、Laravelへデフォルトのベースディレクトリの代わりに、プロジェクトルートを指示できます。

たとえば、app/assets/sass/app.scssファイルをコンパイルし、結果をpublic/css/app.cssとして出力したければ、sassメソッドを以下のように呼び出します。

elixir(function(mix) {
    mix.sass('./app/assets/sass/app.scss');
});

Stylus

StylusをCSSへ変換するにはstylusメソッドを使います。Stylusファイルは、resources/assets/stylusへ設置されると想定しています。以下のようにメソッドを呼び出します。

elixir(function(mix) {
    mix.stylus('app.styl');
});

Tip!! このメソッドの使用方法はmix.less()mix.sass()と同じです。

通常のCSS

通常のCSSスタイルシートを一つのファイルに結合したい場合は、stylesメソッドを使います。このメソッドに渡すパスはresources/assets/cssからの相対位置で、結果のCSSはpublic/css/all.cssに保存されます。

elixir(function(mix) {
    mix.styles([
        'normalize.css',
        'main.css'
    ]);
});

stylesメソッドの第2引数で、結果を出力するカスタムディレクトリかファイルを指定することも可能です。

elixir(function(mix) {
    mix.styles([
        'normalize.css',
        'main.css'
    ], 'public/assets/css/site.css');
});

ソースマップ

Elixirではソースマップは、デフォルトで有効になっており、コンパイルしたアセットを利用時に、ブラウザの開発者ツールでよりわかりやすいデバッグ情報が確認できます。コンパイルされた各ファイルごとに、同じディレクトリ中に同名の*.css.map*.js.mapファイルが存在しているのが見つかるでしょう。

アプリケーションのソースマップを生成したくなければ、sourcemaps設定オプションで無効にしてください。

elixir.config.sourcemaps = false;

elixir(function(mix) {
    mix.sass('app.scss');
});

スクリプト操作

ElixirはECMAScript 2015のコンパイル、モジュールのバンドル、圧縮、シンプルなJavaScriptファイルの結合など、JavaScript操作を手助けする多くの機能を提供しています。

ES2015をモジュールで書く場合、WebpackRollupを選択できます。両ツールについてよく知らなくても、心配ありません。Elixirが裏の面倒な仕事を一手に引き受けます。デフォルトではLaravelのgulpfilewebpackをJavaScriptのコンパイルに使っていますが、好きなモジュールバンドラーを自由に使用できます。

Webpack

webpackメソッドは、ECMAScript 2015をプレーンなJavaScriptへコンパイルし、ファイル結合するために使用します。この関数はresources/assets/jsディレクトリからの相対パスを引数に取り、public/js上へ結合済みの単一ファイルを生成します。

elixir(function(mix) {
    mix.webpack('app.js');
});

他の出力先やベースディレクトリを選ぶには、希望するパスを先頭の.に続け、アプリケーションルートからの相対パスとして指定してください。たとえば、app/assets/js/app.jspublic/dist/app.jsへコンパイルするには:

elixir(function(mix) {
    mix.webpack(
        './app/assets/js/app.js',
        './public/dist'
    );
});

Webpackの機能をより活用したい場合は、プロジェクトルートのwebpack.config.jsファイルを用意してください。Elixirが読み込み、ビルドプロセスへその設定を組み込みます

Rollup

Webpackと同様、RollupもES2015の次世代バンドラーです。rollup関数はresources/assets/jsディレクトリからの相対パスの配列を引数に取り、public/jsディレクトリへ単一ファイルを生成します。

elixir(function(mix) {
    mix.rollup('app.js');
});

webpackメソッドと同様に、入出力ファイルの場所をrollupメソッドに指定し、カスタマイズできます。

elixir(function(mix) {
    mix.rollup(
        './resources/assets/js/app.js',
        './public/dist'
    );
});

JavaScript

複数のJavaScriptファイルを結合し、単一ファイルにしたい場合は、scriptsメソッドを使います。自動的にソースマップを生成し、結合し、圧縮します。

scriptsメソッドは全パスをresources/assets/jsからの相対位置であると想定し、結果をデフォルトでpublic/js/all.jsに置きます。

elixir(function(mix) {
    mix.scripts([
        'order.js',
        'forum.js'
    ]);
});

複数のスクリプトを異なったファイルに結合したい場合は、scriptsメソッドを複数回呼び出してください。それぞれの結合の結果を出力するファイル名は、第2引数で指定します。

elixir(function(mix) {
    mix.scripts(['app.js', 'controllers.js'], 'public/js/app.js')
       .scripts(['forum.js', 'threads.js'], 'public/js/forum.js');
});

指定したディレクトリの全スクリプトを結合するには、scriptsInメソッドを使います。結果のJavaScriptはpublic/js/all.jsに設置されます。

elixir(function(mix) {
    mix.scriptsIn('public/js/some/directory');
});

Tip!! jQueryのように既にミニファイされている、複数のベンダーファイルを結合したい場合は、代わりにmix.combine()の使用を考慮してください。このメソッドはファイルを結合しますが、ソースマップ生成とミニファイを行いません。結果として、コンパイル時間はドラマティックに改善されます。

ファイルとディレクトリのコピー

copyメソッドはファイルとディレクトリを新しい場所へコピーするために使用できます。全操作はプロジェクトルートディレクトリからの相対位置で指定します。

elixir(function(mix) {
    mix.copy('vendor/foo/bar.css', 'public/css/bar.css');
});

バージョン付け/キャッシュ破壊

多くの開発者がコンパイルしたアセットにタイムスタンプや一意なトークンをサフィックスとして付加し、保存されている古いコードの代わりに真新しいアセットを強制的にロードさせています。Elixirはこれをversionメソッドで処理します。

versionメソッドはpublicディレクトリからの相対パスファイル名を受け取り、ファイル名に一意なハッシュを付けることでキャッシュを破壊します。たとえば生成されたファイル名はall-16d570a7.cssのような名前になります。

elixir(function(mix) {
    mix.version('css/all.css');
});

バージョンが付いたファイルを生成した後、ビューの中からLaravelのグローバルelixir関数を使い、ハッシュが付いたアセットをロードすることができます。elixir関数はハッシュをつけたファイル名を自動的に決定します。

<link rel="stylesheet" href="{{ elixir('css/all.css') }}">

複数ファイルのバージョン付け

versionメソッドへ配列で複数ファイルを渡すこともできます。

elixir(function(mix) {
    mix.version(['css/all.css', 'js/app.js']);
});

ファイルにバージョンが付けられたら、elixirヘルパー関数でハッシュが付いた実際のファイルへリンクを生成することができます。elixirヘルパー関数にはハッシュをつけていないファイル名を渡す必要があることを覚えておきましょう。

<link rel="stylesheet" href="{{ elixir('css/all.css') }}">

<script src="{{ elixir('js/app.js') }}"></script>

BrowserSync

browserSyncメソッドは、アプリケーションのローカルURLを含むproxy属性を持つ、JavaScriptオプジェクトを引数に取ります。その後、gulp watchを実行すれば、ポート3000(http://project.dev:3000)でWebアプリケーションへアクセスでき、ブラウザ自動同期を楽しめます。

elixir(function(mix) {
    mix.browserSync({
        proxy: 'project.dev'
    });
});