gulp.jsを用いたフロントエンド開発環境の構築

## 前置き、概要説明

今回は、フロントエンド開発に最低限必要であろう構成で環境を構築します。

- SASSコンパイル(Compassを利用)
- CoffeeScriptコンパイル
- CSS 及び Javascript ミニファイ
- ファイル及びディレクトリの監視とタスク実行

本記事では各種ライブラリを利用する関係上、**Node.js**及び**Ruby**が既にインストールしてあることを前提としています。インストールに関しては下記リンクを参照して下さい。

- [nodebrew を用いた Node.js環境構築](http://qiita.com/HayneRyo/items/326de7231d907447834d)
- [rbenvやBundlerを用いたRuby環境構築](http://qiita.com/HayneRyo/items/d493a2b3cec2322f167c)

## gulp.js環境インストール

gulp.jsとはタスクランナーと呼ばれるツールです。

CoffeeScriptやSASSなど、昨今はフロントエンド環境でもコンパイルが必要となりました。他にもソースコードのミニファイなど様々な作業＝**タスク**が発生します。これら複数のタスクを逐一、コマンドを叩き処理するのはどうしても手間になります。

タスクランナーは**ファイルを監視し**、コンパイルなどの**タスクを自動化**してくれます。類似ツールにはGruntなどがあります。

### 1. gulp.jsをインストールする

npm初期化、package.jsonの生成を行います。

```lang:ターミナル
$ npm init
```

このpackage.jsonには**インストールされたnpmライブラリのリストなどの情報**が追加され、自分以外の作業者でも同一環境を構築することを容易にします。

次にgulp.jsをインストールします。

```lang:ターミナル
$ npm install --save-dev gulp
```

これによりプロジェクトのディレクトリ配下(node_modules)に**ローカルインストール**されます。
逆にシステム全体に対して**グローバルインストール**する方法もあり、その場合はオプション`-g`を付けてインストールします。

また、installのオプションには`--save`や`--save-dev`が存在します。この`--save`オプションを指定することでpackage.jsonにインストールするライブラリが追記されて他作業者との同一環境が担保されます。`--save-dev`は開発環境のみでのインストールを指定します。

インストールされことを確認します。

```lang:ターミナル
$ gulp -v
CLI version 3.8.11
Local version 3.8.11
```

### 2.SASSコンパイル環境の構築

今回、SASSのコンパイルには**Compass**を利用します。
CompassとはSASSコンパイルの他、スプライト画像の生成などコーディングに便利なヘルパー機能を内包しているRubyのgemライブラリです。なので、はじめにBundlerを用いてCompassをインストールします。

#### 2-1.Compassインストール

Bundler初期化、Gemfileの生成を行います。これは先述の`npm init`のBundler版だと思って下さい。

```lang:ターミナル
$ bundle init
```

次に生成されたGemfileに**インストールしたいgemライブラリ名を記述**します。今回はCompassを追記します。

```lang:Gemfile
gem "compass"
```

実際にgemライブラリをインストールします。

```lang:ターミナル
$ bundle install --binstubs --path vendor/bundle
```

オプション`--path`を用いてプロジェクト配下にインストールします。このオプションを忘れてしまうと、システム(rbenvの適応されているRubyバージョン配下)にインストールされてしまいます。

また、オプション`--binstubs`を付けると実行ファイルを`./bin`に生成してくれます。
※注：このオプションはRails4で行うとRailsのbinを上書きしてしまうらしいので注意が必要です。

実際にインストールされたことを確認します。

```lang:ターミナル
$ compass -v
Compass 1.0.3 (Polaris)
Copyright (c) 2008-2015 Chris Eppstein
Released under the MIT License.
Compass is charityware.
```

ここまでで、Compassのインストールが完了しました。

#### 2-2.gulp.jsの設定

gulp.jsでCompassを利用する為のライブラリをインストールします。

```lang:ターミナル
$ npm install --save-dev gulp-ruby-sass
```

gulp.jsの設定ファイルを用意します。

```js:gulpfile.js
'use strict';

var
  gulp    = require('gulp'),
  compass = require('gulp-compass')
;

gulp.task('sass',function(){
  gulp
    .src('./src/sass/**/*.sass')
    .pipe(compass({
       config_file: './config/compass.rb',
       comments   : false,
       css        : '../public/css/',
       sass       : './src/sass/'
    }));
});
```

抜粋しながら記述の説明します。

```js:gulpfile.js(3行目)
var
  gulp    = require('gulp'),
  compass = require('gulp-compass')
;
```

ここでは必要なnpmパッケージをrequireで読み込んでいます。ここで読み込むのは、先程の`npm install`でインストールしたライブラリです。

```js:gulpfile.js(8行目)
gulp.task('sass',function(){
  gulp
    .src('./src/sass/**/*.sass')
    .pipe(compass({
       config_file: './config/compass.rb',// Compass設定ファイル
       comments   : false,
       css        : '../public/css/',     // css出力先
       sass       : './src/sass/'         // sass読込元
    }));
});
```

ここでは**タスク定義**を行っています。Compassメソッドの設定ファイル、引数については説明を割愛します。

タスク定義は基本的に下記のような記法となります。

```lang:タスク記述例
gulp.task('タスク名',function(){
  gulp
    .src('対象ファイル')
    .pipe(行いたい処理)
    .pipe(行いたい処理)
    ....
    .pipe(gulp.dest('出力先'))
});
```

`pipe(行いたい処理)`の処理の部分には`require`で読み込んだライブラリを用います。pipeメソッドは**出力を引き継ぎ、チェーンすることで重ねて処理を掛けることも可能**です。最終的にdestメソッドで出力を行います。
※注:本項のCompassのようにプラグイン自体が出力する場合はdestメソッドは使わないこともあります。

定義したタスクが動くか確認します。`gulp タスク名`で定義されたタスクが実行されます。

SASSファイルを設定した読込元ディレクトリに保存して下記コマンドを実行します。

```lang:ターミナル
$ gulp sass
```

設定した出力先ディレクトリに出力されれば成功です。

### 3.CoffeeScriptコンパイル環境の構築

SASSコンパイル環境と同様に、CoffeeScriptコンパイル環境を用意します。SASSコンパイル環境と異なり、利用するのはnpmライブラリのみです。

CoffeeScriptをコンパイルする為のライブラリをインストールします。

```lang:ターミナル
$ npm install --save-dev gulp-coffee
```

gulp.jsの設定ファイルを用意します。記法は前述の通りです。

```js:gulpfile.js
'use strict';

var
  gulp    = require('gulp'),
  compass = require('gulp-coffee')
;

gulp.task('coffee',function(){
  gulp
    .src('./src/coffee/**/*.coffee')
    .pipe(coffee())
    .pipe(gulp.dest('./src/js/'));
});
```

CoffeeScriptファイルを設定した読込元ディレクトリに保存して下記コマンドを実行します。

```lang:ターミナル
$ gulp coffee
```

設定した出力先ディレクトリに出力されれば成功です。

### 4.ソースコードのミニファイ

ミニファイとはいわゆる圧縮、余分なスペース、改行、インデントなどの不要なバイトを取り除くことです。CSS、JavaScriptを圧縮すると、ダウンロード、解析、実行時の速度を向上させることができます。 

ミニファイに必要なライブラリをインストールします。

```lang:ターミナル
$ npm install --save-dev gulp-uglify gulp-minify-css
```

gulp.jsの設定ファイルを用意します。記法は前述の通りです。

```js:gulpfile.js
'use strict';

var
  minifyCss = require('gulp-minify-css'),
  uglify    = require('gulp-uglify'),
;

gulp.task('minifyCSS',function(){
  gulp
    .src('./src/css/**/*.css')
    .pipe(minifyCss())
    .pipe(gulp.dest('../public/css/'));
});

gulp.task('minifyJS',function(){
  gulp
    .src('./src/js/**/*.js')
    .pipe(uglify())
    .pipe(gulp.dest('../public/js/'));
});
```

SASS、CoffeeScript両ファイルをコンパイルし、さらにミニファイしてみます。

```lang:ターミナル
# SASSをCSSにコンパイル
$ gulp sass
# 出力したCSSをミニファイ
$ gulp minifyCSS

# CoffeeScriptをJSにコンパイル
$ gulp coffee
# 出力したCSSをミニファイ
$ gulp minifyJS
```

設定した出力先ディレクトリに出力されれば成功です。

### 5.監視と処理の自動化

ファイルの更新を行う度に上記のコマンドを毎回実行するのはひと手間です。そこで、gulp.jsの**ファイルを監視し続けて、変更があった場合にタスクを実行する**という機能を活用します。

```js:gulpfile.js
gulp.task('default', function(){
  gulp.watch('./src/sass/**/*.sass',     ['sass']);
  gulp.watch('./src/css/**/*.css',       ['minifyCSS']);
  gulp.watch('./src/coffee/**/*.coffee', ['coffee']);
  gulp.watch('./src/js/**/*.js',         ['minifyJS']);
});
```

監視とタスク実行には`watch()`メソッドを利用します。書式は下記の通りです。

```lang:watchメソッド記述例
gulp.watch('監視対象ファイル', 実行タスク名);
```

また、`gulp.task('default',function(){});`のようにタスク名にdefaultを用いると、下記のようにgulpの引数を渡さず実行出来ます。

```lang:ターミナル
$ gulp
```

上記を実行したまま、該当ファイルを更新して出力出来れば成功です。

### 6.まとめ

今回作成したgulpfile.jsの全容は下記となります。


```js:gulpfile.js
'use strict';

var
  gulp        = require('gulp'),
  compass     = require('gulp-compass'),
  coffee      = require('gulp-coffee'),
  minifyCss   = require('gulp-minify-css'),
  uglify      = require('gulp-uglify'),
  SASS_FILE   = './src/sass/**/*.sass',
  COFFEE_FILE = './src/coffee/**/*.coffee',
  CSS_FILE    = './src/css/**/*.css',
  JS_FILE     = './src/js/**/*.js'
;

gulp.task('sass',function(){
  gulp
    .src(SASS_FILE)
    .pipe(compass({
       config_file: './config/compass.rb',
       comments   : false,
       css        : '../public/css/',
       sass       : './src/sass/'
    }));
});

gulp.task('coffee',function(){
  gulp
    .src(COFFEE_FILE)
    .pipe(coffee())
    .pipe(gulp.dest('./src/js/'));
});

gulp.task('minifyCSS',function(){
  gulp
    .src(CSS_FILE)
    .pipe(minifyCss())
    .pipe(gulp.dest('../public/css/'));
});

gulp.task('minifyJS',function(){
  gulp
    .src(JS_FILE)
    .pipe(uglify())
    .pipe(gulp.dest('../public/js/'));
});

gulp.task('default', function(){
  gulp.watch(SASS_FILE,   ['sass']);
  gulp.watch(CSS_FILE,    ['minifyCSS']);
  gulp.watch(COFFEE_FILE, ['coffee']);
  gulp.watch(JS_FILE,     ['minifyJS']);
});
```