WebP support for the image compression script

[blog poststandalone]

Long ago I published my image compression script and it has been very useful to me. I hope it was useful for somebody else too.

I have just added support for *WebP* image format. This image was designed to further save size of your website images without losing quality. Now, if you pass the -w parameter to the script, an additional file will be created in WebP format and appending the file extension .webp. So if your image was called something.png, the script will create something.png.webp. I will explain below why to append and not replace the extension.

The idea now is that, when our web server receives a request for an image (i.e. /img/something.png) It will return the WebP version (i.e. /img/something.png.webp) if the browser supports WebP or the original if it doesn't. We know that a browser supports WebP because as part of the request it will send the HTTP header Accept: image/webp,*.*.

I use and love Nginx as my http server so I will show you how to implement the above behavior in it.

First of all we will add a map like the one below. A good place to set it is /etc/nginx/conf.d/webp.conf.

map $http_accept $webp_ext {
    default         "";
    "~*image/webp"  ".webp";

This way, the variable $webp_ext will be an empty string if the browser does not support WebP or it will be .webp if it does support it.

You can now add a section for the images that will look like this.

location ~* \.(gif|jpg|jpeg|png)$ {
    add_header Vary Accept;
    expires 31536000s;
    add_header Pragma "public";
    add_header Cache-Control "max-age=31536000, public, must-revalidate, proxy-revalidate";
    try_files $uri$webp_ext $uri =404;

We add the Vary header so any intermediate cache or CDN splits the cache depending on the Accept header sent by the browser. Note that right now some CDN services like CloudFlare do not honor the Vary header though.

The real magic happens in the try_files where it will return the WebP image depending on the value of $webp_ext. I added also a single $uri just in case, but it shouldn't be required.

With this you should have your setup complete. Do not forget to add a periodic task via cron or systemd timers to compress and generate WebP versions of your new images.

#m h dom mon dow command
15 * *   *   *   /var/www/tools/dIb_compress_images -q -c -w /var/www/my_website

Enjoy your performance boost.

Remember that you can get the image compression script from GitHub here: https://github.com/diego-treitos/dgtool/blob/master/compress_images/dIb_compress_images