WebP at Allegro
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.