はじめに
gulpは長い事つかってますが、 フロントの方が入れてくれた環境を基に使っているのでゼロから学んだ経験は乏しいです。 (自分はサーバサイド)
ディレクトリのclearやbuildを行うためにrun-sequence
を使っています。
ふとした動機でこれの挙動をちゃんと確認したくなったので
そんなときの自分メモ
アジェンダ
- run-sequenceとは
- run-sequenceの使い方
- run-sequenceのrunSequenceで直列指定の挙動を確認
1. run-sequenceとは
説明は公式からの引用です
Runs a sequence of gulp tasks in the specified order.
This function is designed to solve the situation where you have defined run-order,
but choose not to or cannot use dependencies.
https://www.npmjs.com/package/run-sequence
指定された順序で一連のタスクを実行する君
ということですね。
gulp4.0
公式サイトからの引用です。
これは、同様にタスクの依存関係を定義するためのサポートを持つ必要がある、
gulp 4.0のリリースまでの一時的な解決策であることを意図していました。
https://www.npmjs.com/package/run-sequence
公式サイトPlease Note
に記載がありますが、
gulp4.0ではgulp.series
、gulp.parallel
という機能で同様の事ができるらしいです。
ちなみに、gulp4.0のchangelogには記載があります。
2. run-sequenceの使い方
インストール
$ npm install --save-dev run-sequence
使い方
公式からの引用です。
https://www.npmjs.com/package/run-sequence#usage
var gulp = require('gulp'); var runSequence = require('run-sequence'); var del = require('del'); var fs = require('fs'); // This will run in this order: // * build-clean // * build-scripts and build-styles in parallel // * build-html // * Finally call the callback function gulp.task('build', function(callback) { runSequence('build-clean', ['build-scripts', 'build-styles'], 'build-html', callback); }); // configure build-clean, build-scripts, build-styles, build-html as you wish, // but make sure they either return a stream or promise, or handle the callback // Example: gulp.task('build-clean', function() { // Return the Promise from del() return del([BUILD_DIRECTORY]); // ^^^^^^ // This is the key here, to make sure asynchronous tasks are done! }); gulp.task('build-scripts', function() { // Return the stream from gulp return gulp.src(SCRIPTS_SRC).pipe(...)... // ^^^^^^ // This is the key here, to make sure tasks run to completion! }); gulp.task('callback-example', function(callback) { // Use the callback in the async function fs.readFile('...', function(err, file) { console.log(file); callback(); // ^^^^^^^^^^ // This is what lets gulp know this task is complete! }); });
ポイント
上記のコードでいうと、ポイントは以下です。
runSequence('build-clean', ['build-scripts', 'build-styles'], 'build-html', callback);
- runSequenceに記載した順に直列で実行される
- 各タスクはreturnするか、
callback()
を呼び出す必要がある
3. run-sequenceのrunSequenceで直列指定の挙動を確認
まず、非同期な処理想定としてsetTimeoutを使って確認してみます。
runSequenceを使うパターンを以下のようなパターンで確認します。
- 3.0. runSequence使った場合の期待する挙動
- 3.1. runSequence使わなかった場合
- 3.2. runSequencee使ったがcallback呼ばなかった場合
- 3.3. runSequencee使ってcallbackを入れたがおしい場合
- 3.4. runSequencee使って意図通りの指定をした場合
3.0. runSequencee使った場合の期待する挙動
まずは期待する挙動です。
以下のようにtaskを定義したとします。
この時、呼ばれる順番を以下のように期待した
という前提ですすめます。
3.1. runSequence使わなかった場合
runSequence
を使わなかった場合の挙動を確認します。
コード
var gulp = require('gulp'); gulp.task('task', ['task-1', 'task-2', 'task-3']); gulp.task('task-1', function() { console.log('called task-1'); }); gulp.task('task-2', ['task-2-1', 'task-2-2']); gulp.task('task-2-1', function() { console.log('called task-2-1'); // 5秒間かかるタスク setTimeout(function(){ console.log("\tcalled task-2-1_subtask"); }, 5000); }); gulp.task('task-2-2', function() { console.log('called task-2-2'); // 3秒間かかるタスク setTimeout(function(){ console.log("\tcalled task-2-2_subtask"); }, 3000); }); gulp.task('task-3', function() { console.log('called task-3'); // 1秒間かかるタスク setTimeout(function(){ console.log("\tcalled task-3_subtask"); }, 1000); }); gulp.task('default', ['task-normal']);
このコードは以下に置きました。
https://github.com/tweeeety/gulp-task-order/blob/master/task_normal/gulpfile.js
実行してみる
このまま実行すると、*_subtask
が非同期に最後にまとめて呼ばれます。
$ gulp task [16:39:10] Using gulpfile ~/gulp-task-order/task_normal/gulpfile.js [16:39:10] Starting 'task-1'... called task-1 [16:39:10] Finished 'task-1' after 104 μs [16:39:10] Starting 'task-2-1'... called task-2-1 [16:39:10] Finished 'task-2-1' after 592 μs [16:39:10] Starting 'task-2-2'... called task-2-2 [16:39:10] Finished 'task-2-2' after 558 μs [16:39:10] Starting 'task-2'... [16:39:10] Finished 'task-2' after 2 μs [16:39:10] Starting 'task-3'... called task-3 [16:39:10] Finished 'task-3' after 38 μs [16:39:10] Starting 'task'... [16:39:10] Finished 'task' after 1.78 μs called task-3_subtask called task-2-2_subtask called task-2-1_subtask
結果
以下のような順で呼ばれています
ポイント
*_subtask
たちが非同期にすべて最後に呼ばれている- 順番もtask-3-1_subtask, task-2-2_subtask, task-2-1_subtaskというように期待した逆の順に呼ばれている
3.2. runSequence使ったがcallback呼ばなかった場合
runSequence
は使ったが、callbackを呼ばなかった場合の挙動を確認します。
一番よくありがちなパターンでしょうか。
コード
var gulp = require('gulp'); var runSequence = require('run-sequence'); gulp.task('task', function(callback) { runSequence('task-1', 'task-2', 'task-3', callback); }); gulp.task('task-1', function() { console.log('called task-1'); }); gulp.task('task-2', ['task-2-1', 'task-2-2']); gulp.task('task-2-1', function() { console.log('called task-2-1'); // 5秒間かかるタスク setTimeout(function(){ console.log("\tcalled task-2-1_subtask"); }, 5000); }); gulp.task('task-2-2', function() { console.log('called task-2-2'); // 3秒間かかるタスク setTimeout(function(){ console.log("\tcalled task-2-2_subtask"); }, 3000); }); gulp.task('task-3', function() { console.log('called task-3'); // 1秒間かかるタスク setTimeout(function(){ console.log("\tcalled task-3_subtask"); }, 1000); }); gulp.task('default', ['task-sync-fail-1']);
このコードは以下に置きました。
https://github.com/tweeeety/gulp-task-order/blob/master/task_sync_fail_1/gulpfile.js
実行してみる
runSequenceを使ったものの、
3.1. runSequence使わなかった場合
とまったく同じ結果で非同期なままです。
$ gulp task [17:02:17] Using gulpfile ~/gulp-task-order/task_sync_fail_1/gulpfile.js [17:02:17] Starting 'task'... [17:02:17] Starting 'task-1'... called task-1 [17:02:17] Finished 'task-1' after 102 μs [17:02:17] Starting 'task-2-1'... called task-2-1 [17:02:17] Finished 'task-2-1' after 967 μs [17:02:17] Starting 'task-2-2'... called task-2-2 [17:02:17] Finished 'task-2-2' after 901 μs [17:02:17] Starting 'task-2'... [17:02:17] Finished 'task-2' after 2.05 μs [17:02:17] Starting 'task-3'... called task-3 [17:02:17] Finished 'task-3' after 40 μs [17:02:17] Finished 'task' after 5.69 ms called task-3_subtask called task-2-2_subtask called task-2-1_subtask
結果
以下のような順で呼ばれています
ポイント
3.1. runSequence使わなかった場合
とまったく同じ
3.3. runSequencee使ってcallbackを入れたがおしい場合
runSequenceeを使ってcallbackも入れたがネストが考慮されてない場合の挙動を確認してみます。
コード
var gulp = require('gulp'); var runSequence = require('run-sequence'); gulp.task('task', function(callback) { runSequence('task-1', 'task-2', 'task-3', callback); }); gulp.task('task-1', function() { console.log('called task-1'); }); gulp.task('task-2', ['task-2-1', 'task-2-2']); gulp.task('task-2-1', function(callback) { console.log('called task-2-1'); // 5秒間かかるタスク setTimeout(function(){ console.log("\tcalled task-2-1_subtask"); callback(); }, 5000); }); gulp.task('task-2-2', function(callback) { console.log('called task-2-2'); // 3秒間かかるタスク setTimeout(function(){ console.log("\tcalled task-2-2_subtask"); callback(); }, 3000); }); gulp.task('task-3', function(callback) { console.log('called task-3'); // 1秒間かかるタスク setTimeout(function(){ console.log("\tcalled task-3_subtask"); callback(); }, 1000); }); gulp.task('default', ['task-sync-fail-2']);
このコードは以下に置きました。
https://github.com/tweeeety/gulp-task-order/blob/master/task_sync_fail_2/gulpfile.js
実行してみる
よく見ないとわかりずらいですが、
task-2-2_subtask
、task-2-1_subtaks
あたりが意図した通りになっていません。
$ gulp task [17:13:16] Using gulpfile ~/gulp-task-order/task_sync_fail_2/gulpfile.js [17:13:16] Starting 'task'... [17:13:16] Starting 'task-1'... called task-1 [17:13:16] Finished 'task-1' after 163 μs [17:13:16] Starting 'task-2-1'... called task-2-1 [17:13:16] Starting 'task-2-2'... called task-2-2 called task-2-2_subtask [17:13:19] Finished 'task-2-2' after 3 s called task-2-1_subtask [17:13:21] Finished 'task-2-1' after 5 s [17:13:21] Starting 'task-2'... [17:13:21] Finished 'task-2' after 4.19 μs [17:13:21] Starting 'task-3'... called task-3 called task-3_subtask [17:13:22] Finished 'task-3' after 1 s [17:13:22] Finished 'task' after 6.01 s
結果
以下のような順で呼ばれています
ポイント
- task2とtask3の
*_subtask
は、それぞれの中で呼ばれるようになった- ただし、task2内のtask-2-2_subtask、task-2-1_subtaksの順番は非同期のまま
3.4. runSequencee使って意図通りの指定をした場合
最後に意図通りの使い方の確認です。
コード
var gulp = require('gulp'); var runSequence = require('run-sequence'); gulp.task('task', function(callback) { runSequence('task-1', 'task-2', 'task-3', callback); }); gulp.task('task-1', function() { console.log('called task-1'); }); gulp.task('task-2', function(callback){ runSequence('task-2-1', 'task-2-2', callback); }); gulp.task('task-2-1', function(callback) { console.log('called task-2-1'); // 5秒間かかるタスク setTimeout(function(){ console.log("\tcalled task-2-1_subtask"); callback(); }, 5000); }); gulp.task('task-2-2', function(callback) { console.log('called task-2-2'); // 3秒間かかるタスク setTimeout(function(){ console.log("\tcalled task-2-2_subtask"); callback(); }, 3000); }); gulp.task('task-3', function(callback) { console.log('called task-3'); // 1秒間かかるタスク setTimeout(function(){ console.log("\tcalled task-3_subtask"); callback(); }, 1000); }); gulp.task('default', ['task-sync']);
このコードは以下に置きました。
https://github.com/tweeeety/gulp-task-order/blob/master/task_sync/gulpfile.js
実行してみる
意図どおりになりました!
$ gulp task [17:21:37] Using gulpfile ~/gulp-task-order/task_sync/gulpfile.js [17:21:37] Starting 'task'... [17:21:37] Starting 'task-1'... called task-1 [17:21:37] Finished 'task-1' after 102 μs [17:21:37] Starting 'task-2'... [17:21:37] Starting 'task-2-1'... called task-2-1 called task-2-1_subtask [17:21:42] Finished 'task-2-1' after 5 s [17:21:42] Starting 'task-2-2'... called task-2-2 called task-2-2_subtask [17:21:45] Finished 'task-2-2' after 3 s [17:21:45] Finished 'task-2' after 8.01 s [17:21:45] Starting 'task-3'... called task-3 called task-3_subtask [17:21:46] Finished 'task-3' after 1 s [17:21:46] Finished 'task' after 9.01 s
結果
無事意図通りに呼ばれるようになりました。
サンプル
一応サンプルをおいておきました。
npm install
すればそれぞれ試せます。
参考
おわり
使い方や説明を見てわかることもありますが、
実際に確認するのって大切ですよね\(^o^)/