Three Ways Gulp Can Help Improve Your Site’s Performance

GulpLast year, I wrote a quick introduction to the Gulp JavaScript (Node) task runner. Today, I’d like to delve a little deeper with a practical example that demonstrates the power of Gulp to both streamline front-end development workflows and make a practical difference to the quality of developers’ work.

Gulp is a task runner. Essentially, it takes a set of files, runs them through any number of filters (called pipes in Gulp-speak) that make changes, and outputs another set of files. That doesn’t sound super interesting; the average dev server is full of command-line applications that do the same thing (as do static site generators). What makes Gulp so useful is that anyone with a modicum of JavaScript knowledge can quickly string together a ready-made set of pipes to perform transformations on files that would otherwise be time-consuming and error prone.

As a quick example: SASS is a popular CSS preprocessor that makes CSS more pleasant to write and maintain. But every time SASS files are changed, the preprocessor has to convert the SASS into CSS that browsers understand. It’s a cycle that can quickly become frustrating: edit, save, preprocess, reload the browser. Gulp can do two things to make this easier (three, but I’m not going to focus on LiveReload here). It can watch the SASS files to see if there are any changes, and it can then take the SASS files, run them through the preprocessor, and put the resulting CSS in the right place.

Gulp requires Node.js. Installing and configuring Node is beyond the scope of this article, but if you already have a functioning Node.js environment on your server or development machine, you can install Gulp and the Node / Gulp modules we’ll talk about with npm (the Node Package Manager):

npm install --save-dev gulp

Gulp is configured with gulpfile.js. The Gulpfile for our example task looks like this:

var gulp = require('gulp');
var sass = require('gulp-sass');
var watch = require('gulp-watch');

gulp.task('process_sass', function () {
gulp.src('./sass/*/.scss')
.pipe(sass())
.pipe(gulp.dest('./css'));
});

gulp.task('watch', function () {
gulp.watch('./sass/*/.scss', ['process_sass']);
});

Even if you aren’t a JS ninja, this should be fairly easy to understand. The first three lines say that we want to use gulp with the “gulp-sass” and “gulp-watch” modules.

Next, we create a task called “process_sass” and use gulp.src to say which files to work on. Files that match will be sent into the pipe. The next line is where the work happens. We pipe the files through the SASS preprocessor, and with the last line, put them into the destination file.

The watch task follows a similar pattern, but in this case it does nothing but watch the SASS directory and run the sass_process task when anything changes.

In this way, we can make changes to our SASS and have them automatically processed into CSS.

To run this task, you’d enter:

gulp watch

This is a fairly trivial example of what Gulp can do. There are thousands of Gulp modules that cover a huge range of web development tasks. In the rest of this article I’ll focus on three common performance optimization tasks. I’m going to concentrate on CSS here, but there are Gulp modules that will optimize JavaScript and HTML for performance too.

Concatenate

Because requests to the server are expensive, ideally we’d like to make as few of them as possible. The best way to do this is to have a single CSS file: one request, one download. But most websites have several – if not dozens – of CSS files. Gulp can handle concatenating the files, and, even better, because of its pipe architecture, it can take the output of the previous SASS task and concatenate that.

Our new gulpfile would like this:

var gulp = require('gulp');
var watch = require('watch');
var sass = require('gulp-sass');
var concat = require('gulp-concat');

gulp.task('sass', function () {
gulp.src('./sass/*/.scss')
.pipe(sass())
.pipe(concat('allthestyles.css'))
.pipe(gulp.dest('./css'));
});

gulp.task('watch', function () {
gulp.watch('./sass/*/.scss', ['sass']);
});

One new module and a new pipe added to the sass task is all it takes. After we process the SASS into CSS, we send it through the “concat” pipe. When it comes out, instead of being multiple files, it’s one big file with a new name.

Minify

Minification reduces the size of a file by removing unnecessary whitespace, stripping out comments, and so on.

This time we’ll use the “gulp-minify-css” module, and our gulpfile will look like this:

var gulp = require('gulp');
var watch = require('gulp-watch');
var sass = require('gulp-sass');
var concat = require('gulp-concat');
var minifyCss = require('gulp-minify-css');

gulp.task('process_sass', function () {
gulp.src('./sass/*/.scss')
.pipe(sass())
.pipe(concat('allthestyles.css'))
.pipe(minifyCss())
.pipe(gulp.dest('./css'));
});

gulp.task('watch', function () {
gulp.watch('./sass/*/.scss', ['process_sass']);
});

I’m sure you can see the pattern here, so I won’t belabor the obvious. We add a new module to the list at the top and a new pipe that sends our concatenated file through the minifier.

Create Responsive Images

For the final example, I’m going to move away from CSS and take a look at another task that plagues web designers: creating a range of image sizes for use on a responsive page – this also works for creating thumbnails and any other scenario where you need to resize images.

The workflow we’re going to use goes like this: upload a large image to a source folder watched by Gulp, then run a Gulp task that resizes it to create a smaller 750px width image and then optimizes the image. We optimize the image – strip metadata and so on – after resizing because the resizing phase can bloat images even if the original image was optimized with a tool like ImageOptim.

For this to work, you’re going to need to have either ImageMagick or GraphicsMagick installed on your dev machine. If you don’t already know, these are powerful command-line image editors that will do the actual resizing.

You’re also going to need the Gulp modules “gulp-image-resize” and “gulp-imagemin”, along with the node module “imagemin-jpegtran” (assuming you’re optimizing JPEGs).

The gulpfile will now look like this:

var gulp = require('gulp');
var watch = require('gulp-watch');
var sass = require('gulp-sass');
var concat = require('gulp-concat');
var concat = require('gulp-minify-css')
var imagemin = require('gulp-imagemin');
var jpegtran = require('imagemin-jpegtran');
var imageResize = require('gulp-image-resize');

gulp.task('sass', function () {
gulp.src('./sass/*/.scss')
.pipe(sass())
.pipe(concat('allthestyles.css'))
.pipe(minifyCss())
.pipe(gulp.dest('./css'));
});
gulp.task('small-image', function(){
return gulp.src('imagesource/*.jpg')
.pipe(imageResize({
width : 750
}))
.pipe(imagemin({
progressive: true,
use: [jpegtran()]
}))
.pipe(rename({suffix: '-small'}))
.pipe(gulp.dest('images/'))
})

gulp.task('watch', function () {
gulp.watch('./sass/*/.scss', ['sass']);
gulp.watch('./imagesource', ['small-image']);
});

This one is a little more complex than the previous examples, but the process is basically the same. We have created a new task that takes image files from our image source folder, runs them through the image resizing pipe, and then through the image optimization pipe. We give options to each of the pipes to control the output. Finally, we rename the image so that we can refer to it in our HTML. We also add a watch task that watches the image source folder for new files. The result is that whenever a new image is uploaded, we get a resized version ready for use in seconds. Of course, you can add as many of these resizing tasks as you need for your design.

Gulp is a tremendously helpful tool for front-end designers, who should embrace automation wherever possible.

Matthew Davis is a technical writer and Linux geek for Future Hosting.

Dedicated Server Special

Take advantage of our Double RAM offer on the E3-1230v2 4 x 3.30GHz+HT server! Only $134.95 per month. Managed and Unmanaged options available at checkout.

GET STARTED
  • champ here

    I saw the jpeg image quality is degrated after running through this. How to maintain the quality of the image with imagemin?