Laravel5でcssやjs、画像などをバージョニングしたくてElixirを使ってみた

Webアプリケーションを開発しててよくあるのが、画像とかcssとかを更新してもブラウザがキャッシュしちゃってて
なかなかクライアント側に反映されないなんてことがあります。

解決方法としては色々あると思いますが、その一つにファイル名を変えてしまうというのがあります。

例えば
> app.css

こういうcssがあったとしたら
> app-001.css

こんな名前にして、cssを更新するたびに001の部分も変えていくわけです。


ただしこれを**自分で書き換えていくのは超しんどい**です。



けれど**Laravel5でWebアプリケーションをつくるなら**、Laravel Elixirという機能を利用することで**簡単に解決してくれる**事がわかったので使ってみました。


**Laravel Elixirを使えばcssに限らずpublicディレクトリ下のファイルを簡単にバージョニングして、テンプレート側を書き換えることなく更新する事が出来ます。**

# Laravel Elixirを利用するための準備
Elixirはnodeモジュールとして提供されているため、いくつかインストールする必要があります。
## Node.js
nvmを利用してnodejsのインストール

```
$ cd ~
$ curl https://raw.githubusercontent.com/creationix/nvm/v0.13.1/install.sh | bash
$ nvm install v0.12.0
$ nvm alias default v0.12.0
$ node -v
v0.12.0
$ nvm --version
0.13.1
$ npm -v
2.5.1
```

nodejsのバージョンはv0.12.0を指定しました。[^1]


## gulp
ストリーミングビルドシステム
プラグインを組み合わせながら様々なファイルをビルドする仕組みを提供してくれるっぽい。
Laravel ElixirにはLESSを編集しながらCSSを適用していくみたいな機能があって
それを実現するためにストリーミング機能のあるgulpが採用されているんだと思う。

```
$ npm install -g gulp
$ gulp -v
[12:59:47] CLI version 3.8.11
[12:59:47] Local version 3.8.11
```

## Elixir
Laravelアプリケーション内にあるpackage.json[^2]を使ってインストール
(僕の場合は/www/laravel5.app/htdocs配下にappとか置いてある感じです。)

```
$ cd /www/laravel5.app/htdocs/
$ npm install
```

するとカレントディレクトリにnode_modulesディレクトリが作成されてそこにインストールされてます。

# Elixirを使ってみる
まずはgulpfile.jsを見てみます。

```
$ cd /www/laravel5.app/htdocs/
$ cat gulpfile.js
var elixir = require('laravel-elixir');
/*
|--------------------------------------------------------------------------
| Elixir Asset Management
|--------------------------------------------------------------------------
|
| Elixir provides a clean, fluent API for defining some basic Gulp tasks
| for your Laravel application. By default, we are compiling the Less
| file for our application, as well as publishing vendor resources.
|
*/
elixir(function(mix) {
    mix.less('app.less');
});
```

この```mix.less('app.less');```で指定されているファイルは```resources/assets/less/app.less```のことです。

Laravelではlessを使ってcssを作ることができて、これはapp.lessをコンパイルしてくれって命令ですね。

Elixirを使うにはこのgulpfile.jsを編集してgulpコマンドを叩く必要があるのですが、
いったんこのままgulpコマンドを実行してみます。

```
$ gulp
[13:00:32] Using gulpfile /www/laravel5.app/htdocs/gulpfile.js
[13:00:32] Starting 'default'...
[13:00:32] Starting 'less'...
[13:00:33] Finished 'default' after 930 ms
[13:00:35] gulp-notify: [Laravel Elixir]
[13:00:35] gulp-notify: [Laravel Elixir]
[13:00:35] Finished 'less' after 3.49 s
[13:00:35] gulp-notify: [Error in notifier] Error in plugin 'gulp-notify'
not found: notify-send
[13:00:35] gulp-notify: [Error in notifier] Error in plugin 'gulp-notify'
not found: notify-send
```

これにより
**public/css/app.css.map** が作成されて
**public/css/app.css** が更新されます

gulpコマンド実行時にエラーが発生しましたが、Elixirの利用にはひとまず問題ありませんでした[^3]

### バージョニング
gulpfile.jsを下記のように修正します。

```
elixir(function(mix) {
    //mix.less('app.less');
    mix.less('app.less').version('css/app.css');
});
```

再びgulpコマンドを実行すると publicディレクトリ配下にbuild関連のファイルが作成されます。
そしてバージョニングされたapp.cssが作成されます。

```
public/build/css/app-bfb06d94.css
```

あとはこれをViewで表示してあげるだけです。
app.cssを指定している箇所を下記のように修正します。

```
<!--<link href="/css/app.css" rel="stylesheet">-->
<link href="{{ elixir("css/app.css") }}" rel="stylesheet">
```

上記コードから生成されるHTMLはこれ

```
<link href="/build/css/app-bfb06d94.css" rel="stylesheet">
```

elixirメソッドがapp.cssのバージョニングされたファイルパスを返してくれるので
app-xxxxxx.cssというファイル名が変更されてもテンプレート側を修正する必要はありません。

#### ファイルを複数指定したい
配列で渡してあげます。

```
mix.less('app.less').version(['css/app.css', 'logo.jpg']);
```

#### less使わないでcss直接書くケース

```
mix.version(['css/app.css', 'logo.jpg']);
```

#### ディレクトリ単位でまとめて指定

```
mix.version(['css/*', 'image/*']);
```


Elixirは他にも色々機能があるようなので、引き続き色々試してみたいと思います。

---

[^1]: 最初 v0.11.14でやったらnode-sassのインストールでエラーになって困った。まさにピンポイントのissueがあがっててv0.12.0にしたら解決してたので参考にしました。https://github.com/sass/node-sass/issues/679

[^2]: Laravel5.0.1まではpackage.jsonにないprivateオプションがmasterブランチには追加されていたから5.0.2あたりで入ってくるのかな https://github.com/laravel/laravel/blob/master/package.json

[^3]: なにやらvagrant環境だと出てしまうよう。。。要調査。https://laracasts.com/discuss/channels/general-discussion/laravel-elixer-gulp-watch-error-in-homestead http://stepquick.net/blog/2014/09/08/use-gulp-notify-with-terminal-notifier/