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) {[p], [p]);

  // Reload browser on build change

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.


Now read this

11 JavaScript Blogs to Follow in 2017

There’s a huge benefit in running a JavaScript newsletter. You get to know about many smart people from whom you can learn a lot. Here are the most interesting blogs I stumbled upon. Feel free to add them directly to your preferred RSS... Continue →