Running Gulp tasks synchronously

Gulp tasks run asynchronously. For example when you describe your build task like this:

gulp.task('build', ['clean', 'html', 'sass', 'coffee']);

you can’t be sure in which exact order the tasks will be finished. Sometimes this is the source of problems. For example, if sass task is trying to compile your styles into the build directory and at the same time clean trying to empty that directory, you can get in a lot of trouble.

Now one way of solving this is to specify task dependencies. You declare you sass, html, coffee as being dependent on clean:

gulp.task('sass', ['clean'], function() { ... })
gulp.task('html', ['clean'], function() { ... })
gulp.task('coffee', ['clean'], function() { ... })

Gulp will guarantee that these tasks will start running only after clean is finished. Which of cause is nice, but if you use livereload and watch sources to recompile on the fly, this can cause another sort of trouble. Consider this:

gulp.task('connect', ['build'], function() {
  // Starting the server
  connect.server({ livereload: true, root: 'build' });

  // Rebuild if sources change
  ['html', 'sass', 'coffee'].forEach(function(task) {
    gulp.watch(paths[p], [p]);
  });

  // Reload browser on build change
  watch(paths.build).pipe(connect.reload());
});

We want to rebuild our coffee/sass/html assets every time the source changes. The important thing is that we don’t want to run through the entire build process. If sass sources change we only want sass recompiled. But sass task depends on clean which means that the whole build directory will be emptied causing our site to break.

So we’d need to introduce the whole new kind of clean tasks e.g. clean-html, clean-css, clean-javascript which would clean only the appropriate build subdirectories. And then:

gulp.task('build', ['html', 'sass', 'coffee']);

gulp.task('sass', ['clean-css'], function() { ... })
gulp.task('html', ['clean-html'], function() { ... })
gulp.task('coffee', ['clean-javascript'], function() { ... })

I don’t like that approach much. If only we could run our clean task in the build strictly before sass/coffee/html that would do it for us. It turns out we can with the help of this extremely useful run-sequence plugin by Phil DeJarnett. With the help of this, we can simply write this:

gulp.task 'build', function (cb) {
  runSeq('clean', ['html', 'sass', 'coffee'], cb)
}

This is it. Now we can eliminate dependencies on clean task in our compile tasks and livereload with partial precompiling will work just fine.

P.S.: I run a weekly JavaScript round-up newsletter. So if you want to be updated with the latest JS news and articles, feel free to sign up.

 
341
Kudos
 
341
Kudos

Now read this

JavaScript hacks explained

There are several JavaScript tricks that are used widely by experienced programmers. Many of them may not be instantly obvious, especially for beginners. These tricks use language features not by their direct purpose, but rather by their... Continue →