Upgrading to Gulp 4

Over a year ago (how time flies!) I was working on a series of blog posts about my new development process with Git and Gulp – the most recent post being about optimising images the easy way.

Whilst this most recent post was written a whopping 14 months ago, I did have a lot of other posts in draft mode.  Having recently been working with this workflow again, it’s made me hungry to bring them out of draft form, and publish a few more of them.

Before I get back to more Gulp plugins that I find useful in my workflow, it’s important to tackle the big issue, Gulp 4 has been released! My previous posts were written using Gulp 3, and there are some important changes.

First things first, you need to go to your project and upgrade the local version of Gulp…

npm install --save-dev [email protected]

This will upgrade you to v4.  Running the "gulp" command now will almost certainly throw a number of errors, which we'll sort out next.

The main thing before was that all prerequisite tasks ran in parallel, and in order for them to run one after the other (in series) you had to chain them together, each task with one prerequisite, which was really messy.  In Gulp 4, you can now define "series" and "parallel" specifically, making it much easier and stopping all the spaghetti code.

Another is that anonymous functions, which is now I built all my tasks previously, are not very helpful anymore in the way that they are handled.  For this reason, I've changed to using named functions, and then exporting just the sequences which I find useful.

Let me give you an example of a previous task...

gulp.task("default",["root","js","css","img"]);

gulp.task("root",function(cb) {
  pump([
    gulp.src("index.htm"),
    htmlmin({collapseWhitespace:true,removeComments:true}),
    gulp.dest("build")
  ]);
});

gulp.task("js",function(cb) {
  pump([
    gulp.src(["js/optimisation.js","js/debug.js"]),
    maps.init(),
    concat("script.js"),
    uglify(),
    optimize(),
    maps.write("../maps"),
    gulp.dest("build/js")
  ]);
});

gulp.task("css",function(cb) {
  pump([
    gulp.src(["css/*.css"]),
    maps.init(),
    concat("style.css"),
    cleancss({level:{1:{specialComments:0},2:{removeDuplicateRules:true}}}),
    maps.write("../maps"),
    gulp.dest("build/css")
  ]);
});

gulp.task("img",function(cb) {
  pump([
    gulp.src(["img/*.png","img/*.jpg","img/*.gif","img/*.svg"]),
    newer("build/img"),
    imagemin(),
    gulp.dest("build/img")
  ]);
});

Now if that's way too much code all at once and you're not sure what I'm talking about, ignore the contents of each function.  The point to fold on to is the fact that each function is anonymous.

Let's take the last task, "img", and rewrite it...

var img = function() {
  return gulp.src(["img/*.png","img/*.jpg","img/*.gif","img/*.svg"])
    .pipe(newer("build/img"))
    .pipe(imagemin())
    .pipe(gulp.dest("build/img"));
};

The key differences are...

  1. I've declared the function and called it "img"
  2. I'm returning the results - this is to signal async completion
  3. I'm no longer using pump - I've found I don't really need it v4
  4. This is just a function, it's not actually a "task" right now

Other than that, the coding is pretty much the same, the tasks themselves largely don't need to change, it's just the way that they're put together that does.

Now, to declare the "final" task...

exports.final = gulp.parallel(root,js,css,img);

You can now export your task, which isn't unique to v4 but is certainly the best way to do it now, and then declare in this case that all 4 tasks (all of which need to be rewritten and declared like "img" above) can run in parallel.

If you needed "root" to run first, you could do something more like this...

exports.final = gulp.series(root,gulp.parallel(js,css,img));

You can nest as many "series" and "parallel" calls as you like, to make it as complex as required.  The great thing here is that the building blocks (the individual functions) are all put together here at the point of export, meaning that you can chain them together in different ways for different tasks, which you couldn't do before without creating duplicates.

This certainly isn't an exhaustive guide, maybe I'll put a course together on it soon, but it covers the main points that got me from v3 to v4.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.