How do I update to Gulp 4?

Gulp is a fantastic build tool for compiling your SCSS, Less and SVG sprites that we use at Liquid Light.

For a while now, the gulpJS team have been working on Version 4. This version features some nice additions to the build tool but does also feature some substantial breaking changes. Upgrading is simple, but does require a few tweaks.

Upgrading gulp to v4

The good news is you can upgrade and play with v4 for a particular project without having to change all of your gulp files. This is ideal if you want to see what gulp v4 means for your and your workflow before taking the big plunge.

Note: You do need to upgrade the global package to use v4, but v3 will still work for each local project where needed.

Installing gulp 4 globally

You will need to remove your current gulp global package before installing v4 in order to do an upgrade.

Note: The $ shows the command is to be run on the command line and shouldn’t be typed

$ npm rm -g gulp
$ npm install -g gulp-cli

This command removes your current global package and installs v4 from the gulp-cli 4.0 branch.

Make sure you don't get any errors from the first command before you type the second. Depending on your set-up, you may need to run them with sudo.

To verify what version you have installed globally, you can run the below command (and should see a similar output)

$ gulp -v
CLI version 1.2.1

<p>If you are in a gulp project, a local version will be listed below the <code>CLI version</code></p> <h3>Install gulp 4 locally</h3> <p>Once globally installed, gulp v4 will then need to be installed on a per-project basis.</p> <pre class="language-bash">$ npm uninstall gulp --save-dev

$ npm install 'gulpjs/gulp.git#4.0' --save-dev</pre> <p>Following a similar technique to that of the global package, uninstall the local version, then install the upgrade. </p> <p>If in your <code>package.json</code> file gulp is listed under <code>dependencies</code>, then replace the <code>--save-dev</code> with just <code>--save</code>.</p> <p>You should now have gulp v4 installed and ready to go. This can be verified by running the version command above</p> <p>Running <code>gulp -v</code> once again should now give you</p> <pre class="language-bash">$ gulp -v

CLI version 1.2.1

Local version 4.0.0-alpha.2</pre> <h2>Updating your gulpfile</h2> <p>Now you have v4 successfully installed, you’ll need to do a few updates to your gulpfile.js. The best thing to do is run <code>gulp</code> and follow the errors that you get.</p> <p>When you get an error, you will be faced with several lines of what appears to be jargon.</p> <p>The first thing you need to look for is the error message. This will be something like</p> <pre class="language-bash">Error: Error message here</pre> <p>Make a note of that. The second line to look for is the one that includes the path to your gulpfile with some numbers afterwards. This is what mine looks like:</p> <pre class="language-bash">at Object.<anonymous> /Sites/gulp-v4/gulpfile.js:418:6</pre> <p>This tells you the error was generated in your gulpfile at line <strong>418</strong>, character <strong>6</strong>.</p> <p>I’ve tested below some errors I came across during the update and how to fix them.</p> <h3>AssertionError: Task function must be specified</h3> <p>This error for me was thrown because of:</p> <pre class="language-js">gulp.task('default', ['del'], function() {

// default task code here

});</pre> <p>Where the <code>del</code> task is being run before the <code>default</code> task.</p> <p>To resolve this, you need to specify that the <code>del</code> and following function are to be run in a <code>series</code>.</p> <p>To resolve this, change the code to:</p> <pre class="language-js">gulp.task('default', gulp.series('del', function() {

// default task code here

}));</pre> <p><em><strong>Note:</strong> because you are opening a parenthesis for <code>gulp.series</code>, don’t forget to add an extra closing one after the function.</em></p> <p>Make sure you update the rest of your gulpfile to follow suit.</p> <p>The gulp has updated this syntax for running tasks in series to add the functionality of running tasks in parallel with <code>gulp.parallel</code>. More can be read about it <a href="https://github.com/gulpjs/gulp/blob/4.0/docs/API.md#gulpparalleltasks">in the gulp docs</a>.</p> <h3>Did you forget to signal async completion?</h3> <pre class="language-bash">The following tasks did not complete: default, del

Did you forget to signal async completion?</pre> <p>This error occurred on an anonymous function (the one occurring after <code>del</code> in the example above).</p> <p>Gulp v4 requires a stream, promise, event emitter, child process or observable to be returned from a function or task. This was resolved in the simplest case of passing a parameter into the function and firing it after the task is completed.</p> <p>E.g.</p> <pre class="language-js">gulp.task('default', gulp.series(function(done) {

// task code here

done();

}));</pre> <p>(Note the <code>done</code> in-between the parenthesis when the function opens and then it firing at the end).</p> <p>I specifically got this error when trying to run the <code>del</code> <a href="https://www.npmjs.com/package/del">npm package</a>.</p> <p>My <code>del</code> package was set to call <code>del.sync</code> which returns an array, Gulp requires one of the stream, promise, event emitter, child process or observable to be returned, which <code>del</code> does by default.</p> <pre class="language-js">return del(dirs);</pre> <h3>Gulp watcher with change event and paths</h3> <p>With gulp v3, the watcher would return the path of the modified file within the function it called.</p> <p>For example, the output for the below would be an object with the location of the file modified and event (e.g. <code>changed</code>).</p> <pre class="language-js">gulp.task('watch', function(){

gulp.watch('path/to/css/*.css').on('change', function(event) {

console.log(event.path);

console.log(event.type);

// code to execute

});

});</pre> <p>With gulp 4, this doesn't seem to be the case. Instead, the watcher can fire some standard functions, but if you need filename based operations, these need to be moved to the <code>changed</code> function.</p> <pre class="language-js">gulp.task('watch', function(){

gulp.watch('path/to/css/*.css')

.on('change', function(path, stats) {

console.log(path);

// code to execute on change

})

.on('unlink', , function(path, stats) {

console.log(path);

// code to execute on delete

});

});</pre> <p>If you did need to fire a generic function when a file is changed while being watched, the <a href="https://github.com/gulpjs/gulp/blob/4.0/docs/API.md#gulpwatchglob-opts-fn">gulp tutorials</a> have an example of this.</p> <h2>It's not that hard</h2> <p>It's not that difficult to update your gulp workflow to use version 4. Just remember - if you are sharing the project with other developers that they would need to upgrade to gulp v4 as well.</p> <p>If you have encountered any other errors, then feel free to drop a comment below or <a href="https://twitter.com/liquidlightuk">tweet us</a> - we'd be more than happy to help and include the solution above for others!</p>

You might also enjoy

Mike Street

Written by Mike Street

Mike is a front-end developer from Brighton, UK. He spends his time writing, cycling and coding. You can find Mike on Twitter.