gulp3→4の変更点に気をつけよう


これはユアマイスター Advent Calendar 2018の23日目の記事です。

AssertionError: Task function must be specifiedに長らくお世話になりましたので、こちらに関する内容を記載したいと思います。

引数指定の変更

4系からgulp.taskgulp.watchの第二引数の指定方法が変わっています。

gulp.taskの場合

// 3系の場合
gulp.task('default', ['sass']);
// 4系の場合
gulp.task('default', gulp.task('sass'));

gulp.watchの場合

// 3系の場合
gulp.watch('webroot/sass/*.sass', ['sass']);
// 4系の場合
gulp.watch('webroot/sass/*.sass', gulp.task('sass'));

配列指定から、関数指定になるイメージですかね。
この変更をしていないと、自分のようにAssertionError: Task function must be specifiedと長い間お付き合いする事になります。

gulp.seriesの解説

gulp.seriesは4系で追加された関数で、順番に実行するというものです。

Gulpfile.js
gulp.task('one', function(done) {
    console.log('task one');
    done();
});

gulp.task('two', function(done) {
    console.log('task two');
    done();
});

gulp.task('default', gulp.series('one', 'two', function(done) {
    console.log('task default');
    done();
}));

サンプルコードです。
gulp.seriesにはtask('one', ...)task('two', ...)を指定しています。
これをgulpで実行すると

[vagrant@local hoge]$ gulp
[02:47:42] Using gulpfile /vagrant/sample/gulpfile.js
[02:47:42] Starting 'default'...
[02:47:42] Starting 'one'...
task one
[02:47:42] Finished 'one' after 880 μs
[02:47:42] Starting 'two'...
task two
[02:47:42] Finished 'two' after 330 μs
[02:47:42] Starting '<anonymous>'...
task default
[02:47:42] Finished '<anonymous>' after 169 μs
[02:47:42] Finished 'default' after 5.52 ms
[vagrant@local hoge]$ 

順番に実行されていることがわかります。
一応gulp.seriesonetwoを逆にして実行してみます。

[vagrant@local hoge]$ gulp
[02:50:05] Using gulpfile /vagrant/sample/gulpfile.js
[02:50:05] Starting 'default'...
[02:50:05] Starting 'two'...
task two
[02:50:05] Finished 'two' after 1.56 ms
[02:50:05] Starting 'one'...
task one
[02:50:05] Finished 'one' after 244 μs
[02:50:05] Starting '<anonymous>'...
task default
[02:50:05] Finished '<anonymous>' after 217 μs
[02:50:05] Finished 'default' after 4.55 ms
[vagrant@local hoge]$ 

想定通り順番に実行されている事がわかりました。

gulp.parallelの解説

gulp.parallelは4系で追加された関数で、並列で実行するというものです。
上記サンプルコードのgulp.series部分をgulp.parallelに変えて実行してみます。

Gulpfile.js
gulp.task('one', function(done) {
    console.log('task one');
    done();
});

gulp.task('two', function(done) {
    console.log('task two');
    done();
});

gulp.task('default', gulp.parallel('one', 'two', function(done) {
    console.log('task default');
    done();
}));

実行結果

[vagrant@local hoge]$ gulp
[03:21:41] Using gulpfile /vagrant/sample/gulpfile.js
[03:21:41] Starting 'default'...
[03:21:41] Starting 'one'...
[03:21:41] Starting 'two'...
[03:21:41] Starting '<anonymous>'...
task one
[03:21:41] Finished 'one' after 1.63 ms
task two
[03:21:41] Finished 'two' after 1.52 ms
task default
[03:21:41] Finished '<anonymous>' after 1.56 ms
[03:21:41] Finished 'default' after 4.22 ms
[vagrant@local hoge]$ 

Startingに注目して下さい。
onetwoが平行して実行されている事がわかります。
gulp.parallelに指定されたtaskはこのように平行して実行されます。

callbackについて

taskfunctionの引数にdoneが指定されていて、function内の処理でdone();が実行されています。
これはcallbackといって、task内の処理の終了を意味します。
なので、このメソッドが呼ばれたタイミングで、そのtaskの処理は終了を宣言します。

gulp.task('default', ..., function(done){...})内のdone();外して実行してみます。

[vagrant@local hoge]$ gulp
[03:12:04] Using gulpfile /vagrant/sample/gulpfile.js
[03:12:04] Starting 'default'...
[03:12:04] Starting 'one'...
task one
[03:12:04] Finished 'one' after 985 μs
[03:12:04] Starting 'two'...
task two
[03:12:04] Finished 'two' after 465 μs
[03:12:04] Starting '<anonymous>'...
task default
[03:12:04] The following tasks did not complete: default, <anonymous>
[03:12:04] Did you forget to signal async completion?
[vagrant@local hoge]$ 

このようにtask defaultStartingはありますが、callbackしていない事によってFinishedが走りません。

その為、Did you forget to signal async completion?というエラーが表示されます。

つまり、各taskでは処理実行の終了を宣言する必要があります。

参考

https://zzz.buzz/2016/11/19/gulp-4-0-upgrade-guide/
https://github.com/gulpjs/gulp
https://gist.github.com/jeromecoupe/0b807b0c1050647eb340360902c3203a