This is my very first time when I’m writing a blog post in English.

WebP

The main reason I’m writing this post is my recent experience with WebP format on my Node.js project.

Probably you’ve heard something about this format before and know what it is, but I have to tell a few words anyway. WebP is a modern image format developed by Google and its main feature is a size efficiency in various conditions. Why it is important? Let’s remember all the cases when we should use different image formats.

PNG. A transparent image with alpha channel. It is lossless and PNG files are usually huge. However this format supports 32-bit color (24-bit for RGB and 8-bit for alpha channel), so images can be of high quality.

JPEG. A good old format for photos. But it isn’t so efficient as modern WebP and HEIF. Moreover, it doesn’t support transparent images.

GIF. A 31 years old format for animated images compression. It’s widely supported by browsers. GIF supports only 256 colors. It also supports transparency, but usually, the quality is awful because of 256 colors.

Sounds depressing, isn’t it? Don’t upset, there is a hope when WebP will be supported by all major browsers, we will forget this as a terrible nightmare. Currently, Blink is the only browser engine, which supports WebP image format. However if we will look at relative usage we will see that 73% of global Internet users can see WebP in their browsers. WebP surely worth it.

Convert to WebP

There are thousand ways to convert your existing images to WebP. To do it manually on MacOS you can run following commands:

brew install webp
cwebp -q 90 image.png -o image.webp

But it really depends on your platform and image library. I can’t name all possible options. For my web service, I’m using Node.js and ImageMagick for this.

nginx

On this step, I’ll help you configure a nginx web-server in the easiest way to support WebP.

First of all, you should put your new WebP images near to your old JPEG/PNG/GIF images, they should have the same name but with .webp extension. Then let’s change a nginx configuration. We need to change http section, usually, you can find it in the /etc/nginx/nginx.conf file, add the following config there:

http {
    # ...

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

    map $uri $file_ext {
        default "";
        "~(\.\w+)$" $1;
    }

    # ...
}

Also, we should make a location for our images in a server section. Usually you can find a server section in the /etc/nginx/conf.d/default.conf file, but it can depend from your basic nginx configuration.

server {
    # ...

    location ~* "^(?<path>.+)\.(png|jpeg|jpg|gif)$" {
        try_files $path$webp_ext $path$file_ext =404;
    }

    # ...
}

And finally please ensure that your /etc/nginx/mime.types file contains the following line:

image/webp webp;

If not, you should put it there manually. So nginx will know which Content-Type header it should send for files with .webp extension.

And that’s all. Now you can point any of your images normally. If it has corresponding WebP version and a current browser supports WebP nginx will return the WebP version. In any other cases, the legacy format version will be used.

How it works

It works really nice, but what’s under the hood? For every request nginx creates two variables $webp_ext and $file_ext

  1. $webp_ext equals .webp if current browser sends image/webp in the Accept header. Or it equals empty string otherwise.
  2. $file_ext equals file extension (e.g. .png) of current URI if current URI has it. Or it equals empty string otherwise.
  3. In the location for images, the $path without extension is captured from incoming URI. And after that nginx tries to find a WebP version by concatenating $path and $webp_ext variables. If the file doesn’t exist nginx will try the next $path and $file_ext.

You will see a legacy file extension in the URI whether it’s WebP or not, but browsers are okay with that because nginx sends correct Content-Type for WebP files.

That’s the secret.

I would be glad if this post helped you with the basic concept of how to make your website WebP ready and keep it compatible with all browsers. In my case, the main page of my website decreased from 1,6 MB to 900 KB. That’s a significant difference. People with bad Internet connection will be happy.

  1. The official WebP website
  2. JPEG vs WebP and PNG vs WebP comparison.
  3. Browser support