Grunt And Gulp Tasks For Performance Optimization

Delays in performance have the potential to impact user engagement, experience and revenue. Thankfully, Google’s ‘Make The Web Faster’ team recommend a set of best-practice rules for keeping your pages lean, fast and smooth. These include minifying resources like CSS and JavaScript, optimizing images, inlining and removing unused styles and so on.

If you have complete control over your server, an excellent PageSpeed Module for Apache and Nginx exists with filters for many of these tasks. If not however, or you feel the module isn’t quite for you, a number of build-tasks exist for tools you’re probably already using to fill in the gaps with more granular control.

The below represent Grunt and Gulp tasks the Yeoman team regularly use in our projects. We’ve tried our best to keep this list focused and exclude previous suggestions which no-longer offer as much value, but there’s plenty here to help you keep your pages and their resources as small as possible.

Note: Yeoman's Grunt and Gulp webapp generators include tasks for optimizing images and concatenating and minifying HTML/CSS/JS. We feel that this provides a healthy baseline, but this post will cover tasks which go further.

Compress & optimize images

The average web page is now over 1.5MB in size, with images responsible for the bulk of this. We aim to keep our image sizes as lean as possible to reduce the time it takes for a user to wait for that resource to load.

With the right balance of compression and formatting it’s possible to still ship images as a part of your page whilst minimizing load time as much as possible. This is really important for users on mobile with limited data plans or slow connections.

Grunt

Why two tasks? Well, here’s an excellent breakdown of differences between the two. Choose the one that is most suitable for you.

Gulp

Note: Etsy found that just by adding 160KB of images to their pages on mobile, their bounce rate increased by 12%. If you can't cut down on the images used in your pages, at least run them through an optimizer.

Generate responsive images for the <picture> element

If you have a responsive site which is visually flexible on multiple devices, you’ll want a strategy to make images flexible too.

Serving unnecessarily large images to the browser can impact both rendering and load performance, but these aren’t the only metrics that can suffer when large images are shipped to the browser.

This is one reason we need responsive images, and it’s great to see srcset - hopefully leading to a full implementation of <picture> - is already in Chrome Beta.

There are a number of Grunt tasks available that can help generate multi-resolution images as part of your build process.

Grunt

In addition, if you need to just resize/normalize images that are large in dimension, you can use grunt-image-resize.

Note: Tim Kaldec's research into responsive images has suggested a responsive images strategy could lead to savings of up to 72% on image weight. Whilst it is still early to opt for a spec-compatible, cross-browser approach to responsive images the BBC and Guardian have been using Imager.js for this successfully.

Minify SVG images

SVG files created with editors usually contain a large quantity of redundant information (metadata, comments, hidden elements and so forth). This content can be safely removed or converted to a more minimal form without imacting the final SVG that’s being rendered.

Grunt

Gulp

Generate spritesheets

Grunt

Gulp

Convert images to WebP

WebP is a recent image format that offers lossless and lossy compression for images on the web. WebP lossless images are up to 26% smaller in size compared to PNGs and WebP lossy images are 25-34% smaller in size compared to JPEGs. That’s quite a saving and thankfully there exist tasks for encoding to WebP for both Grunt and Gulp.

Grunt

Gulp

Note: This test from WebPageTest suggests that compared to JPEG, WebP encoded images complete loading much quicker due to their smaller filesizes. The Chrome Web Store found that switching to WebP saw a 30% average saving on bytes, saving them several terabytes of bandwidth a day.

Build SVG sprites with support for various browsers

Grunt

Gulp

We consider inlining images using Data URIs to now be an anti-pattern given their poor performance on mobile.

Minify CSS

Minification eliminates unnecessary space, line breaks, indendation and characters in your files, which are generally unnecessary in production. Compacting down your HTML, CSS and JS can improve on parsing, execution and doanload times. For CSS specifically, we recommend:

Grunt

Gulp

Remove unused CSS

In projects using CSS frameworks like Bootstrap, Foundation and so forth you typically don’t use the entire kitchen-sink of styles available. Rather than shipping the full framework to production, use UnCSS to remove unused styles across your pages. Some developers have seen anything up to 85% savings in stylesheet filesize.

Grunt

Gulp

Note: A question developers regularly ask is whether UnCSS, or the process of removing unused CSS can also work with styles injected into the page dynamically. The answer is 'yes'. UnCSS works in tandem with PhantomJS in order to make this happen. Devs have seen anything between 10-120KB in savings on a typical Bootstrap page and UnCSS also works well with other frameworks.

Inline CSS

If the external CSS resources for a particular page are small, you can inline those directly in your markup to save on additional requests. Inlining small CSS in this way allows the browser to proceed with rendering the page.

Grunt

Gulp

Combine media queries

This isn’t a PageSpeed recommendation, but allows you to combine matching media queries into a single media query definition. We’ve found it useful for handling CSS generated by preprocessors which may use nested media queries.

Grunt

Gulp

JavaScript

Minify, compress JS

Grunt

Gulp

RequireJS (optimization via r.js)

Grunt

Gulp

Minify HTML

Grunt

Gulp

Simple concatenation

Grunt

Gulp

General compression for files/folders

Grunt

Gulp

Zopfli compression

The Zopfli Compression Algorithm is an open-source compression library that generates output typically 3–8% smaller compared to zlib at maximum compression. It is best suited for apps where data is compressed just once and then sent over the network lots of times.

Grunt

Gulp

Note: When Google Fonts switched to using Zopfli fonts were ~6% smaller on average, and in some cases up to 15% smaller. According to Ilya Grigorik, for the case of Open Sans it was more than 10% smaller, translating to faster rendering and loading times. Zopfli images can however take longer to decode than JPGs so measure the metrics that matter to you when deciding whether to use WebP.

Inline Critical path CSS

The critical path represents the code and resources needed to render the “above-the-fold” content in the page - i.e what your users will first see when they load up your page. PageSpeed recommends inlining your critical path CSS for improved performance. Whilst tools like mod_pagespeed are highly efficient at achieving this, it’s more difficult to optimize for the critical path with other tooling.

You could probably use PhantomJS along with the above the fold scripts from speedreport to get an idea of what CSS is above the fold and can then work on optimizing this manually.

Note: Paul Kinlan wrote a bookmarklet for estimating the above-the-fold CSS for a page which is also worth checking out.

Asset pipeline (auto-handle all optimizations)

On the ‘tools to keep an eye on’ list is AssetGraph.

AssetGraph looks at projects as a set of graph problems where the nodes are considered assets (HTML, CSS, Images, JS) and edges, the relationships between them (image tags, anchor tag, script tags etc).

As AssetGraph can determine how project assets relate to each other it can perform many of the common performance optimizations developers may want to achieve on their own automatically. This works particularly well on smaller projects and support for larger projects is being worked on.

Grunt

Gulp

Gulp users should just use AssetGraph directly.

Benchmarking

The following benchmarking tasks are useful to integrate as a part of Continuous Integration. Although the following are currently only available for Grunt, you can use gulp-grunt to run Grunt tasks from Gulp. We recommend:

  • grunt-pagespeed - fantastic for automating checking your PageSpeed score as a part of CI.
  • grunt-topcoat-telemetry - get smoothness, load time and other stats from Telemetry as part of CI. This could help you set up a performance benchmarking dashboard similar to the one used by TopCoat
  • grunt-wpt - CI for WebPageTest scores
  • grunt-phantomas - response times for requests, responses, time to first image/CSS/JS, onDOMReady and more.

Framework Optimization

Grunt

Gulp

Misch

Conclusions

Delays in performance have the potential to impact user engagement, experience and revenue. Take time to experiment with the tasks available for performance optimization, find out what practical gains they can offer to your projects.

Visitors to your page will be happier as a result of a snappier experience and a faster web is better for all.

~ Addy Osmani

With thanks to Sindre Sorhus, Pascal Hartig and Stephen Sawchuk for their review


« View More Posts