Gulpタスクを順番に実行する方法


398

次のようなスニペットで:

gulp.task "coffee", ->
    gulp.src("src/server/**/*.coffee")
        .pipe(coffee {bare: true}).on("error",gutil.log)
        .pipe(gulp.dest "bin")

gulp.task "clean",->
    gulp.src("bin", {read:false})
        .pipe clean
            force:true

gulp.task 'develop',['clean','coffee'], ->
    console.log "run something else"

developタスク私が実行したいcleanとそれが行わだ後、実行coffeeし、それが終了したとき、何か他のものを実行します。しかし、それを理解することはできません。この作品は動作しません。お知らせ下さい。


10
run-sequence npmモジュールがこの問題を修正しました-他のすべての回答は無関係になりました-以下のOverZealousの回答を参照してください
danday74

1
Gulp 4.0は、実行中のタスクのシーケンスをネイティブにサポートし、run-sequence時代遅れになっています
Forivin

Gulp4はそれが修正するよりも多くのものを壊します。それと数時間戦った後、3.9.1に戻りました。メジャーバージョンがバックコンパクトを壊すことができる/することを理解していますが、不可解で役に立たないエラーメッセージが表示されます。v4は準備ができていません。
2018

回答:


121

まだ正式リリースではありませんが、次期Gulp 4.0ではgulp.seriesを使用して同期タスクを簡単に実行できます。あなたは単にこのようにそれを行うことができます:

gulp.task('develop', gulp.series('clean', 'coffee'))

アップグレードしてこれらのきちんとした機能を使用する方法を紹介する良いブログ投稿を見つけました: 例としてgulp 4への移行


3
すべての新参者のための選択の方法。彼らは本当に一口4から始めるべきであり、すべての3. *の面倒で幅広いアンチパターンをスキップします。
メタリム

187
その2017と彼らはまだそれを導入していませんでした。すごい。
Tomasz Mularczyk 2017年

14
本当に要点はわかりません。Bの実行後にのみAを実行する必要がある場合、AはBに依存します。BがAの依存関係であることを指定できないのはなぜですか。gulp.task('coffee', ['clean'], function(){...}); gulp.task('develop', ['coffee']);
musicin3d 2017年

3
@ musicin3d言ったことは機能しますが、1つのタスクを前のタスクに結合する必要があります。たとえば、いつも前に糸くずを出さなくても構築できるようにしたいです。独立したタスクを持ち、外部ツールを使用して実行の順序を決定する方が良いソリューションです。
AxeEffect

11
その2018年、彼らはついにそれを導入しました。すごい。
dargmuesli

411

デフォルトでは、明示的な依存関係がない限り、gulpはタスクを同時に実行します。これはclean、依存したくないのようなタスクにはあまり役立ちませんが、他のすべての前に実行する必要があります。

私が書いたプラグインをがぶ飲みして、この問題を解決するために特別に。インストールしたら、次のように使用します。run-sequence

var runSequence = require('run-sequence');

gulp.task('develop', function(done) {
    runSequence('clean', 'coffee', function() {
        console.log('Run something else');
        done();
    });
});

パッケージのREADMEで完全な説明を読むことができます—また、いくつかのタスクセットを同時に実行することもできます。

依存関係の自動順序付けを完全に排除し、希望する実行順序を手動で指定できるようなツールを提供するため、これはgulpの次のメジャーリリースで(事実上)修正されることに注意してくださいrun-sequence

ただし、これは重大な重大な変更であるため、run-sequence今日使用できるようになるまで待つ必要はありません。


2
@OverZealousプラグインをありがとう!ところで、gulp-cleanプラグインはStreams 2を実装していなかったため、依存関係として実行すると問題が発生しました。これはリリースバージョン0.3.0で修正され、同僚がPRを送信して変換しました。
Knowasilya 2014年

3
@Indolering組み込みのタスク依存機能はこのシナリオを解決しませ。依存タスクは常に実行されていない:何行に二つのタスクを実行するための方法であっ組み込まれているいくつかの時間ではなく、すべての時間。 run-sequencegulpで欠落している機能の重要な部分を解決します。
OverZealous 2015年

2
また、タスクの依存関係は完全なソリューションではありません。データベースを使用してテストを個別に実行する2つのgulpタスクがあるとします。どちらも他方に依存しているわけではありませんが、どちらもデータベースを使用する必要があるため、どちらも同時に実行したくありません。
peterjwest 2015年

3
すばらしいモジュール-なぜそれが必要なのかについての素晴らしい説明があります-blog.mdnbar.com/gulp-for-simple-build-proccess-これは受け入れられる答えになるはずです
danday74

5
この問題の解決策を作成していただいたことに感謝しますが、順次実行するために追加のツールが必要になるのは不合理です。順次実行がデフォルトであるか、少なくとも簡単に実行できる必要があります。Makefileは40年間連続して実行されてきました。JSエコシステムは私を病気にします。73 MBのnode_modulesは、機能なしでボイラープレートプロジェクトをコンパイルするためだけのものであり、シーケンシャル実行の機能はまだ含まれていません。オペレーティングシステムは狭いスペースに収まり、カーネルとドライバーFFSを備えています。
joonas.fi 2017

371

この問題に対する唯一の良い解決策は、ここにあるgulpのドキュメントにあります。

var gulp = require('gulp');

// takes in a callback so the engine knows when it'll be done
gulp.task('one', function(cb) {
  // do stuff -- async or otherwise
  cb(err); // if err is not null and not undefined, the orchestration will stop, and 'two' will not run
});

// identifies a dependent task must be complete before this one begins
gulp.task('two', ['one'], function() {
  // task 'one' is done now
});

gulp.task('default', ['one', 'two']);
// alternatively: gulp.task('default', ['two']);

6
何らかの理由ReferenceError: err is not definedで、これをgulp-compassタスクで実行しようとしていますが、何か不足していますか?
ワッフル2015

11
@wafflこの例ではコールバックを使用していますが、これが唯一の方法ではありません。ドキュメントによると、「エンジンが解決または終了するのをそれぞれ待つプロミスまたはストリームを返す」こともできます。したがって、たとえばタスク1でストリームを返す場合return gulp.src('app/**/*.js').pipe(concat(app.js)).pipe(gulp.dest('app/scripts');、重要なのは、タスク2を定義するときに、タスク1を従属として識別することです。gulp.task('two', ['one'], function() {... タスク2は、実行する前にタスク1が終了するのを待ちます。
esvendsen 2015

24
これにより、「1つ」と「2つ」の間に密結合が生じます。何が「1」を実行せずに「2」を実行したい場合は
ウィルクを

5
依存関係のない新しいタスクを定義しますか?
MathieuBorderé15年

8
連続して実行するために2つのタスクが必要であることは、密結合を意味します。
リンゴ

56

generator-gulp-webapp Yeomanジェネレーターを使用してnode / gulpアプリを生成しました。この方法で「問題の整理」を処理しました(質問で述べた元のタスクに変換します)。

gulp.task('develop', ['clean'], function () {
  gulp.start('coffee');
});

2
これは私が必要とする正確な(そして非常に単純な)ものでした。これらのタスクへの依存関係としてcleanを設定せずに依存関係を構築するために、先行する依存関係としてcleanのようなものを実行する必要があるシナリオに対処します。PS:gulp.start()ビットに関する情報-警告の警告:github.com/gulpjs/gulp/issues/426
Jaans

それは理にかなっている; メインタスク(およびその依存タスク)が完了した後のコールバック。ありがとう。
markau

4
の公式ドキュメントがない理由を誰かが疑問に思っている場合gulp.start()gulpメンバーからのこの回答は次のように説明しています:gulp.start is undocumented on purpose because it can lead to complicated build files and we don't want people using it(source:github.com/gulpjs/gulp/issues/426#issuecomment-41208007
thybzi

1
この場合、coffeeタスクが終了したことをどのように検出できますか?それが検出されない場合、developタスクはそれより早く終了しますcoffee
thybzi

すでにrun-sequenceソースコードから回答を得ています:gulp.on('task_stop')。詳細については、拡張回答をご覧ください:stackoverflow.com/a/38818657/3027390
thybzi

32

run-sequenceが最も明確な方法です(少なくともGulp 4.0がリリースされるまで)

run-sequenceを使用すると、タスクは次のようになります。

var sequence = require('run-sequence');
/* ... */
gulp.task('develop', function (done) {
    sequence('clean', 'coffee', done);
});

しかし、(何らかの理由で)使用したくない場合は、gulp.startメソッドが役立ちます

gulp.task('develop', ['clean'], function (done) {
    gulp.on('task_stop', function (event) {
        if (event.task === 'coffee') {
            done();
        }
    });
    gulp.start('coffee');
});

注: 結果を聞かずにタスクを開始するだけの場合、developタスクはより早く終了し、coffee混乱を招く可能性があります。

不要な場合は、イベントリスナーを削除することもできます

gulp.task('develop', ['clean'], function (done) {
    function onFinish(event) {
        if (event.task === 'coffee') {
            gulp.removeListener('task_stop', onFinish);
            done();
        }
    }
    gulp.on('task_stop', onFinish);
    gulp.start('coffee');
});

考えてみても、そこにあるtask_errイベント聴きたいことが。 task_stop正常に終了するとトリガーされtask_errますが、エラーが発生すると表示されます。

の公式ドキュメントがないのも不思議に思うかもしれませんgulp.start()。gulpメンバーからのこの回答は、次のことを説明しています。

gulp.start ビルドファイルが複雑になる可能性があるため、意図的に文書化されていません。

(ソース:https : //github.com/gulpjs/gulp/issues/426#issuecomment-41208007


この男にコーヒーを2杯!リスナーを削除するソリューションは完全に機能します!
daniel.bavrin 2017

これが本当に答え、または単に「一口」です。実行シーケンスは堅牢です。
LAdams87

26

Gulpのドキュメントによると:

依存関係が完了する前にタスクが実行されていますか?依存関係タスクが非同期実行ヒントを正しく使用していることを確認してください:コールバックを受け取るか、promiseまたはイベントストリームを返します。

タスクのシーケンスを同期的に実行するには:

  1. イベントストリーム(などgulp.src)をgulp.taskに戻し、ストリームがいつ終了するかをタスクに通知します。
  2. の2番目の引数でタスクの依存関係を宣言しますgulp.task

改訂されたコードを参照してください:

gulp.task "coffee", ->
    return gulp.src("src/server/**/*.coffee")
        .pipe(coffee {bare: true}).on("error",gutil.log)
        .pipe(gulp.dest "bin")

gulp.task "clean", ['coffee'], ->
      return gulp.src("bin", {read:false})
        .pipe clean
            force:true

gulp.task 'develop',['clean','coffee'], ->
    console.log "run something else"

4
これが正解です!戻るタスクはトリックをしました!ありがとう。
Dzoukr

10

私はこれとまったく同じ問題を抱えていましたが、解決策は私にとってかなり簡単であることがわかりました。基本的にコードを次のように変更すれば動作するはずです。注:gulp.srcの前の復帰は、私にとってすべての違いをもたらしました。

gulp.task "coffee", ->
    return gulp.src("src/server/**/*.coffee")
        .pipe(coffee {bare: true}).on("error",gutil.log)
        .pipe(gulp.dest "bin")

gulp.task "clean",->
    return gulp.src("bin", {read:false})
        .pipe clean
            force:true

gulp.task 'develop',['clean','coffee'], ->
    console.log "run something else"

返却についてのメモをありがとう!gulpがsrc-ingタスクを順不同で行っている理由を理解しようと一生懸命でした。
アンドリューF

これは、タスク間の密結合を回避するための正しい答えである必要があります。うまくいきます。4.0で利用可能なgulp.seriesがおそらく最良の答えですが、現在のところ4.0は利用できません。
15

gulpの開発は、最初にクリーンまたはコーヒーで実行されます
スケープは

8

提案されたすべてのソリューションを試しましたが、すべて独自の問題があるようです。

実際にOrchestratorのソース、特に.start()実装を調べると、最後のパラメーターが関数の場合はコールバックとして扱われることがわかります。

私は自分のタスクのためにこのスニペットを書きました:

  gulp.task( 'task1', () => console.log(a) )
  gulp.task( 'task2', () => console.log(a) )
  gulp.task( 'task3', () => console.log(a) )
  gulp.task( 'task4', () => console.log(a) )
  gulp.task( 'task5', () => console.log(a) )

  function runSequential( tasks ) {
    if( !tasks || tasks.length <= 0 ) return;

    const task = tasks[0];
    gulp.start( task, () => {
        console.log( `${task} finished` );
        runSequential( tasks.slice(1) );
    } );
  }
  gulp.task( "run-all", () => runSequential([ "task1", "task2", "task3", "task4", "task5" ));

4

しばらくこの答えを探していました。今、私は公式のgulpのドキュメントでそれを得ました。

最後のタスクが完了したときにgulpタスクを実行する場合は、ストリームを返す必要があります。

gulp.task('wiredep', ['dev-jade'], function () {
    var stream = gulp.src(paths.output + '*.html')
        .pipe($.wiredep())
        .pipe(gulp.dest(paths.output));

    return stream; // execute next task when this is completed
});

// First will execute and complete wiredep task
gulp.task('prod-jade', ['wiredep'], function() {
    gulp.src(paths.output + '**/*.html')
        .pipe($.minifyHtml())
        .pipe(gulp.dest(paths.output));
});


3

単ににcoffee依存しcleandevelop依存しcoffeeます:

gulp.task('coffee', ['clean'], function(){...});
gulp.task('develop', ['coffee'], function(){...});

発送は今シリアルです:cleancoffeedevelopcleanの実装とcoffeeの実装コールバックを受け入れる必要があることに注意してください。「そうすることで、エンジンはいつ実行されるかを認識できます」

gulp.task('clean', function(callback){
  del(['dist/*'], callback);
});

結論として、以下は、同期とclean非同期のビルド依存関係が続く単純なgrupパターンです

//build sub-tasks
gulp.task('bar', ['clean'], function(){...});
gulp.task('foo', ['clean'], function(){...});
gulp.task('baz', ['clean'], function(){...});
...

//main build task
gulp.task('build', ['foo', 'baz', 'bar', ...], function(){...})

Gulpは、依存関係がいくつ依存していても、clean1回に1回だけ実行できるほどスマートです。上記のように、は同期バリアであり、のすべての依存関係は並列に実行され、次に実行されます。buildbuildcleancleanbuildbuild


3

私にとっては、連結された入力を想定しているため、連結後にminifyタスクを実行していませんでした。

デフォルトのタスクに実行順に追加してみましたが、うまくいきませんでした。return各タスクにa を追加し、gulp.start()以下のように内部に縮小化した後、それは機能しました。

/**
* Concatenate JavaScripts
*/
gulp.task('concat-js', function(){
    return gulp.src([
        'js/jquery.js',
        'js/jquery-ui.js',
        'js/bootstrap.js',
        'js/jquery.onepage-scroll.js',
        'js/script.js'])
    .pipe(maps.init())
    .pipe(concat('ux.js'))
    .pipe(maps.write('./'))
    .pipe(gulp.dest('dist/js'));
});

/**
* Minify JavaScript
*/
gulp.task('minify-js', function(){
    return gulp.src('dist/js/ux.js')
    .pipe(uglify())
    .pipe(rename('ux.min.js'))
    .pipe(gulp.dest('dist/js'));
});

gulp.task('concat', ['concat-js'], function(){
   gulp.start('minify-js');
});

gulp.task('default',['concat']); 

ソースhttp://schickling.me/synchronous-tasks-gulp/


2

GulpとNodeはpromiseを使用しています。

だからあなたはこれを行うことができます:

// ... require gulp, del, etc

function cleanTask() {
  return del('./dist/');
}

function bundleVendorsTask() {
  return gulp.src([...])
    .pipe(...)
    .pipe(gulp.dest('...'));
}

function bundleAppTask() {
  return gulp.src([...])
    .pipe(...)
    .pipe(gulp.dest('...'));
}

function tarTask() {
  return gulp.src([...])
    .pipe(...)
    .pipe(gulp.dest('...'));
}

gulp.task('deploy', function deployTask() {
  // 1. Run the clean task
  cleanTask().then(function () {
    // 2. Clean is complete. Now run two tasks in parallel
    Promise.all([
      bundleVendorsTask(),
      bundleAppTask()
    ]).then(function () {
      // 3. Two tasks are complete, now run the final task.
      tarTask();
    });
  });
});

gulpストリームを返す場合、then()メソッドを使用してコールバックを追加できます。または、NodeのネイティブPromiseを使用して独自のプロミスを作成することもできます。ここPromise.all()では、すべてのpromiseが解決されたときに発生する1つのコールバックを使用しています。


-8

このハックを試してください:-) Gulp v3.x非同期バグのハック

Readmeの「公式」の方法をすべて試しましたが、うまくいきませんでした。gulp 4.xにアップグレードすることもできますが、アップグレードしないことを強くお勧めします。あなたは本当のjs promiseを使うことができますが、ちょっと、これは速くて汚い、シンプルです:-)基本的に次のものを使います:

var wait = 0; // flag to signal thread that task is done
if(wait == 0) setTimeout(... // sleep and let nodejs schedule other threads

投稿をチェックしてください!


問題を解決するより良い方法があります。setTimeoutの使用は適切ではありません。タスクが完了するまでにかかる時間を正確に知ることができませんでした。
レジナルドカマルゴリベイロ2016

あなたはコードpffを書く前に本当に考えるべきです
DDD
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.