[Gulp.js] タスク単位のファイル分割
車輪開発大好きおたいがです。こんにちは。(挨拶)
今までタスクランナーツールは Grunt を使用していたのですが、Gulp ( ガルプ ) は、Grunt よりも定義ファイルの記述が簡潔だと評判が良いらしいのでデビューを果たしました。
ざっくり触ってみたところ、かなりシンプルであることは分りました。ただそれでも、開発中に機能 ( タスク ) を追加していくたびに、どうしても設定ファイル (gulpfile.js) は肥大化していきます。そんな状況を極力減らすために、タスク単位でファイルを分割することを試してみたのでまとめてました。
解説前に
当ブログに Gulp のインストールから実行までの入門記事がありますので、何もご存じない方は併せてご覧ください。
【Gulp.js入門】新鋭フロンエンド・タスクランナーツール を試してみました。
例 : 任意の JavaScript ファイルの結合および minify タスク
ファイルの結合
gulp で複数のファイルを結合するときには gulp-concat モジュールを使用します。
gulp-concat
https://www.npmjs.org/package/gulp-concat
インストール
[user@host project]$ npm install gulp-concat --save-dev
JavaScript の minify
JS を minify するときには gulp-uglify モジュールを使用します。
gulp-uglify
https://www.npmjs.org/package/gulp-uglify
インストール
[user@host project]$ npm install gulp-uglify --save-dev
タスク (gulp/js-minify.js)
上記支度を済ませたあと、以下のようなタスクを用意します。
/** gulp/js-minify.js */ module.exports = function(gulp) { var taskName = 'js-minify'; var uglify = require('gulp-uglify'); var concat = require('gulp-concat'); var srcPath = 'app/js/*.js'; var dstPath = 'build/js'; var exportFileName = 'script.js'; gulp.task(taskName, function () { gulp.src(srcPath) .pipe( concat(exportFileName) ) .pipe( uglify() ) .pipe( gulp.dest(dstPath) ); }); };
これで完成です。
例 : 任意の CSS の結合および minify タスク
CSS の minify
CSS を minify するときには gulp-minify-css モジュールを使用します。
gulp-minify-css
https://www.npmjs.org/package/gulp-minify-css
インストール
[user@host project]$ npm install gulp-minify-css --save-dev
タスク (gulp/css-minify.js)
上記支度を済ませたあと、以下のようなタスクを用意します。
/** gulp/css-minify.js */ module.exports = function(gulp) { var taskName = 'css-minify'; var minifyCSS = require('gulp-minify-css'); var concat = require('gulp-concat'); var srcPath = 'app/css/*.css'; var dstPath = 'build/css'; var exportFileName = 'style.css'; var option = { 'keepBreaks' : false }; gulp.task(taskName, function () { gulp.src(srcPath) .pipe( concat(exportFileName) ) .pipe( minifyCSS(option) ) .pipe( gulp.dest(dstPath) ); }); };
作成したタスクの定義
上記 2 つのタスクを、メインの設定ファイルである gulpfile.js から読み込む例は以下のとおりです。
/** gulpfile.js */ var gulp = require('gulp'); require('./gulp/js-minify.js')(gulp); require('./gulp/css-minify.js')(gulp); gulp.task('default', ['js-minify', 'css-minify']);
ここで大切なのは require(taskFile)(gulp); です。require() の戻り値である関数に gulp の参照を渡さないとタスク名が登録されません。
実行
これで支度は完了したので以下のように Gulp を実行します。
[user@host project]$ gulp
これで 'default' タスクが実行されて、定義済みの 'js-minify' タスクと 'css-minify' タスクが並行で実行されます。
分割したタスクファイルを簡単に定義したい場合
以下のような、タスクを新規作成するたびに定義を都度書き足していく行為も自動的に行いたいものです。
require('./gulp/js-minify.js')(gulp); require('./gulp/css-minify.js')(gulp); … //タスクが増えるたびに増える定義
recursive-readdir を使用した一括タスク定義
recursive-readdir は、指定したディレクトリとサブディレクトリ内のすべてのファイルの配列を取得することのできるモジュールです。
recursive-readdir
https://www.npmjs.org/package/recursive-readdir
このモジュールを使用することで、gulp ディレクトリ配下のタスク定義を自動的に処理されることができます。
var gulp = require('gulp'); var recursive = require('recursive-readdir'); gulp.task('recursiveTask', function(callback) { recursive('./gulp', function (err, files) { files.forEach(function(path, index, arry) { path = './' + path.replace('\\', '/' ); require(path)(gulp); }); callback(); //タスクの完了を通知する }); });
タスク定義の完了後にタスクを実行させる
ここで気を付けないといけないことは、上記 'recursiveTask' タスクが完了した後でないと登録したタスクは実行できないということです。
以下のように記述した場合、エラーが発生してタスクが実行されません。
//並列でタスクが実行されるため怒られる例 gulp.task('default', ['default', ['recursiveTask', 'js-minify', 'css-minify']);
次のように書くことで解決できます。
gulp.task('default', ['recursiveTask'], function() { // 'recursiveTask' 登録関数の引数 callback を実行することで呼ばれる処理 gulp.start(['js-minify', 'css-minify']); });
ちなみに gulp.start() で任意のタイミングにタスクを実行させることが可能です。
最終的に gulpfile.js は、こんな感じになりました。
/** gulpfile.js */ var gulp = require('gulp'); var recursive = require('recursive-readdir'); gulp.task('recursiveTask', function(callback) { recursive('./gulp', function (err, files) { files.forEach(function(path, index, arry) { path = './' + path.replace('\\', '/' ); require(path)(gulp); }); callback(); }); }); gulp.task('default', ['recursiveTask'], function() { gulp.start(['js-minify', 'css-minify']); });
おわりに
この記事を書く数時間前に Gulp デビューしたのですが、Grunt と比べてとても馴染め易かった気がします。
世の中に発信されているリソース情報が Grunt と比べると少ないとは思いますが、興味のある方は是非触ってみてはいかがでしょうか。