Gulp is a streaming build system, and 4.0 is the next major release of Gulp. Here is an upgrade guide for your reference.

Motivation

  • If you are using node 7 or later, you have to use gulp 4.

    Gulp <4.0 depends on old version of graceful-fs (<3.0.0) which is incompatible with node >=7.0.

    npm WARN deprecated [email protected]: graceful-fs v3.0.0 and before will fail on node releases >= v7.0. Please update to graceful-fs@^4.0.0 as soon as possible. Use 'npm ls graceful-fs' to find it in the tree.

    Thus if you are going to work with node >=7.0, you have to upgrade your installation of gulp to 4.0.

Upgrade the Installation

  1. Remove the old version of gulp if installed globally

    npm rm --global gulp
    rm /usr/share/man/man1/gulp.1
    
  2. Install/Update gulp-cli to the latest version globally

    sudo npm install --global gulp-cli
    

    Note: If you run into following errors when installing gulp-cli, don't forget to run rm /usr/share/man/man1/gulp.1, and then try again.

    /usr/bin/gulp -> /usr/lib/node_modules/gulp-cli/bin/gulp.js
    npm ERR! Linux 3.4.0+
    npm ERR! argv "/usr/bin/nodejs" "/usr/bin/npm" "install" "-g" "gulp-cli"
    npm ERR! node v7.2.0
    npm ERR! npm  v3.10.9
    npm ERR! path /usr/share/man/man1/gulp.1
    npm ERR! code EEXIST
    	
    npm ERR! Refusing to delete /usr/share/man/man1/gulp.1: ../../../lib/node_modules/gulp/gulp.1 symlink target is not controlled by npm /usr
    npm ERR! File exists: /usr/share/man/man1/gulp.1
    npm ERR! Move it away, and try again.
    	
    npm ERR! Please include the following file with any support request:
    npm ERR!     /home/zzz.buzz/npm-debug.log
    

    Note: Installing the latest version of gulp-cli is required, or you may run into the following error:

    [19:56:57] Using gulpfile ~/zzz.buzz/gulpfile.js
    /usr/lib/node_modules/gulp/bin/gulp.js:129
        gulpInst.start.apply(gulpInst, toRun);
                      ^
    	
    TypeError: Cannot read property 'apply' of undefined
        at /usr/lib/node_modules/gulp/bin/gulp.js:129:19
        at _combinedTickCallback (internal/process/next_tick.js:67:7)
        at process._tickCallback (internal/process/next_tick.js:98:9)
        at Module.runMain (module.js:607:11)
        at run (bootstrap_node.js:420:7)
        at startup (bootstrap_node.js:139:9)
        at bootstrap_node.js:535:3
    
  3. Uninstall the old version of gulp in project directory

    npm rm gulp --save-dev
    
  4. Install the 4.0 version of gulp

    // Use https protocol
    npm install --save-dev https://github.com/gulpjs/gulp#4.0
    // or use git protocol
    npm install --save-dev gulpjs/gulp#4.0
    

That's it. Check your installation with this:

$ gulp -v
[01:06:42] CLI version 1.2.2
[01:06:42] Local version 4.0.0-alpha.2

Upgrade gulpfile.js

Gulp 4.0 introduces many incompatible API changes. (That's what a major release implies anyway.)

To fix them, just run gulp tasks, and follow the error messages.

Here are some common errors and corresponding solutions:

  • AssertionError: Task function must be specified

    This is caused by API change in gulp.task from gulp.task(name [, deps] [, fn]) to gulp.task([name,] fn).

    If you were writing

    gulp.task('alias', ['mytask']);
    gulp.task('zzz', ['dep1'], function() { ... });
    gulp.task('buzz', ['dep1', 'dep2'], function() { ... });
    gulp.task('zzzbuzz', ['dep1', 'dep2', 'dep3']);
    

    Change them to the following respectively

    gulp.task('alias', gulp.task('mytask'));
    gulp.task('zzz', gulp.series('dep1', function() { ... }));
    gulp.task('buzz', gulp.series(gulp.parallel('dep1', 'dep2'), function() { ... }));
    gulp.task('zzzbuzz', gulp.parallel('dep1', 'dep2', 'dep3'));
    

    See gulp/API.md at v3.9.1 · gulpjs/gulp vs. gulp/API.md at v4.0.0 · gulpjs/gulp.

  • Error: watching …: watch task has to be a function (optionally generated by using gulp.parallel or gulp.series)

    This is caused by API change in gulp.watch from gulp.watch(glob [, opts], tasks) or gulp.watch(glob [, opts, cb]) to gulp.watch(globs[, opts][, fn]).

    The solution to this is much the same as the previous one, and is also said in the error message.

    e.g. Change

    gulp.watch('*.js', ['taskzzz']);
    

    to

    gulp.watch('*.js', gulp.task('taskzzz'));
    // or
    gulp.watch('*.js', gulp.series('taskzzz'));
    // or
    gulp.watch('*.js', gulp.parallel('taskzzz'));
    

    See gulp/API.md at v3.9.1 · gulpjs/gulp vs. gulp/API.md at 4.0 · gulpjs/gulp.

  • AssertionError: Task never defined: …

    Gulp 4.0 requires that task should already be registered when using task names.

    If you were defining the broadest/alias tasks before defining component tasks

    gulp.task('t', ['mytask']);
    gulp.task('task', gulp.series('mytask'));
    gulp.task('mytask', function() { ... });
    

    Then you need to put the component tasks first.

    gulp.task('mytask', function() { ... });
    gulp.task('t', gulp.series('mytask'));
    gulp.task('task', gulp.series('mytask'));
    

    And if you were using requireDir, make sure that tasks imported via requireDir do not depend on each other, or tasks with dependencies are imported in proper order.

  • TypeError: gulp.hasTask is not a function

    If you were using run-sequence or other plugins that depend on gulp.hasTask, they won't work for Gulp 4.0, as this API is removed in favor of gulp.series and gulp.parallel.

    e.g. Change this

    gulp.task('build', function(cb) {
      runSequence(
        'jekyll-build',
        'modernizr',
        [
          'minify',
          'autoprefixer'
        ],
        'serve',
        cb);
    });
    

    to

    gulp.task('build', gulp.series(
        'jekyll-build',
        'modernizr',
        gulp.parallel(
          'minify',
          'autoprefixer'
        ),
        'serve'));
    

There are also some other changes which may or may not break your existing code without throwing an error.

For example, the underlying watching library used by gulp.watch has been switched from gaze to chokidar, which may or may not cause incompatibility for your gulpfile. Though this did cause problems for me.

In gulp before 4.0, I was watching on some css files, auto-prefixing properties on file changes, and writing back to their original location. It worked like a charm, but in gulp 4.0 with chokidar, this causes infinite recursive calls. If you run into this as well, a staging area may be employed to overcome this.

References