A lot has already been written about WebP, a new image format created by Google that provides both lossy and lossless compression of images displayed on the web. However, this solution is still not popular in web development.

Although it’s already shipped by Chrome and Opera, pay attention that Internet Explorer 11 and Firefox 41 do not support the new format. Browser support can be checked on caniuse.com and status.modern.ie websites.

Benefits of WebP

The table below shows potential benefits for selected websites if WebP is used instead of JPEG:

website # of JPEG images JPEG images size WebP images size
bbc.com 26 332KB 188KB
allegro.pl 26 1011KB 267KB
amazon.com 147 1945KB 1082KB
zalando.pl 34 410KB 67KB
merlin.pl 77 858KB 366KB

Recently, we delivered WebP to Allegro Articles’ readers. And here’s what we have gained in various departments:

department size of JPEG images size of WebP images
electronics 642KB 440KB
sports and leisure 740KB 462KB
automotive 747KB 501KB
household and health 821KB 445KB
baby 1004KB 462KB
culture and entertainment 742KB 462KB
fashion and beauty 682KB 425KB

We have reduced the website size by 40% on average. This change is obviously meaningful for mobile users.

The <picture/> way

The easiest way to provide an image format that is supported by a user’s browser is to use the picture HTML5 tag. You can find up-to-date documentation concerning this tag in the latest HTML Editor’s Draft. Here is an example:

<picture>
  <source srcset="photo.webp" type="image/webp" />
  <img src="photo.jpg" alt="photo" />
</picture>

The action performed by the user agent is called image format based selection. It checks the type attribute of the first picture’s source child element. If a browser supports a particular MIME type, then the first source element is applied. Otherwise, the next one is taken into account (in this case it is img that is obviously supported everywhere).

The picture and source tags are not supported by all browsers (check browser support). Nevertheless, web developers know how to deal with it. Scott Jehl created picturefill which might be helpful in such cases. The script goes through each child of a picture element and verifies whether your browser supports given media types. Next, it selects the best candidate based on supported media types and window.devicePixelRatio. The best option is applied and the img tag is created with src value derived from srcset.

If adding some extra kilobytes to your website is not a problem, then picturefill might suit you well. However, there is one catch — you need to have two versions of an image. The first image as WebP and the second one as JPEG. As a result, you need to maintain both versions, which is not always possible.

Converting images on the fly

You can solve this problem if you have your own image conversion service. At Allegro we use ScaleMe to convert images on the fly. We use it to manipulate images served for Allegro Articles. Just compare these two examples (use Chrome or Opera to open the second URL):

http://articles.scaleme.pl/DB60B87F/27363/238x134/centercrop — JPEG, 14.4 KB

http://articles.scaleme.pl/DF95DFDF/27363/238x134/centercrop/format_webp — WebP, 4.7 KB

Media types and URLs are different, but the source of these two images is the same. Pay attention to the size difference as it is quite significant, whereas the difference in quality is negligible.

Analyzing Accept header

Every WebP-enabled browser is expressing this fact via Accept header. For example Google Chrome sends the following:

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8

The above-mentioned header allows you to indicate user agents that support WebP. In case of Spring Framework, an interceptor can help you with that task:

public class WebpInterceptor extends HandlerInterceptorAdapter {
    private final Pattern webpPattern = Pattern.compile(".*image/webp.*");

    @Override
    public void postHandle(HttpServletRequest request,
                           HttpServletResponse response,
                           Object handler,
                           ModelAndView modelAndView) {
        String accept = request.getHeader("Accept");
        if (null != modelAndView && webpPattern.matcher(accept).matches()) {
            modelAndView.getModelMap().addAttribute("webp", true);
        }
    }
}

If a user agent supports WebP images then webp attribute is added to a model. Therefore, it can be used in a template — here is a Handlebars example:


{{if webp}}
  <img src='{{image article.image "webp"}}' alt="" />
{{else}}
  <img src='{{image article.image "jpeg"}}' alt="" />
{{/if}}

The image helper uses a backend image manipulation tool and serves a suitable image URL:

@Override
public String image(String url, String format) {
    return imageManipulationService.buildImageUrl(format);
}

Caching on proxy server

If you use any caching proxy servers (for example Varnish Cache) do not forget to add the following response header:

Vary: Accept

The header instructs a proxy to cache a separate copy for each Accept header variant. As a result, content with WebP images is served to all WebP-enabled browsers, whereas JPEG images are sent to the others.

Summary

The benefit that is brought by WebP is not small at all. Sometimes it is quite significant. According to caniuse.com the WebP format can be served to 61% of Internet users all over the world and to 73% of Internet users in Poland. By taking it into account, it is worth getting your hands dirty and provide your users with WebP.