Cover

Upgrading from Gulp 3 to 4

October 28, 2019
No Comments.

I may be very late to the party, but once Gulp 3.x stopped working with recent versions of Node, I’ve been forced to update my projects to the newest version of Gulp.

I was hesitant to learn it as I often think of Gulp as just a side-line tool that I use for production. Luckily for me, the new Gulp is actually simpler and more intuitive. I wanted to write a quick blog post explaining how I converted them.

Let’s start with my Gulp 3 version:

// I've simplified this for the blog
// Full version available: 
// https://shawnw.me/31UXsr1

var gulp = require('gulp');
var uglify = require('gulp-uglify');
var concat = require('gulp-concat');
var rimraf = require("rimraf");
var merge = require('merge-stream'); 

gulp.task("minify", function () {

  var streams = [
    gulp.src(["wwwroot/js/*.js", '!wwwroot/js/tour*.js', '!wwwroot/js/contact.js'])
      .pipe(uglify())
      .pipe(concat("wilderblog.min.js"))
      .pipe(gulp.dest("wwwroot/lib/site")),
    gulp.src(["wwwroot/js/contact.js"])
      .pipe(uglify())
      .pipe(concat("contact.min.js"))
      .pipe(gulp.dest("wwwroot/lib/site"))
  ];

  return merge(streams);
});


gulp.task("clean", function (cb) {
  return rimraf("wwwroot/lib/", cb);
});

gulp.task("default", gulp.series('clean', 'minify'));

The Gulp 3 version uses a gulp object is key to the different code. The addons are separate objects too in the pipes. When converting these there were several steps. First, I upgraded the gulp dependency to:

...
  "devDependencies": {
    "gulp": "4.0.2",
    "gulp-uglify": "3.0.2",
    "gulp-concat": "2.6.1",
    "rimraf": "3.0.0",
    "merge2": "1.3.0"
  }
...

Then I switched all the gulp.task references into to named functions which is much easier to read:

minify() {
   //...
}

clean(cb) {
  // ...
}

Next, I noticed that I didn’t need the gulp object any longer. Instead I just got the parts of Gulp that i needed:

const { src, dest, series } = require('gulp');
const uglify = require('gulp-uglify');
const concat = require('gulp-concat');
const rimraf = require("rimraf");
const merge = require('merge-stream'); 

Notice the use of const to represent the unchanging objects (I did this for all the addins too). Then I destructured the gulp dependency into src, dest and series (the three parts of Gulp i’m using). I switched theThat makes it easy to just remove ‘gulp.’ in most of the code:

function minify() {
  var contact = src(["wwwroot/js/contact.js"])
    .pipe(uglify())
    .pipe(concat("contact.min.js"))
    .pipe(dest("wwwroot/lib/site"));

  var site = src(["wwwroot/js/*.js", '!wwwroot/js/tour*.js', '!wwwroot/js/contact.js'])
    .pipe(uglify())
    .pipe(concat("wilderblog.min.js"))
    .pipe(dest("wwwroot/lib/site"));

  return merge(site, contact);
}

Notice that this code is effective the same since the names of the destructured objects are the same as the props on the gulp object. The addons are still the same. For merging of the two streams, I still need to merge them (though I had to upgrade to merge2 instead of gulp-merge):

  "devDependencies": {
    "gulp": "4.0.2",
    "gulp-uglify": "3.0.2",
    "gulp-concat": "2.6.1",
    "rimraf": "3.0.0",
    "merge2": "1.3.0"
  }

With my ‘tasks’ defined, I could then export the different actions in a much more ECMAScript 6 way:

exports.minify = minify;
exports.clean = clean;
exports.default = series(clean, minify);

Notice that each task is now just a named export and that the default is using series to tell gulp how I want to execute the tasks. You could also import parallel if you have tasks that you’d rather run in parallel (versus in series like I’m doing).

You can see the before and after comparison here:

Before
After

Let me know what you think?