最近gruntよりgulpの方が熱い!という噂を聴いてバリバリgrunt派だったのですがチャレンジしてみました。
インストールとかは同じnode関連なのでnpm使えば簡単にできるので、この辺りgruntと大差なく導入できるなぁ〜って印象でした。
gruntで言うところのwatch
がgulp自体に含まれてるっぽいので、gruntより最初の段階でnpm install する量は少なくて済みますね。ハラショー!!
インストール関係はこちらを参考にしました。 liginc.co.jp
いつもやっている、javascriptの結合とmin化をするタスクを書いてみました。
プロジェクトのpackage.jsonを作る。
node.jsが必要なので、インストールされてない場合は下記リンクなどを参考にインストールしておいてください。
Macにnvm + Node.jsをインストールする - Qiita
プロジェクトのpackage.jsonを生成します。
$ npm init
gulpと必要なプラグインをインストールする
$ npm install --save-dev gulp
結合するプラグインgulp-concat
をインストール
$ npm install --save-dev gulp-concat
min化するプラグインgulp-uglify
をインストール
$ npm install --save-dev gulp-uglify
エラーが起こってもタスクが停止しないようにするプラグインgulp-plumber
をインストール
$ npm install --save-dev gulp-plumber
gulpfile.jsを作成
gruntで言うところのgruntfile.jsですね。このファイル作成してタスクを書いていきます。
$ touch gulpfile.js
// glup・使用する各プラグインを最初に読み込む var gulp = require("gulp"), uglify = require("gulp-uglify"), concat = require("gulp-concat"), plumber = require("gulp-plumber"); // それぞれのプラグインで行う処理を書いていく gulp.task('js.concat', function() { return gulp.src('dev/js/*.js') .pipe(plumber()) .pipe(concat('main.js')) .pipe(gulp.dest('app/webroot/js')); }); gulp.task('js.uglify', function() { return gulp.src('app/webroot/js/main.js') .pipe(plumber()) .pipe(uglify('main.min.js')) .pipe(gulp.dest('app/webroot/js/')); }); // 監視して処理するのをひとまとめにしておく。 gulp.task('js', ['js.concat', 'js.uglify']); // ファイルを監視して実行させる gulp.task('watch', function() { gulp.watch(['dev/js/*.js'], ['js']); });
こんな感じでしょうか。とりあえず実行してみます。
$ gulp [16:30:44] Using gulpfile ~/gulpfile.js [16:30:44] Task 'default' is not in your gulpfile [16:30:44] Please check the documentation for proper gulpfile formatting
default
って名前のタスクが無いとダメみたいです。
何をまず実行するのかが解らないからですよね。よくよく考えればそりゃそうだ!でした。
gulpfile.jsを編集します。まずはファイルの監視を動作させたいので、watchしているタスク名をdefaultに変更します。
/* 略 */ // ファイルを監視して実行させる // gulpコマンドで実行できるように、タスク名をdefaultに変更 gulp.task('default', function() { gulp.watch(['dev/js/*.js'], ['js']); });
再試行します。
$ gulp
今度はエラーにならず監視が上手く動作しているようです。
gulp-uglify ではmin化したファイルを別ファイルにできないっぽい?
gulpで監視した状態で、dev/js/ 内にあるjavascriptファイルを編集すると下の用なエラーが表示されました。
/node_modules/gulp-uglify/node_modules/deap/lib/deap.js:56 Object.keys(b).forEach(function(p) { ^ TypeError: Object.keys called on non-object ...
どうやらgulp-uglify
は引数に出力するファイル名を指定できるわけではないようです。
調べてみた結果、gulp-uglify
だけではどうやら別のファイル名にして出力できないっぽいと言うことがわかりました。
Allow piping to the same directory with a different filename · Issue #9 · terinjokes/gulp-uglify · GitHub
gulp-rename
というプラグインを使ってファイル名を変更してあげるのが良いみたいです。
gulp-rename
をインストールします。
$ npm install --save-dev gulp-rename
gulpfile.jsを編集します。
合わせて gulp-uglifyで特定のコメントを残したままJavaScriptをminifyする - Qiita こちらの記事を参考に/*! */
で始まるコメントがmin化した時に消えないようにします。
// glup・使用する各プラグインを最初に読み込む var gulp = require("gulp"), uglify = require("gulp-uglify"), concat = require("gulp-concat"), rename = require('gulp-rename'), // ファイル名を変更するプラグインを追加 plumber = require("gulp-plumber"); // それぞれのプラグインで行う処理を書いていく gulp.task('js.concat', function() { return gulp.src('dev/js/*.js') .pipe(plumber()) .pipe(concat('main.js')) .pipe(gulp.dest('app/webroot/js')); }); gulp.task('js.uglify', function() { return gulp.src('app/webroot/js/main.js') .pipe(plumber()) .pipe(uglify({ // ※ gulp-uglify v3.0.0 以前の場合 ↓ preserveComments: 'some' // ! から始まるコメントを残すオプションを })) .pipe(rename('main.min.js')) // 出力するファイル名を変更 .pipe(gulp.dest('app/webroot/js/')); }); // 監視して処理するのをひとまとめにしておく。 gulp.task('js', ['js.concat', 'js.uglify']); // ファイルを監視して実行させる gulp.task('watch', function() { gulp.watch(['dev/js/*.js'], ['js']); });
追記 2017-06-30
gulp-uglify v3.0.0 以降ではライセンスのコメントを残す preserveComments
オプションが廃止になっていてエラーになってしまします。
gulp-uglify v3.0.0 以上の場合はjs.uglify
のタスクを次のように変更してください。
gulp.task('js.uglify', function() { return gulp.src('app/webroot/js/main.js') .pipe(plumber()) .pipe(uglify({ // ※ gulp-uglify v3.0.0 以上↓ output:{ comments: /^!/ // 正規表現で /*! //! で始まるコメントを残す } })) .pipe(rename('main.min.js')) // 出力するファイル名を変更 .pipe(gulp.dest('app/webroot/js/')); });
▲ 追記ココまで ▲
gulp
コマンドで再度監視を開始して、javascriptファイルを変更した所、ファイルが結合され、min化されていました。
これでgruntと同じようにタスクファイルが作れたぞ!と思ったのですが…
gulpは高速化のためにタスクを並列処理しているので、必ずしも結合してからmin化されている訳ではなかった!
実行した時のコンソールを見ていると時々
[17:15:52] Using gulpfile ~/gulpfile.js [17:15:52] Starting 'default'... [17:15:52] Finished 'default' after 9.54 ms [17:15:53] Starting 'js.concat'... [17:15:53] Starting 'js.uglify'... [17:15:53] Finished 'js.uglify' after 47 ms [17:15:53] Finished 'js.concat' after 60 ms [17:15:53] Starting 'js'... [17:15:53] Finished 'js' after 14 μs
な感じで、処理の完了順がタスクの実行順になってないないことがありました。
どうやらgulpのタスクは非同期処理(並行処理)がデフォルトなので、実行順が決まっている場合は同期処理になるように書いてあげないとダメなようです。
gulpのタスクを同期的に実行する方法 - Qiita
gulp入門その3―こまごま便利なこと | アライドアーキテクツのクリエイターブログ
こちらの記事を参考に、
今回はお手軽そうなgulp.taskの第2引数にどの処理の後に行うかを指定する方法を試してみます。
js.uglify
はjs.concat
の後に行いたいので、再びgulpfile.jsを編集します。
/* 略 */ // 第2引数に先に実行して欲しい js.concat を指定する gulp.task('js.uglify', ['js.concat'], function() { return gulp.src('app/webroot/js/main.js') .pipe(plumber()) .pipe(uglify({preserveComments: 'some'})) .pipe(rename('main.min.js')) .pipe(gulp.dest('app/webroot/js/')); }); /* 略 */
これで、どうやら意図した順番にタスクが実行できるようになったみたいです。
タスクが複雑になってくると run-sequence
プラグインを使用する方法が見通しが良さそうかなーと思いました。
感想
gruntと実行ファイルの書き方や同じような名前のプラグインでもできる事が少し違っていたりするので初めは戸惑う部分もありましたが慣れればどちらでも大差なく使っていくことができそうだなーと感じました。
[参考]
- gulp.js
- Gulp.js入門 - コーディングを10倍速くする環境を作る方法まとめ | 株式会社LIG
- gulpの基本的な使い方(gulp.jsの基礎をしっかり理解する) | maesblog
- Allow piping to the same directory with a different filename · Issue #9 · terinjokes/gulp-uglify · GitHub
- gulp-uglifyで特定のコメントを残したままJavaScriptをminifyする - Qiita
- gulpのタスクを同期的に実行する方法 - Qiita
- gulp入門その3―こまごま便利なこと | アライドアーキテクツのクリエイターブログ
ガールズ&パンツァー リトルアーミーII (1) (MFコミックス アライブシリーズ)
- 作者: 槌居,ガールズ&パンツァー製作委員会
- 出版社/メーカー: KADOKAWA/メディアファクトリー
- 発売日: 2015/08/22
- メディア: コミック
- この商品を含むブログ (5件) を見る