Laravel ElixirでCSSをビルドする際に出力ファイル名を変更する

# 変更方法
```javascript:gulpfile.js
elixir.config.cssOutput = 'public/css/mycss.css';
```
これで出力ファイル名がmycss.cssになります。（デフォルトだと常にapp.cssになる）

# Laravel Elixir、一体何者なんだ…
Laravel用のGulpタスクが使える奴みたいな認識．
(´･ω･)っ[Laravel Elixir - Laravel - The PHP Framework For Web Artisans](http://laravel.com/docs/5.1/elixir)
> Laravel Elixir provides a clean, fluent API for defining basic Gulp tasks for your Laravel application

だいたいあってる．なお，Erlang VM上で動く[Elixir](http://elixir-lang.org/)とはちっとも関係がない．

# メモ：ソースコードを追う
- 上の方法を見つけるためにコードを読んだので、理解したところまで流れのメモ。
- 中途半端な理解で書いているので本当にメモです。

## コンパイル実行
SCSSからCSSへのコンパイル処理の流れをみていこう。コンパイルはSass.jsにおいて、`elixir.extend('sass', addSassTask)`が呼び出されるあたりから始まるっぽい（これを呼び出しているのはどこ？）。

```javascript:Sass.js
var compile = require('./commands/CompileCSS');

var addSassTask = function (src, output, options, useRuby) {
    return compile({
        compiler: 'Sass',
        plugin: useRuby ? 'gulp-ruby-sass' : 'sass',
        pluginOptions: buildOptions(options, useRuby),
        src: src,
        output: output || elixir.config.cssOutput,
        search: '**/*.+(sass|scss)'
    });
};

elixir.extend('sass', addSassTask);
elixir.extend('rubySass', function (src, output, options) {
    return addSassTask(src, output, options, true);
});

```
addSassTaskの実態は`compile()`に引数の配列を渡した戻り値である。`compile()`自体は`node_modules/laravel-elixir/ingredients/commands/CompileCSS.js`からロードされているので実装を見に行く。

### 参考：Extend()の定義
```javascript:node_modules/laravel-elixir/index.js
Elixir.extend = function(name, callback) {
    Elixir.config[name] = callback;
};
```

## オプションの保存

これが`compile()`の実装である。

```javascript:CompileCSS.js
module.exports = function(options) {
    var name = options.compiler.toLowerCase();
    var dir = config.assetsDir + name;
    var watchPath = dir + '/' + options.search;

    config.saveTask('compile' + name, { // オプションなどを保存している
        src: utilities.buildGulpSrc(options.src, dir, options.search),
        options: options
    });

    return buildTask(name, watchPath);
};
```
まず、compilerの名前をキーにして、与えられた先ほど与えた引数(options)などを保存していることがわかる。この関数の実装は次の通り。

```javascript:Config.js
config.saveTask = function (key, data) {
    this.collections[key] = this.collections[key] || [];

    this.collections[key].push(data);
}
```

次に、与えられた引数からディレクトリのpathやファイル名を取得し、`buildTask()`を呼び出して返している。結局、これが先の`elixir.extend()`のコールバック関数となっている。
では`buildTask()`はどこで定義されているのか。

## ファイル名の決定

`buildTask()`はConfig.jsで次のように定義されている。

```CompileCSS.js
var buildTask = function(name, watchPath) {
// 略
	var destination = utilities.parse(options.output); // 与えられたpathをパースする
	// 略
	return triggerCompiler(data.src, options)
	// 略
	.pipe(plugins.concat(destination.name || 'app.css')) //ファイル名を決める（64行目）
// 略
}
```
実装をみると、ここで`destination.name`がどうやら生成するcssのファイル名になるようだ。すなわち、cssのファイル名は`options.output`に格納されるpathの名前と同一になる。
この変数は`output: output || elixir.config.cssOutput`を格納している。冒頭での呼び出し処理`elixir.extend('sass', addSassTask)`においてはaddSassTaskに引数は渡されていないため、`options.output`には`elixir.config.cssOutput`のデフォルト値が入るはずだ。デフォルト値はapp.cssのはず。

## `elixir.config.cssOutput`のデフォルト値
`elixir.config`のデフォルト値は`node_modules/laravel-elixir/Config.js`に定義されている。

```javascript:Config.js
var config = {
    production: !!util.env.production,
    srcDir: 'app',
    publicDir: 'public',
    assetsDir: 'resources/assets/',
    cssOutput: 'public/css', // ←ここ
    jsOutput: 'public/js',
    sourcemaps: !util.env.production,
    autoprefix: true,
    tasks: [],
    collections: [],
    watchers: {default: {}},
    babelOptions: {
        stage: 2,
        compact: false
    },
    autoprefixerOptions: {
        browsers: ['last 2 versions'],
        cascade: false
    }
};

```
`elixir.config.cssOutput`の値を見ると、生成先のディレクトリのpathが指定されている。
前節で見たようにファイル名は`plugins.concat(destination.name || 'app.css')`という処理で決定される。ファイル名が存在しなければ`destination.name`はfalseとなるため、デフォルト値app.cssが生成されるcssのファイル名となる。

さて、ファイル名を変更したければ、ここの`cssOutput`を`path/to/mycss.css`になるように変えれば良い。このためには自分の使うgulpfileに次の一文を加えればよい。

```javascript:gulpfile.js
elixir.config.cssOutput = 'public/css/mycss.css';
```
これで`public/css`以下にmycss.cssが出力される。


# コード解読方法
実際のコード解読はgrepでCompileCss.jsの`app.css`を発見してから、ファイル名は`myapp.scss`なのに`app.css`になるということは、そもそも`options.output`の終端は`**.scss`のような形になっていないはず。と予想を立てて呼び出し元を逆引きしていった。