How to Migrate to Gulp.js 4.0

Share this article

How to Migrate to Gulp.js 4.0

Despite competition from webpack and Parcel, Gulp.js remains one of the most popular JavaScript task runners. Gulp.js is configured using code which makes it a versatile, general-purpose option. As well as the usual transpiling, bundling and live reloading, Gulp.js could analyze a database, render a static site, push a Git commit, and post a Slack message with a single command. Learn how to migrate to Gulp.js 4.0.

For an introduction to Gulp, take a look at the following:

Gulp.js 4.0

Gulp.js 3.x has been the default for around half a decade. Until recently, npm install gulp would have installed 3.9.1 — the version referenced in the tutorials above.

Gulp.js 4.0 has been available throughout that time, but had to be explicitly installed with npm install gulp@next. This was partly owing to ongoing development and because Gulp.js 4 gulpfile.js configuration files are not compatible with those developed for version 3.

On December 10, 2018, Gulp.js 4.0 was announced as the default and published to npm. Anyone using npm install gulp on a new project will receive version 4.

Is it Necessary to Migrate to Gulp.js 4?

No. Gulp.js 3 has been deprecated and is unlikely to receive further updates, but it can still be used. Existing projects won’t update unless the version is explicitly changed in the dependencies section of package.json. For example:

"dependencies": {
  "gulp": "^4.0.0"
}

You an also install Gulp.js 3 in new projects using:

npm install gulp@^3.9.1

It’s possibly best to stick with Gulp.js 3.x if you have a particularly complex, mission-critical build system.

However, existing Gulp.js plugins should be compatible and most gulpfile.js configurations can be migrated in an hour or two. There are several benefits to upgrading, which will become apparent throughout this tutorial.

Upgrade to Gulp.js 4.0

Update your package.json dependencies as shown above, then run npm install to upgrade. You can also update the command-line interface using npm i gulp-cli -g, although this hasn’t changed at the time of writing.

To check the installation, enter gulp -v at the command line:

$ gulp -v
[15:15:04] CLI version 2.0.1
[15:15:04] Local version 4.0.0

Migrating gulpfile.js

Running any task is now likely to raise scary-looking errors. For example:

AssertionError [ERR_ASSERTION]: Task function must be specified
  at Gulp.set [as _setTask] (/node_modules/undertaker/lib/set-task.js:10:3)
  at Gulp.task (/node_modules/undertaker/lib/task.js:13:8)
  at /gulpfile.js:102:8
  at Object.<anonymous> (/gulpfile.js:146:3)
  at Module._compile (internal/modules/cjs/loader.js:688:30)
  at Object.Module._extensions..js (internal/modules/cjs/loader.js:699:10)
  at Module.load (internal/modules/cjs/loader.js:598:32)
  at tryModuleLoad (internal/modules/cjs/loader.js:537:12)
  at Function.Module._load (internal/modules/cjs/loader.js:529:3)
  at Module.require (internal/modules/cjs/loader.js:636:17)
  at require (internal/modules/cjs/helpers.js:20:18)
  at execute (/gulp-cli/lib/versioned/^4.0.0/index.js:36:18)
  at Liftoff.handleArguments (/gulp-cli/index.js:175:63)
  at Liftoff.execute (/gulp-cli/node_modules/liftoff/index.js:203:12)
  at module.exports (/gulp-cli/node_modules/flagged-respawn/index.js:51:3)
  at Liftoff.<anonymous> (/gulp-cli/node_modules/liftoff/index.js:195:5)

It’s daunting, but you can ignore everything except the first reference of gulpfile.js, which shows the line where an error was encountered (102 in this example).

Fortunately, most of these errors are caused by the same type of problem. The following sections use the CSS tasks tutorial code as an example. The code is available on GitHub and provides the original Gulp.js 3 gulpfile.js and the migrated Gulp.js 4 equivalent.

Convert Task Arrays to series() Calls

Gulp.js 3 allowed arrays of synchronous tasks to be specified. This was typically used when a watch event was triggered or a task had dependencies. For example, run the images task before the css task:

gulp.task('css', ['images'], () =>

  gulp.src(cssConfig.src)
    // .other plugins
    .pipe(gulp.dest(cssConfig.build));

);

Gulp.js 4.0 introduces the series() and parallel() methods to combine tasks:

  • series(...) runs tasks one at a time in the order specified, and
  • parallel(...) runs tasks simultaneously in any order.

Complex tasks can be nested to any level — something which would have been difficult to achieve in Gulp.js 3. For example, run tasks a and b in parallel then, once both are complete, run tasks c and d in parallel:

gulp.series( gulp.parallel(a, b), gulp.parallel(c, d) )

The css task above can be migrated to Gulp.js 4 by changing the array to a series() method call:

gulp.task('css', gulp.series('images', () =>

  gulp.src(cssConfig.src)
    // .other plugins
    .pipe(gulp.dest(cssConfig.build));

)); // remember the extra closing bracket!

Async Completion

Gulp.js 3 permitted synchronous functions but these could introduce errors which were difficult to debug. Consider tasks which don’t return the gulp streamed value. For example, a clean task to delete the build folder:

const
  gulp = require('gulp'),
  del = require('del'),
  dir = {
    src         : 'src/',
    build       : 'build/'
  };

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

  del([ dir.build ]);

});

Gulp.js 4.0 throws a warning because it needs to know when a task has completed in order to manage series() and parallel() sequences:

[15:57:27] Using gulpfile gulpfile.js
[15:57:27] Starting 'clean'...
[15:57:27] The following tasks did not complete: clean
[15:57:27] Did you forget to signal async completion?

To solve this, Gulp.js 4 will accept a returned Promise (which is supported by the del package):

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

  return del([ dir.build ]);

});

// or use the simpler implicit return:
// gulp.task('clean', () => del([ dir.build ]) );

Alternatively, pass a callback function which is executed on completion (del also provides a synchronous sync() method):

gulp.task('clean', (done) => {

  del.sync([ dir.build ]);
  done();

});

Here’s a more complex Gulp.js 3 example with watch tasks:

gulp.task('default', ['css', 'server'], () => {

  // image changes
  gulp.watch(imgConfig.src, ['images']);

  // CSS changes
  gulp.watch(cssConfig.watch, ['css']);

});

These can be migrated to Gulp.js 4 series() methods and a done() callback:

gulp.task('default', gulp.series('css', 'server', (done) => {

  // image changes
  gulp.watch(imgConfig.src, gulp.series('images'));

  // CSS changes
  gulp.watch(cssConfig.watch, gulp.series('css'));

  done();

}));

Bonus Tip: Convert Task Methods to ES6 Modules

Most gulpfile.js configurations will work in Gulp.js 4.0 once task arrays are converted to series() calls and asynchronous functions signal completion.

Although the task() definition method is still supported, the newer ES6 module exports pattern offers several benefits:

  1. Private tasks can be defined which can be called within gulpfile.js but not from the gulp command.
  2. Functions can be passed by reference rather than a string name so syntax errors can be highlighted by editors.
  3. The same function can be referenced using any number of task names.
  4. It’s easier to define complex dependencies in series() and/or parallel().

Take the following Gulp.js 3 images and css tasks:

gulp.task('images', () =>

  gulp.src(imgConfig.src)
    // .other plugins
    .pipe(gulp.dest(imgConfig.build))

);

gulp.task('css', ['images'], () =>

  gulp.src(cssConfig.src)
    // .other plugins
    .pipe(gulp.dest(cssConfig.build))

);

These could be converted to use the Gulp.js 4 module pattern:

function images() {

  return gulp.src(imgConfig.src)
    // .other plugins
    .pipe(gulp.dest(imgConfig.build));

}
exports.images = images;
exports.pics = images;


function css() {

  return gulp.src(cssConfig.src)
    // .other plugins
    .pipe(gulp.dest(cssConfig.build));

}
exports.css = gulp.series(images, css);
exports.styles = exports.css;

Note: return statements must be added because the ES6 arrow => functions with an implicit return have been changed to standard function definitions.

In this Gulp.js 4 example:

  • either gulp images or gulp pics can be used to run the images() task
  • either gulp css or gulp styles will run images() followed by css().

Set exports.default to define a default task run when gulp is executed from the command line without a specific task.

Gulp Goodness

The CSS tasks example, which optimizes images, compiles Sass, minifies CSS, and live-reloads on changes, took less than one hour to convert. Examine the code on GitHub to see:

It’s taken a while to (properly) arrive, but Gulp.js 4 provides opportunities for defining tasks which would have been impractical in version 3. Updating software can seem like a waste of development effort, but you’ll be rewarded with a faster, more robust set of tasks, which will save time in the long run.

Frequently Asked Questions (FAQs) about Migrating to Gulp 4

What are the major changes in Gulp 4 compared to Gulp 3?

Gulp 4 introduces several significant changes compared to Gulp 3. The most notable change is the new task execution system. In Gulp 3, tasks were run in parallel by default, but in Gulp 4, tasks run in series. This allows for better control over task execution order. Another major change is the introduction of the gulp.series() and gulp.parallel() methods, which allow you to explicitly define the execution order of tasks. Gulp 4 also introduces a new way to watch files and directories for changes, using the gulp.watch() method.

How do I update my Gulp 3 code to Gulp 4?

Updating your Gulp 3 code to Gulp 4 involves several steps. First, you need to replace the old task dependencies syntax with the new gulp.series() and gulp.parallel() methods. Second, you need to replace the old gulp.watch() syntax with the new one. Finally, you need to update your package.json file to use the latest version of Gulp.

What is the purpose of gulp.series() and gulp.parallel() in Gulp 4?

The gulp.series() and gulp.parallel() methods in Gulp 4 are used to define the execution order of tasks. gulp.series() runs tasks in series, one after the other, while gulp.parallel() runs tasks in parallel, all at the same time. These methods provide more control over task execution order compared to Gulp 3.

How do I use the new gulp.watch() method in Gulp 4?

The new gulp.watch() method in Gulp 4 is used to watch files and directories for changes. It takes two arguments: the path to the files or directories to watch, and the tasks to run when a change is detected. The tasks can be defined using gulp.series() or gulp.parallel().

Why am I getting errors when trying to run my Gulp tasks after updating to Gulp 4?

If you’re getting errors when trying to run your Gulp tasks after updating to Gulp 4, it’s likely because your code is still using the old Gulp 3 syntax. You need to update your code to use the new Gulp 4 syntax, including the new task execution system and the new gulp.watch() method.

How do I define default tasks in Gulp 4?

In Gulp 4, default tasks are defined using the gulp.task() method with ‘default’ as the task name. The second argument to gulp.task() is the tasks to run when the default task is called. These tasks can be defined using gulp.series() or gulp.parallel().

Can I still use Gulp plugins with Gulp 4?

Yes, you can still use Gulp plugins with Gulp 4. However, some plugins may not be compatible with the new version and may need to be updated or replaced.

How do I handle asynchronous tasks in Gulp 4?

In Gulp 4, asynchronous tasks can be handled in several ways. You can use the done callback, return a stream, return a promise, or use an async function. The method you choose depends on the specific requirements of your task.

Can I run tasks in a specific order in Gulp 4?

Yes, you can run tasks in a specific order in Gulp 4 using the gulp.series() and gulp.parallel() methods. gulp.series() runs tasks in series, one after the other, while gulp.parallel() runs tasks in parallel, all at the same time.

How do I install Gulp 4?

To install Gulp 4, you need to run the following command in your terminal: npm install gulp@4.0.0. This will install the latest version of Gulp. You also need to update your package.json file to use the latest version of Gulp.

Craig BucklerCraig Buckler
View Author

Craig is a freelance UK web consultant who built his first page for IE2.0 in 1995. Since that time he's been advocating standards, accessibility, and best-practice HTML5 techniques. He's created enterprise specifications, websites and online applications for companies and organisations including the UK Parliament, the European Parliament, the Department of Energy & Climate Change, Microsoft, and more. He's written more than 1,000 articles for SitePoint and you can find him @craigbuckler.

automationbuild systemsGulpGulp.jswebpack
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week