アセットのコンパイル(Laravel Elixir)
イントロダクション
Laravel Elixir(エリクサー:万能薬)は、Laravelアプリケーションのための基本的なGulpタスクを定義しており、美しくスラスラかけるAPIを提供しています。ElixirはSassやWebpackのような、一般的な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をモジュールで書く場合、WebpackかRollupを選択できます。両ツールについてよく知らなくても、心配ありません。Elixirが裏の面倒な仕事を一手に引き受けます。デフォルトではLaravelのgulpfile
はwebpack
をJavaScriptのコンパイルに使っていますが、好きなモジュールバンドラーを自由に使用できます。
Webpack
webpack
メソッドは、ECMAScript
2015をプレーンなJavaScriptへコンパイルし、ファイル結合するために使用します。この関数はresources/assets/js
ディレクトリからの相対パスを引数に取り、public/js
上へ結合済みの単一ファイルを生成します。
elixir(function(mix) {
mix.webpack('app.js');
});
他の出力先やベースディレクトリを選ぶには、希望するパスを先頭の.
に続け、アプリケーションルートからの相対パスとして指定してください。たとえば、app/assets/js/app.js
をpublic/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'
});
});