Using Grunt to generate WebP image assets
Web Development17 March 2017
I've previously written about using
<picture> and WebP to dramatically reduce the weight of your pages, but if all your assets are PNG or JPG you might need a way to generate WebP images from them. There's probably a plugin for your image editor of choice that can export your images as WebP, but this kind of repetitive manual job is exactly what task runners like Grunt and Gulp are really good at.
If you've not used one before, the gist of a task runner is that you equip it with a set of capabilities by installing modules, and then give it a list of tasks to perform. In your task runner's configuration you tell it where to find your project files, what tasks you'd like to run against them, and where to place any resulting new files.
In this brief overview, we'll use my favourite task runner, Grunt, to take all the JPG and PNG images in a project and output WebP versions of them in a separate folder.
Getting started: installing dependencies
Grunt requires Node.js and NPM. You can find detailed instructions on getting Grunt installed in its documentation. Grunt uses two files in your project:
package.json for a list of modules to install, and
gruntfile.js for instructions on what tasks to perform. The task we're going to have it carry out is automated bulk conversion of image files to the WebP format, and we'll be using a module called grunt-cwebp to do that.
Configuring Grunt: package.json
We need a
package.json file that lists the grunt-cwebp module as a project dependency for NPM to install it for us. Here's a quick example file that will install grunt-cwebp when we run the command
npm install in the terminal from the root of our project:
Configuring Grunt: gruntfile.js
With our node module installed, we now need a
gruntfile.js to define the WebP conversion task we'd like Grunt to perform. In the sample file below, we configure a task named
cwebp, with parameters that specify the quality we would like to maintain during the conversion, where to find the files we'd like converted, the file formats to convert, and finally a destination folder for the resulting WebP images.
We'll place our original JPG and PNG images in the folder specified under
cwd in the gruntfile:
images/img_original. To have Grunt do all the image conversion heavy lifting for us, we run the command
grunt cwebp:dynamic from the terminal, and watch as it takes our originals, crunches them to the quality specified, and drops shiny new WebP versions in the
images/img_webp folder. And we're done! We now have a new WebP file for every source file in the
You might have noticed that we defined a task named
dev at the bottom of our gruntfile, which runs
cwebp:dynamic for us when we run the command
grunt dev in the terminal. This might seem unnecessary for a single task, but on more complicated projects shortcut commands like
A note on image quality
In our gruntfile we set the desired quality of our new WebP images at 75. Depending on the original source image, I've found this level to maintain a virtually indistinguishable visual quality with a smaller file size, but it's worth noting that not all images will be smaller in WebP format than they might be in JPG or PNG. Experiment with it, and if you find that the WebP version of a given image is the same size (or perhaps larger!) than the source JPG or PNG, you'd be better off linking to the original source file in your markup instead. Where a smaller file size is realised though, WebP is an excellent way to reduce page weights, sometimes quite significantly.