A Quick Guide for Switching to Gulp 4

Mar 17, 2016
Gulp, Javascript, Node
~3min
Share on Twitter

A new version of gulp is here. What do you need to know? Will your gulpfiles break?

There are various changes listed in the CHANGELOG for gulp@4.0. The majority are non-breaking. The major breaking change is the introduction of gulp.series and gulp.parallel.

Before going any further, thanks to Gulp for sharing this guide over on Twitter 🐦!

For those in camp TL;DR — not a huge impact. Your tasks will break if they use the list parameter to define task dependencies. It’s not a huge refactor though to get things back in working order. You can see a gist using gulp@4.0 below and here’s a link to a gulp boilerplate using gulp@4.0.


            javascript
            
          import gulp from 'gulp'

const compileMarkup = () => { // COMPILE MARKUP }
const compileScript = () => { // COMPILE SCRIPT }
const compileStyle = () => { // COMPILE STYLE }

const watchMarkup = () => { // WATCH MARKUP }
const watchScript = () => { // WATCH SCRIPT }
const watchStyle = () => { // WATCH STYLE }

const compile = gulp.parallel(compileMarkup, compileScript, compileStyle)
compile.description = 'compile all sources'

// Not exposed to CLI
const startServer = () => { // START SERVER }

const serve = gulp.series(compile, startServer)
serve.description = 'serve compiled source on local server at port 3000'

const watch = gulp.parallel(watchMarkup, watchScript, watchStyle)
watch.description = 'watch for changes to all source'

const defaultTasks = gulp.parallel(serve, watch)

export {
  compile,
  compileMarkup,
  compileScript,
  compileStyle,
  serve,
  watch,
  watchMarkup,
  watchScript,
  watchStyle,
}

export default defaultTasks

Series + Paralell permalink

This is the big change. It seems there has been a big effort made towards enabling more control over how tasks run 🛂

Always in parallel or chained ⛓ permalink

In previous versions of gulp we could pass a list parameter to a task. This would define a set of tasks that would run before that task.


            javascript
            
          gulp.task('a', ['b', 'c'], function () { // do something})

In this example, task a relies on tasks b and c to run before it will. Tasks b and c will run in parallel. You don’t have control over their running order unless you create a chain;


            javascript
            
          gulp.task('a', ['c'], function () { // do something})
gulp.task('c', ['b'], function () { // do something})

This ensures a running order of b, then c, then a. If you need to chain tasks, it could soon get confusing. Task metadata and good docs might help but wouldn’t it be much easier to have something like;


            javascript
            
          gulp.task('a', series(['b', 'c']), function () { // do something})

That’s pretty much what you’re getting with gulp@4.0 🎉

The new kids on the block permalink


            javascript
            
          gulp.series()
gulp.parallel()

Rather intuitive. The list parameter gets deprecated 👢

If we look at our first example;


            javascript
            
          gulp.task('a', ['b', 'c'], function () { // do something })

To convert this for gulp@4.0


            javascript
            
          gulp.task('a', gulp.series(gulp.parallel('b', 'c'), function () {
  // do something
}))

If you’re switching to gulp@4.0, and you haven’t already, you’ll likely want to stop using anonymous functions. They print <anonymous> when run and aren’t very useful when viewing task metadata. If you haven’t used task metadata, I recommend it. You can read about it here.

You could change the above to


            javascript
            
          gulp.task('a', gulp.series(gulp.parallel('b', 'c'), function a () {
  // do something
}))

But to make it even better 👍


            javascript
            
          var a = function () { // do some stuff }
gulp.task('a', gulp.series(gulp.parallel(b, c), a))

Or better than that


            javascript
            
          var a = gulp.series(gulp.parallel(b, c), a)
module.exports = { a:a }

Yep that does actually work. You can export functions as tasks. This isn’t specific to gulp@4.0 but if you’re switching why not try out something new? You can see more on exports as tasks here.

I’d switch out the variable a declaration there though. Though it would still work via hoisting.


            javascript
            
          var doStuff = gulp.series(gulp.parallel(b, c), a)
module.exports = { doStuff: doStuff }

Let’s take it a little further. Odds are you are using newer JavaScript syntax via babel etc.


            javascript
            
          const doStuff = gulp.series(gulp.parallel(b, c), a)
export { doStuff }

Or


            javascript
            
          export const doStuff = gulp.series(gulp.parallel(b, c), a)

That’s tidy 😎

If you don’t mind, the rest of the examples will use the newer syntax style 👍

Right, back to gulp@4.0. The new API encourages you to think more about the actual structure of your build tasks. It also advocates smaller comprehensive tasks which provides better flexibility when making changes.

A real example permalink

Let’s consider a real use case.

A common default task is something like develop. This may have once looked like


            javascript
            
          gulp.task('develop', ['serve', 'watch'])

It should be pretty self explanatory what these tasks do;

  • serve — serves up assets on a local static server
  • watch — watches all source and triggers compilation on change

This makes perfect sense to run in parallel


            javascript
            
          const defaultTasks = gulp.parallel(serve, watch)
export default defaultTasks

An example of series in use? It’s likely that serve task will want to compile assets before serving. Something like


            javascript
            
          const compileAssets = gulp.parallel([compileScript, compileStyle])
const startServer = () => { // magic }
const serve = gulp.series(compileAssets, startServer)
export { serve }

And that’s all there is to it! permalink

Migration to gulp@4.0 should be pretty straightforward. The documentation is good and there are plenty of resources out there to help you if you get stuck. I’ve left some links below and an example gist using the new syntax. You can also check out a gulp boilerplate using gulp@4.0 here 👍🤓

As always, any questions or suggestions, please feel free to leave a response or tweet me 🐦!

Some links permalink


            javascript
            
          import gulp from 'gulp'

const compileMarkup = () => { // COMPILE MARKUP }
const compileScript = () => { // COMPILE SCRIPT }
const compileStyle = () => { // COMPILE STYLE }

const watchMarkup = () => { // WATCH MARKUP }
const watchScript = () => { // WATCH SCRIPT }
const watchStyle = () => { // WATCH STYLE }

const compile = gulp.parallel(compileMarkup, compileScript, compileStyle)
compile.description = 'compile all sources'

// Not exposed to CLI
const startServer = () => { // START SERVER }

const serve = gulp.series(compile, startServer)
serve.description = 'serve compiled source on local server at port 3000'

const watch = gulp.parallel(watchMarkup, watchScript, watchStyle)
watch.description = 'watch for changes to all source'

const defaultTasks = gulp.parallel(serve, watch)

export {
  compile,
  compileMarkup,
  compileScript,
  compileStyle,
  serve,
  watch,
  watchMarkup,
  watchScript,
  watchStyle,
}

export default defaultTasks