Gulp görevleri birbiri ardına nasıl çalıştırılır


398

snippet'te şöyle:

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"

Gelen developgörev ı çalıştırmak istiyorum cleanve bitti sonra çalıştırın coffeeve bitince, başka bir şey çalıştırın. Ama bunu anlayamıyorum. Bu parça çalışmıyor. Tavsiye lütfen.


10
Çalışma sırası npm modülü bu sorunu şimdi gideriyor - diğer tüm yanıtlar artık önemsiz - aşağıdaki OverZealous'un cevabına bakınız
danday74

1
Gulp 4.0 yerel olarak sırayla çalışan görevleri destekler run-sequence- kullanılmaz hale getirir - aşağıdaki massanishi'nin cevabına bakınız
Forivin

Gulp4 düzelttiğinden daha fazla şey kırıyor, öyle görünüyor. Birkaç saat boyunca onunla savaştıktan sonra, 3.9.1'e geri döndüm. Ben büyük sürümleri geri uyum bozabilir / şifreli ve işe yaramaz hata mesajları ile fark, ben hayır teşekkürler. v4 hazır değil.
Sat Thiru

Yanıtlar:


121

Henüz resmi bir sürüm değil, ancak yaklaşan Gulp 4.0, gulp.series ile eşzamanlı görevleri kolayca yapmanızı sağlar. Bunu şu şekilde yapabilirsiniz:

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

Bu düzgün özelliklerin nasıl yükseltileceğini ve kullanılacağını tanıtan iyi bir blog yazısı buldum: örnek olarak gulp 4'e geçiş


3
Tüm yeni gelenler için tercih edilen yöntem. Gerçekten de yudum 4 ile başlamalı, tüm 3'ü atlamalı. * Güçlük ve çok çeşitli antipatterns.
metalim

187
2017 ve hala tanıtmadılar. Harika.
Tomasz Mularczyk

14
Gerçekten anlamıyorum. A'nın yalnızca B çalıştırıldıktan sonra çalışması için kesinlikle ihtiyacınız varsa, A B'ye bağlıdır. Neden B'nin A'nın bağımlılığı olduğunu belirleyemiyorsunuz? gulp.task('coffee', ['clean'], function(){...}); gulp.task('develop', ['coffee']);
musicin3d

3
@ musicin3d Söyledikleriniz işe yarıyor, ancak bir görevi mutlaka bir öncekiyle birleştiriyorsunuz. Örneğin, daha önce tiftik yapmak zorunda kalmadan inşa edebilmek istiyorum. Bağımsız görevlere sahip olmak ve harici bir araçla yürütme sırasına karar vermek daha iyi bir çözümdür.
AxeEffect

11
2018 ve sonunda tanıttılar. Harika.
dargmuesli

411

Varsayılan olarak, gulp, açık bağımlılıkları olmadıkça görevleri aynı anda çalıştırır. Bu, cleanbağımlı olmak istemediğiniz görevler için çok yararlı değildir, ancak diğer her şeyden önce çalışması için onlara ihtiyacınız vardır.

Yazdığım eklentisi yudum ile bu sorunu gidermek için özel olarak. Yükledikten sonra şu şekilde kullanın:run-sequence

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

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

README paketinin tüm talimatlarını okuyabilirsiniz - ayrıca bazı görevlerin aynı anda çalıştırılmasını da destekler.

Otomatik bağımlılık sırasını tamamen ortadan kaldırdıklarından ve çalışma sırasını istediğiniz gibi manuel olarak belirlemenize olanak tanıyacak benzer araçlar sağladığından, bu , yemin sonraki büyük sürümünde (etkili bir şekilde) düzeltileceğini unutmayın run-sequence.

Ancak, bu büyük bir kırılma değişikliği, bu yüzden run-sequencebugün kullanabileceğiniz zaman beklemek için bir neden yok .


2
Eklenti için @OverZealous teşekkürler! Btw, gulp-cleaneklenti Streams 2'yi uygulamıyordu, bu yüzden bağımlılık olarak çalıştırılmakta olan sorunları vardı. Bu sürüm 0.3.0'dan itibaren düzeltildi, iş arkadaşım dönüştürmek için bir PR gönderdi.
bilinenasilya

3
@Indolering yerleşik görev bağımlılığı işlevselliği yok değil bu senaryoyu çözmek. Hiçbir üst üste iki görevi çalıştırmak için bir şekilde orada yerleşik: Bağımlı görevler hep çalıştırılır bazı zaman değil her zaman. run-sequenceyudumdaki kritik bir işlevsellik parçasını çözer.
OverZealous

2
Ayrıca, görev bağımlılıkları tam bir çözüm değildir. Diyelim ki veritabanını kullanarak bağımsız olarak testler yürüten iki görevim var. İkisi de diğerine bağımlı değildir, ancak ikisinin de veritabanını kullanması gerektiğinden ikisinin de aynı anda çalışmasını istemiyorum.
peterjwest

3
İnanılmaz modül - Heres neden gerekli olduğuna dair harika bir açıklama - blog.mdnbar.com/gulp-for-simple-build-proccess - Bu kabul edilmiş cevap olmalı
danday74

5
Bunun için bir çözüm yaptığınız için minnettarım, ancak sıralı yürütme için ek araçlara ihtiyacımız olduğu saçma. Sıralı yürütme varsayılan olmalıdır veya en azından kolayca yapılabilir. Makefiles 40 yıldır sıralı olarak icra edildi. JS ekosistemi beni hasta ediyor. 73 megabayt node_modules, herhangi bir özellik olmadan bir kazan plakası projesini derlemek için ve yine de sıralı yürütme yeteneğini içermiyor. İşletim sistemleri daha küçük bir alana sığar ve Çekirdekler ve sürücüler FFS'leri vardır.
joonas.fi

371

Bu soruna tek iyi çözüm, burada bulunan yutkunma belgelerinde bulunabilir .

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
Nedense bunu ReferenceError: err is not definedbir gulp-compassgörevde çalıştırmaya çalışıyorum, bir şey mi kaçırıyorum?
waffl

11
@waffl bu örnek, bunu yapmanın tek yolu olmayan bir geri arama kullanır. Dokümanlara göre , "motorun sırasıyla çözmek veya bitirmek için beklemesi gereken bir söz veya akış da verebilirsiniz". Dolayısıyla, birinci görevdeki bir akışı döndürürseniz, örneğin return gulp.src('app/**/*.js').pipe(concat(app.js)).pipe(gulp.dest('app/scripts');anahtar görev 2'yi tanımlarken bağımlı olanı bir görev olarak tanımlamaktır: İkinci görev gulp.task('two', ['one'], function() {... şimdi çalıştırılmadan önce birinci görevin bitmesini bekleyecektir.
esvendsen

24
Bu, 'bir' ve 'iki' arasında sıkı bir bağlantı yaratır. 'Bir' çalıştırmadan 'iki' koşmak isterseniz
15'de wilk

5
bağımlılık olmadan yeni bir görev tanımlamak?
Mathieu Borderé

8
Sıralı olarak çalıştırmak için iki göreve ihtiyaç duyulması, sıkı bir bağlantı anlamına gelir.
Ringo

56

Ben jeneratör-gulp-webapp Yeoman jeneratör kullanarak bir düğüm / yutmak uygulaması oluşturdu . "Temiz muamma" yı bu şekilde ele aldı (soruda belirtilen orijinal görevlere tercüme edildi):

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

2
Bu ihtiyacım olan tam (ve çok basit) idi. Bu görevlere bağımlılık olarak temiz ayarlamadan bağımlılıklar oluşturmak için önceki bağımlılık gibi temiz bir şey yapmam gereken senaryoyu ele alır. Not: gulp.start () biti hakkında bilgi - uyarı emptor: github.com/gulpjs/gulp/issues/426
Jaans

Mantıklı; ana görev (ve bağımlı görevler) tamamlandıktan sonra geri arama. Teşekkürler.
markau

4
Birisi neden resmi bir belge olmadığını merak ederse, gulp üyesindengulp.start() gelen bu cevap şunları açıklar: gulp.start is undocumented on purpose because it can lead to complicated build files and we don't want people using it(kaynak: github.com/gulpjs/gulp/issues/426#issuecomment-41208007 )
thybzi

1
Bu durumda, coffeegörevin bittiğini nasıl tespit edebilirim ? Tespit developcoffee
etmezsem

Zaten gelen cevabı var run-sequencekaynak kodu: gulp.on('task_stop'). Ayrıntılar için genişletilmiş
cevabıma

32

çalışma sırası en açık yoldur (en azından Gulp 4.0 piyasaya sürülene kadar)

Çalışma sırası ile göreviniz şöyle görünecektir:

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

Ancak (herhangi bir nedenden dolayı) kullanmamayı tercih ederseniz, gulp.startyöntem yardımcı olacaktır :

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

Not: Görevi yalnızca sonucu dinlemeden başlatırsanız, developgörev daha önce biter coffeeve bu kafa karıştırıcı olabilir.

Gerektiğinde olay dinleyicisini de kaldırabilirsiniz

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');
});

Dinlemek isteyebileceğiniz bir olay olduğunu datask_err düşünün . task_stopbaşarılı bir bitişte tetiklenirken task_err, bir hata olduğunda görünür.

Ayrıca neden resmi bir belge bulunmadığını merak edebilirsiniz gulp.start(). Gulp üyesinden gelen bu cevap şunları açıklıyor:

gulp.start amaçlanmamıştır çünkü karmaşık yapı dosyalarına yol açabilir ve insanların onu kullanmasını istemiyoruz

(kaynak: https://github.com/gulpjs/gulp/issues/426#issuecomment-41208007 )


Bu adama iki kahve! dinleyiciyi kaldırarak çözüm mükemmel çalışır!
daniel.bavrin

Bu gerçekten cevap, ya da sadece "gulp 4". Çalışma sırası sağlam.
LAdams87

26

Gulp belgelerine göre:

Görevleriniz bağımlılıklar tamamlanmadan çalışıyor mu? Bağımlılık görevlerinizin zaman uyumsuz çalıştırma ipuçlarını doğru kullandığından emin olun: geri arama yapın veya bir söz veya olay akışı döndürün.

Görev dizinizi senkronize olarak çalıştırmak için:

  1. Akışın ne zaman sona ereceği konusunda bilgi vermek için olay akışını (örn. gulp.src) gulp.taskDöndürün.
  2. 'Nin ikinci argümanında görev bağımlılıklarını bildirin gulp.task.

Gözden geçirilmiş koda bakın:

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
BU doğru cevap olmalı! Görev geri döndü! Teşekkürler dostum.
Dzoukr

10

Aynı sorunu yaşıyordum ve çözüm benim için oldukça kolay çıktı. Temel olarak kodunuzu aşağıdaki şekilde değiştirin ve çalışması gerekir. NOT: gulp.src'den önceki dönüş benim için tüm farkı yarattı.

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"

Dönen not için teşekkürler! Yutkunanın görevleri neden bozduğunu anlamaya çalışırken çıldırmıştı.
Andrew F

Görevler arasında sıkı bağlantıyı önlemek için bu doğru cevap olmalıdır. İyi çalışıyor. 4.0'da bulunan gulp.series muhtemelen en iyi cevaptır, ancak bugün itibariyle 4.0 mevcut değildir.
wilk

yutmak geliştirmek temiz veya kahve ilk çalışacak
scape

8

önerilen tüm çözümleri denedim, hepsinin kendi sorunları var gibi görünüyor.

Gerçekten Orkestratör kaynağına, özellikle .start()uygulamaya bakarsanız, son parametre bir işlevse onu geri arama olarak değerlendireceğini göreceksiniz.

Bu pasajı kendi görevlerim için yazdım:

  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

Bir süredir bu cevabı arıyordum. Şimdi resmi yemin belgelerinde aldım.

Sonuncusu tamamlandığında yutkunma görevi gerçekleştirmek istiyorsanız, bir akış döndürmeniz gerekir:

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

Sadece coffeebağımlı olun cleanve aşağıdakilere developbağlı olun coffee:

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

Dağıtım şimdi seri: cleancoffeedevelop. O Not clean'S uygulaması ve coffee' nın uygulanması gerekir , bir geri arama kabul 'bitti olarak ne zaman motor bilir böylece' :

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

Sonuç olarak, aşağıda bir eşzamanlı ve cleanardından eşzamansız yapı bağımlılıkları için basit bir yırtık biçimi verilmiştir :

//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, bağımlılıklarından kaçının bağlı olduğuna bakılmaksızın, cleantam olarak bir kez çalışacak kadar akıllıdır . Yukarıda yazıldığı gibi, bir senkronizasyon engeli, daha sonra tüm bağımlılıkları paralel olarak çalışır , sonra çalışır.buildbuildcleancleanbuildbuild


3

Benim için, birleştirilmiş girdiyi beklediğinden ve birkaç kez oluşturulmadığından, birleştirme işleminden sonra küçültme görevini çalıştırmıyordu.

Yürütme sırasında varsayılan bir göreve eklemeyi denedim ve işe yaramadı. returnHer görev için sadece bir ekledikten ve gulp.start()aşağıdaki gibi küçültmeyi içerdikten sonra çalıştı .

/**
* 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']); 

Kaynak http://schickling.me/synchronous-tasks-gulp/


2

Gulp ve Node vaadleri kullanır .

Böylece bunu yapabilirsiniz:

// ... 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();
    });
  });
});

Körfez akışını döndürürseniz, then()geri arama eklemek için yöntemi kullanabilirsiniz . Alternatif olarak, Promisekendi vaatlerinizi oluşturmak için Node's native'i kullanabilirsiniz. Burada Promise.all()tüm vaatler çözüldüğünde ateş bir geri arama için kullanın .


-8

Bu hack deneyin :-) Async hata için Gulp v3.x Hack

Benioku içindeki tüm "resmi" yolları denedim, benim için çalışmadılar ama bu işe yaradı. Ayrıca gulp 4.x'e yükseltebilirsiniz ama kesinlikle tavsiye etmiyorum, çok fazla şey kırıyor. Gerçek bir js söz kullanabilirsiniz, ama hey, bu hızlı, kirli, basit :-) Esasen kullanıyorsunuz:

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

Gönderiyi kontrol et!


Sorunu çözmenin daha iyi yolları vardır, setTimeout kullanımı uygun değildir. Bir görevin tamamlanması için ne kadar zaman alacağını tam olarak bilemezsiniz.
Reginaldo Camargo Ribeiro

Herhangi bir kod pff yazmadan önce gerçekten düşünmelisiniz
DDD
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.