Run code after gulp task done with all files

31,634

Solution 1

You could just make a task which depends on html-minify:

gulp.task('other-task', ['html-minify'], function() {
  //stuff
});

You could also listen for the stream end event inside the html-minify task:

gulp.task('html-minify', function(done) {
  var files = [
    relativePaths.webPath + '/*.html',
    relativePaths.webPath + '/components/**/*.html',
    relativePaths.webPath + '/' + relativePaths.appPath + '/components/**/*.html'
  ];

  var changedFiles = buildMetaData.getChangedFiles(files);

  //TODO: needs to execute only after successful run of the task
  buildMetaData.addBuildMetaDataFiles(changedFiles);
  buildMetaData.writeFile();
  var stream = gulp.src(changedFiles, {
      base: relativePaths.webPath
    })
    .pipe(filelog())
    .pipe(minifyHtml({
      empty: true,
      quotes: true,
      conditionals: true,
      comments: true
    }))
    .pipe(gulp.dest(relativePaths.webPath + '/' + relativePaths.appPath +  '/' + relativePaths.buildPath));

  stream.on('end', function() {
    //run some code here
    done();
  });
  stream.on('error', function(err) {
    done(err);
  });
});

Solution 2

You can also merge two streams with with event-stream. This example takes input from the command line with yargs, builds a config and then merges the two:

var enviroment = argv.env || 'development';
gulp('build', function () {
    var config = gulp.src('config/' + enviroment + '.json')
      .on('end', function() { gutil.log(warn('Configured ' + enviroment + ' enviroment.')); })
      .pipe(ngConstant({name: 'app.config'}));
    var scripts = gulp.src('js/*');
    return es.merge(config, scripts)
      .pipe(concat('app.js'))
      .pipe(gulp.dest('app/dist'))
      .on('error', function() { });
  });

As well as the standard before tasks, you can also wait for a previous task to complete. This is useful when you need to pass arguments to the before task (which gulp does not currently support):

var tasks = {
  before: function(arg){
    // do stuff
  },
  build: function() { 
    tasks.before(arg).on('end', function(){ console.log('do stuff') });
  }
};

gulp('build', tasks.build);

Solution 3

GULP V3

Using dependency tasks:

gulp.task('qr-task', ['md-task', 'js-task'], function() {
  gulp.src(src + '/*.qr')
    .pipe(plugin())
    .pipe(gulp.dest(dist));
});

Although main task starts after all of dependent tasks but they (dependent tasks) will run in parallel (all at once), so don't assume that the tasks will start/finish in order (md and js run in parallel before qr).

If you want exact order for several tasks and don't want to split them you can use async & await to achieve this:

function Async(p) {
   return new Promise((res, rej) => p.on('error', err => rej(err)).on('end', () => res()));
}

gulp.task('task', async () => {

  await Async(gulp.src(src + '/*.md')
      .pipe(plugin())
      .pipe(gulp.dest(dist)));

  await Async(gulp.src(src + '/*.js')
      .pipe(plugin())
      .pipe(gulp.dest(dist)));

  await Async(gulp.src(src + '/*.qr')
      .pipe(plugin())
      .pipe(gulp.dest(dist)));
});

GULP V4

in gulp 4 the old dependency pattern is removed and you will get this error:

AssertionError [ERR_ASSERTION]: Task function must be specified

instead you must use gulp.parallel and gulp.series (which provides correct execution of tasks):

gulp.task('qr-task', gulp.series('md-task', 'js-task', function(done) {
  gulp.src(src + '/*.qr')
    .pipe(plugin())
    .pipe(gulp.dest(dist));
  done();
}));

for more detail visit https://github.com/gulpjs/gulp/blob/4.0/docs/API.md

Share:
31,634
ryanzec
Author by

ryanzec

A software engineer for severals years in web development with PHP/MySQL now focusing on front-end development with HTML, CSS, and JavaScript (AngularJS). Also and inspiring game developer using the Unity game engine.

Updated on October 09, 2020

Comments

  • ryanzec
    ryanzec over 3 years

    So I have been trying out Gulp to see how it compares to Grunt as far as speed and I am pretty impressed with the results but I have one thing I don't know how to do in Gulp.

    So I have this gulp task to minify HTML:

    gulp.task('html-minify', function() {
      var files = [
        relativePaths.webPath + '/*.html',
        relativePaths.webPath + '/components/**/*.html',
        relativePaths.webPath + '/' + relativePaths.appPath + '/components/**/*.html'
      ];
    
      var changedFiles = buildMetaData.getChangedFiles(files);
    
      //TODO: needs to execute only after successful run of the task
      buildMetaData.addBuildMetaDataFiles(changedFiles);
      buildMetaData.writeFile();
      return gulp.src(changedFiles, {
          base: relativePaths.webPath
        })
        .pipe(filelog())
        .pipe(minifyHtml({
          empty: true,
          quotes: true,
          conditionals: true,
          comments: true
        }))
        .pipe(gulp.dest(relativePaths.webPath + '/' + relativePaths.appPath +  '/' + relativePaths.buildPath));
    });
    

    The buildMetaData object has custom functionality that I need and why I can't use plugins like gulp-changed. What I am trying to figure out is how (if possible) to run a block of code after the minify is done process all files and it run successfully. Is something like this possible with gulp?

  • ryanzec
    ryanzec almost 10 years
    The second method was what I was looking for, thanks.
  • Colin
    Colin about 9 years
    You could do stream.on('error', done); to simplify it a minuscule amount. No need to create another anonymous function.
  • Edwin Chua
    Edwin Chua over 5 years
    The magic in [option 1] is that calling 'other-task' will automatically run 'html-minify', wait for it to finish, before running itself. Thanks!