web-dev-qa-db-fra.com

Comment exécuter les tâches Gulp séquentiellement les unes après les autres

dans l'extrait comme ceci:

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"

Dans la tâche develop, je veux exécuter clean et ensuite, exécuter coffee, puis exécuter autre chose. Mais je ne peux pas comprendre cela. Cette pièce ne fonctionne pas. S'il vous plaît donnez votre avis.

393
iLemming

Ce n'est pas encore une version officielle, mais la prochaine version de Gulp 4.0 vous permet d'effectuer facilement des tâches synchrones avec gulp.series. Vous pouvez simplement le faire comme ceci:

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

J'ai trouvé un bon article de blog qui explique comment mettre à niveau et utiliser ces fonctionnalités intéressantes: migration vers gulp 4 par exemple

116
massanishi

Par défaut, gulp exécute des tâches simultanément, sauf si elles ont des dépendances explicites. Ce n'est pas très utile pour des tâches telles que clean, pour lesquelles vous ne voulez pas dépendre, mais dont vous avez besoin avant.

J'ai écrit le plugin run-sequence spécialement pour résoudre ce problème avec gulp. Après l'avoir installé, utilisez-le comme ceci:

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

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

Vous pouvez lire les instructions complètes sur le paquet README - il prend également en charge l’exécution simultanée de certains ensembles de tâches.

Veuillez noter que ceci sera (effectivement) corrigé dans la prochaine version majeure de gulp , car ils éliminent complètement le classement automatique des dépendances et fournissent des outils similaires à run-sequence pour vous permettre de spécifiez l'ordre d'exécution comme vous le souhaitez.

Cependant, il s’agit d’un changement radical majeur. Il n’ya donc aucune raison d’attendre lorsque vous pouvez utiliser run-sequence aujourd’hui.

410
OverZealous

La seule bonne solution à ce problème peut être trouvée dans la documentation gulp qui peut être trouvée ici

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']);
371
Mathieu Borderé

J'ai généré une application nœud/gulp à l'aide du générateur générateur-gulp-webapp Yeoman. Il traitait le "casse-tête propre" de cette façon (en traduisant les tâches originales mentionnées dans la question):

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

run-sequence est le moyen le plus clair (au moins jusqu'à ce que Gulp 4.0 soit publié)

Avec run-sequence , votre tâche ressemblera à ceci:

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

Mais si vous (pour une raison quelconque) préférez ne pas l'utiliser, la méthode gulp.start vous aidera :

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

Remarque: Si vous ne démarrez que la tâche sans écouter le résultat, la tâche develop se terminera plus tôt que coffee, et cela peut être déroutant.

Vous pouvez également supprimer le programme d'écoute d'événement lorsque vous n'en avez pas besoin

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

Considérez un autre événement task_err que vous souhaitez peut-être écouter. task_stop est déclenché à la fin, tandis que task_err apparaît en cas d'erreur.

Vous pouvez également vous demander pourquoi il n’existe pas de documentation officielle pour gulp.start(). Cette réponse d'un membre de gulp explique les choses:

gulp.start est délibérément non documenté car il peut entraîner des fichiers de construction compliqués et nous ne voulons pas que les gens l'utilisent

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

32
thybzi

Selon les documents Gulp:

Vos tâches sont-elles en cours d'exécution avant la fin des dépendances? Assurez-vous que vos tâches de dépendance utilisent correctement les astuces d'exécution asynchrone: recevez un rappel ou renvoyez une promesse ou un flux d'événements.

Pour exécuter votre séquence de tâches de manière synchrone:

  1. Renvoyez le flux d'événements (par exemple gulp.src) à gulp.task pour informer la tâche de la fin du flux.
  2. Déclarez les dépendances de tâches dans le deuxième argument de gulp.task.

Voir le code révisé:

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"
26
senornestor

J'avais exactement le même problème et la solution s'est révélée assez facile pour moi. Modifiez fondamentalement votre code comme suit et cela devrait fonctionner. NOTE: le retour avant gulp.src a fait toute la différence pour moi.

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"
9
Craig

essayé toutes les solutions proposées, toutes semblent avoir leurs propres problèmes.

Si vous regardez réellement dans la source de l'orchestrateur, en particulier dans l'implémentation .start(), vous verrez que si le dernier paramètre est une fonction, il le traitera comme un rappel.

J'ai écrit cet extrait pour mes propres tâches:

  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" ));
7
Assaf Moldavsky

Je cherchais cette réponse pendant un moment. Maintenant, je l'ai dans la documentation officielle de gulp.

Si vous souhaitez effectuer une tâche d'absorption lorsque la dernière est terminée, vous devez renvoyer un flux:

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));
});
4
Lucho Suárez

Pour moi, la tâche de minify n'était pas exécutée après la concaténation car elle attendait une entrée concaténée et elle n'a pas été générée à plusieurs reprises.

J'ai essayé d'ajouter une tâche par défaut dans l'ordre d'exécution et cela n'a pas fonctionné. Cela fonctionnait après avoir ajouté juste un return pour chaque tâche et obtenir la minification à l'intérieur de gulp.start() comme ci-dessous.

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

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

3
devo

Faites simplement coffee dépendre de clean, et develop dépend de coffee:

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

Le dispatch est maintenant en série: cleancoffeedevelop. Notez que l'implémentation de clean et celle de coffee doivent accepter un rappel, "afin que le moteur sache quand il ' Tout sera fait " :

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

En conclusion, vous trouverez ci-dessous un modèle de groupe simple pour un clean synchrone suivi de dépendances de construction asynchrones :

//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 est suffisamment intelligent pour exécuter clean exactement une fois par build, quel que soit le nombre de dépendances de build dépendant de clean. Comme indiqué ci-dessus, clean est une barrière de synchronisation; toutes les dépendances de build sont exécutées en parallèle, puis build est exécuté.

3
akarve

Gulp et Node utilisent promesses.

Donc, vous pouvez faire ceci:

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

Si vous renvoyez le flux gulp, vous pouvez utiliser la méthode then() pour ajouter un rappel. Alternativement, vous pouvez utiliser le Promise natif de Node pour créer vos propres promesses. Ici, j'utilise Promise.all() pour avoir un rappel qui se déclenche lorsque toutes les promesses sont résolues.

2
Peter J. Hart