Gulp Workflow: Looking at Gulp 4

Gulp 4.0, the next version of Gulp, should be released any day now and it will make some parts of the workflow easier to manage.

This section is not a comprehensive guide to Gulp 4 and the changes it brings in. It’s meant to get the file we’ve worked in on previous sections working against Gulp 4 mostly because it allows me to run serial tasks.

Gulp 4.0 is alpha software. It’s still under development and the APIs we discuss here may change without notice. Use the code and examples below at your own risk.

To get started with Gulp 4 we need to take the following
:
Uninstall previous Gulp installation, if any

$ npm uninstall gulp -g
$ cd [your_project_root]
$ npm uninstall gulp

Install Gulp 4 CLI tools globally from the 4.0 GitHub branch.

$ npm install -g git://github.com/gulpjs/gulp-cli.git#4.0

Install Gulp 4 into your project (also from the 4.0 Gihub branch.)

$ npm install --save-dev git://github.com/gulpjs/gulp.git#4.0

Note that we run the installations pointing to a given release of the Github repository. We do this because the authors have not released the code to npm yet and likely they will not do so until the final release.

When the final release happens we’ll be able to just run:

# Installs gulp-cli globally
npm install –g gulp-cli 
# Installs gulp in the project and saves it to dev-dependencies
npm install --save-dev gulp

To pull version 4 into our development environment and specific projects.

CLI Options

Even though these options are available in Gulp 3 I didn’t notice them until I updated my gulpfiles to work with 4.0.

The first flag is --task-simple. It will list all the tasks available in the gulpfile. For my athena shell project it looks like this:

[12:49:40] [email protected] athena-shell 2389$ gulp --tasks-simple
sass:dev
sass:production
scsslint
sassdoc
processCSS
uncss
useref

The second one is --tasks which will list the tasks as above but will also list the dependencies, like shown below.

[12:53:35] Tasks for ~/code/athena-shell/gulpfile.js
'' [12:53:35] ├─┬ processCSS
[12:53:35] │ └─┬ <series>
[12:53:35] │   └── sass:dev
[12:53:35] ├─┬ prep
[12:53:35] │ └─┬ </series><series>
[12:53:35] │   ├── clean
[12:53:35] │   ├─┬ <parallel>
[12:53:35] │   │ ├── copyAssets
[12:53:35] │   │ ├── copyBower
[12:53:35] │   │ └── copyFonts
[12:53:35] │   └── processImages

The difference between Gulps: Handling Dependencies

Gulp 3 (3.9.1 as of this writing), the current version, runs task on maximum concurrency. It’ll launch as many simultaneous tasks as there are task available and they will each run to completion independent of each other. The image below shows the diagram for a task with prerequisites

Gulp 4 introduces additional methods to the API that specify if a group of tasks should run in sequence (gulp.series) or whether tasks should run in parallel (gulp.paralel).

The best aspect of this API is that we can chain series and parallel tasks as deep as we want. We’ll ltake our default task and modify it to work with Gulp 4

The original task looks like this:

// COMBINED TASKS
gulp.task('default', function () {
  runSequence('clean', 
    ['copyAssets', 'copyBower', 'copyFonts'], 
    'processImages');
});

And the updated task, using the new syntax, looks like this:

// COMBINED TASKS
gulp.task('prep',
  gulp.series(
    'clean',
    gulp.parallel('copyAssets', 'copyBower', 'copyFonts'),
    'processImages'
  ));

This is the same change we need to make when assigning prerequisites. If we want our processCSS task to require sass:dev to run and complete before it begins we need to change the task signature to use gulp.series or gulp.parallel to indicate the prerequisites and whether they run in sequence (gulp.series) or parallel (gulp.parallel):

/**
 * Run autoprefixer and cssnano in the css generated by sass The versions of browsers to run autoprefixer against are defined in the variable AUTOPREFIXER_BROWSERS 
 * Requires `sass:dev` to run before this task
*/
gulp.task('processCSS', gulp.series('sass:dev'), () => {
  return gulp.src('app/css/**/*.css')
    .pipe(gulpif(args.list, $.print()))
    .pipe($.autoprefixer(AUTOPREFIXER_BROWSERS))
    .pipe($.sourcemaps.init())
    .pipe($.cssnano({autoprefixer: false}))
    .pipe($.sourcemaps.write('.'))
    .pipe(gulp.dest('dist/css'))
    }));
});

Writing in ES6/2015

I’ve made it a goal for this year to fully learn ES6 and all the cool and nifty APIs that are being released with/for it. One of the advantages of working with Node is that V8, the underlying engine for Node, is updated independently than the browsers. That makes it easier to write using the ES6 features Node/V8 support.

Some examples of those features are the ‘arrow functions’. Instead of defining anonymous functions like we would normally:

function  () {
 //body of the function 
}

We can shorten it to this

() => {
 // body of the function
});

When using gulp there are times when this is not useful. For example when working with Mocha-based tasks it is recommended we do not use arrow functions. Even with those restrictions there’s a lot we can explore using ES6 and Node for our Gulp-based projects