gulpを使ったフロントエンド開発 gulpfile.jsの書き方編

/

導入

この記事はgulpを使ったフロントエンド開発 導入編 – Koltattの続きです。

前回gulpのインストールと処理の実行までを確認したので今回はより細かい処理の書き方を見ていきます。

gulp.watch

前回行ったSassのコンパイルのようにCSSの編集などは頻繁にファイルの更新を行うため通常のタスクの書き方だと何度もコマンドを打つ必要があり非常に面倒です。そのためgulpには特定のファイルに変更があった場合には自動的に指定したタスクを実行してくれるwatchの機能が用意されています。

// src 変更があると task を実行してくれる
gulp.watch([src][task]);
//Sassのコンパイル
gulp.task('sass',function(){
	gulp.src('./sass/*.scss')
	.pipe(sass()
	.pipe(gulp.dest('./css'));
});

//./sass/ にあるscssファイルが更新されるとsassタスクを実行
gulp.task('watch', function(){
  gulp.watch('./sass/*.scss' ,['sass']);
});
$ gulp watch

watchを使ったタスクを実行するとgulpは待機状態になり、待機状態でいる限り指定したファイルを監視し続け、ファイルに変更があった場合その都度設定したタスクを実行してくれます。作業を中断して待機状態を終了したい時にはCtrl-Cを実行すると処理が終了します。

複数の処理を同時に行う

gulpのwatch機能は便利ですが前回のようなSassのコンパイルやwatchを使った監視は通常のSassでも出来るので、このためだけならわざわざgulpを使う必要はありません(通常のSassの導入にはRubyが必要だという違いがありますが)。

gulpのようなタスクランナーは複数の処理を実行して初めて真価を発揮するのでSassの他にBabelを使ったタスクの同時処理をを実装していきます。

Babel

BabelはECMAScript2015仕様のJavascirptを一般的なブラウザがサポートしているECMAScript5形式のJavaScriptにコンパイルしてくれるライブラリです。
ECMAScript2015はアロー関数などの便利な機能を実装した新しいJavaScriptの仕様ですが、現時点ではブラウザの対応が整っていないためBabelを使ったコンパイルを実行して使用します。

#Babelとプリセットのインストール
$ npm install --save-dev gulp-babel babel-preset-es2015
//Babelでコンパイルを実行するタスク
gulp.task('babel', function(){
  gulp.src('./babel/**/*.js')
  .pipe(babel({
    presets:['es2015']
  }))
  .pipe(gulp.dest('./javascript'));
});

gulpではタスク名を default に設定すると gulp コマンドだけでタスクを実行出来るようになります。
このデフォルトタスクを使ってSassとBabelのタスクを同時に実行してみます。

gulp.task('default', function(){
  gulp.start(['sass','babel']);
});
#デフォルトコマンドの実行
$ gulp

[17:58:11] Using gulpfile ~/project/gulpfile.js
[17:58:11] Starting 'default'...
[17:58:11] Starting 'sass'...
[17:58:11] Finished 'sass' after 18 ms
[17:58:11] Starting 'babel'...
[17:58:11] Finished 'babel' after 5.91 ms
[17:58:11] Finished 'default' after 27 ms

一つのタスクの実行でSassとBabelを同時にコンパイルする事が出来ました。

gulp.watchで複数の対象を監視する

watchでも複数のタスクを同時に実行する事が出来ます。

gulp.task('watch', function(){
  //sassの監視
  gulp.watch('./sass/*.scss' ,['sass']);
  //JavaScript(babel)の監視
  gulp.watch('./babel/*.js' ,['babel']);
});

このように書いたwatchコマンドを実行すると待機状態である限り、scss/にあるscssファイルとbabel/にあるjavaScriptファイルのどちらを更新してもそれぞれのタスクが実行されます。

依存タスクの処理

gulpではタスクを同時に処理する事も出来ますが、依存の指定する事でタスクを実行した際にそのタスクが処理される前に別のタスクを実行させる事が出来ます。

del

まずは依存処理によって実行するライブラリが必要なのでdelを追加します。
del はgulp内で指定したファイルを削除してくれるライブラリです。SassやBabaelでコンパイルを実行する際に事前に出力先のディレクトリを空っぽにしておきたいのでdelを使ってディレクトリ内のファイルを削除するタスクを用意します。

// css/内のcssファイルを削除
gulp.task('clean:css', function(){
  return del(['./css/*.css']);
});

clean:cssタスクをsassタスクの依存に指定します。

gulp.task('sass',['clean:css'], function(){
	gulp.src('./sass/*.scss')
	.pipe(sass()
	.pipe(gulp.dest('./css'));
});

このようなコードを書いてからsassタスクを実行するとまず依存タスクの処理として[]でくくられたclean:cssが実行され、その次にSassのコンパイルが実行されるためcss/の中にはsassタスクによってコンパイルされたファイルだけが残る事になります。

同様の処理はbabelタスクでも実行出来るほかにcss/とjavascript/のファイルの削除を同時に行うタスクを書くことも出来ます。

//javascript/*.jsファイルの消去
gulp.task('clean:javascript', function(){
  return del(['./javascript/*.js']);
});

//ファイルを削除してからコンパイルを実行
gulp.task('babel',['clean:javascript'], function(){
  gulp.src('./babel/**/*.js')
  .pipe(babel({
    presets:['es2015']
  }))
  .pipe(gulp.dest('./javascript'));
});

// gulp clean でcssとjavascriptのファイルをまとめて消去
gulp.task('clean', function(){
  gulp.start(['clean:css','clean:javascript']);
});

タスクをまとめる

最後に全てのタスクをまとめてみます。

var gulp  = require('gulp');
var sass  = require('gulp-sass');
var babel = require('gulp-babel');
var del   = require('del');

//sassのコンパイル
gulp.task('sass',function(){
	gulp.src('./sass/*.scss')
	.pipe(sass()
	.pipe(gulp.dest('./css'));
});

//babelのコンパイル
gulp.task('babel', function(){
  gulp.src('./babel/**/*.js')
  .pipe(babel({
    presets:['es2015']
  }))
  .pipe(gulp.dest('./javascript'));
});

//SassとBabelのコンパイル
gulp.task('build', function(){
  gulp.start(['sass','babel']);
});

//出力先のcssファイルの削除
gulp.task('clean:css', function(){
  return del(['./css/*.css']);
});

//出力先のjavascripファイルを削除
gulp.task('clean:javascript', function(){
  return del(['javascript/*.js']);
});

//cssとjavascriptファイルをまとめて削除
gulp.task('clean', function(){
  gulp.start(['clean:css','clean:javascript']);
});

//デフォルトタスクでファイルを削除してからSassとBabelのコンパイルを実行
gulp.task('default',['clean'], function(){
  gulp.start(['build']);
});

//sass/*.cssと/babel/.jsの監視
gulp.task('watch', function(){
  gulp.watch('./sass/*.scss' ,['sass']);
  gulp.watch('./babel/*.js' ,['babel']);
});

このgulpfile.jsの最終的な処理の流れは以下のようになります。

$ gulp
#clean(出力先のcss & javaScriptの削除) > build(css & javascriptのコンパイル)が実行

$ gulp watch
#sass/ と babel/ 内のファイルが更新されると自動的にそれぞれのコンパイルが実行される

このままでも gulp > gulp watch とコマンドを実行する事によって2つのライブラリのコンパイルが自動的に実行されますが、極力手間を省きたいのであれば defaultタスクの依存に clean と build を指定し watch を起動するようにすれば一回の gulp コマンド で全ての処理を実行させる事も出来ます。

参照

英語ですがGithubのgulpのページにAPIの詳しい説明やレシピ集があります。
gulp API docs/Github
gulp docs recipes/Github
gulp docs articles/Github

あとがき

前回は一つのタスクを実行するだけだったので今回複数のタスクの同時処理や連結させた処理をやってみました。
複数の処理を組み合わせる事で単純な処理だけだと見えづらかったタスクランナーのメリットがよく解りました。しかも一度タスクを作ってしまえばタスクやファイルをコピーして使い回しが出来るので、プロジェクト毎にいちいち環境を整える必要が無く開発の環境構築の手間を省くことが出来ます。