When I saw this competition it immediately made me think of some of the fun things that you can do with Service Workers. In some of the side projects that I've built, I repeatedly find myself the similar code over and over again. Armed with this knowledge, and inspired by the recent Service Worker helper libraries project, I decided to put together a little project that works in under 10 KB. This is where the Image Beast comes in!
When I built my Progressive Beer App and the Building Great Startup Teams website, I used Service Workers to return different image formats depending on whether the users browser supported them. Image formats such as WebP and JpegXR offer significant file size savings over the traditional formats (JPEG, GIF, PNG).
Unfortunately, most browsers don't support all of these image formats and working around them can be tricky. The Image Beast is a tiny 1 Kb script that you include in your Service Worker file. Once you have created the alternate versions of your images, Image Beast intercepts the requests and returns the appropriate formats where possible. The Image Beast does all of these things:
- Serves WebP images to Google’s Chrome Browser
- Serves JpegXR images to Microsoft’s Edge Browser
- Serves lean images to Android users with the Data Saver feature enabled
- Caches the images!
What about older browsers I hear you say? Well, the beast has them tamed too! Service Workers are the ultimate progressive enhancement and if your browser doesn’t support them they will simply return the original image as normal. If your browser does support Service Workers, then the image beast simply uses it slippery tentacles to decide the perfect image format to return.
Show me an example!
First up, you need to check if Service Workers are supported in your browser. If they are, create and register the Service Worker by adding the following code to your page.
Next, import the script into your Service Worker (service-worker.js) and begin optimizing.
As you can see from the code above, you can also configure image beast. For example, if you’d prefer not to return WebP images, then simply disable it in the config.
Head over to deanhume.github.io/image-beast and open your developer tools to see this working example. It is a really basic website, without much design, but hopefully it gives you the idea!
How does it work under the hood?
The image beast works by listening to the client hints that your browser sends through when it makes an HTTP request. Let's say you are using Google Chrome as your browser. By default, the browser will send through an Accept Request header and in the case of Chrome, it will send through a client hint of "image/webp" notifying the server that it supports WebP images. Using a Service Worker, we can tap into this request and return an alternate version of the image.
Hey, but I don't use Google Chrome! Don't worry - the image beast has you covered. Microsoft's Edge currently has Service Workers under development and the image beast will return JPEGXR images for you if it detects that it can support it. The image beast is prowling and ready to pounce on every image format.
Performance is key!
Using the image beast, you are able to return the leanest possible images to your user's browser. With the power of Service Workers, we can take this a step further and cache the image request once it has been made. This means that the user won't even have to make another HTTP request for the image and it will load instantly. It is built-in by default, but you can turn it off using the configuration options.
The image beast also has another sneaky trick up it's tentacle. Users that use Android devices and have the Data Saver feature enabled for their phone or tablet will have low resolution images returned to them. All you need to do is save a low resolution version of the image with "-savedata" appended to the file name (eg. beast-savedata.jpg) and the image beast will do the rest. In fact, even if you haven't provided a low resolution version of the image, it will simply return a tiny placeholder image in order to save your users data.
In the future, it would be great to extend this library as more image formats become available. I am keeping a close eye on FLIF, but who knows what might be next! It's worth noting that while this script works really well, I would pick and choose the right project to use it in. It will work perfectly for any website, but I imagine without the right tools in place keeping track of every image on a large website could be tricky!
I also thoroughly recommend submitting something to the 10K Apart competition - its a great chance to test your skills and you may even win some prize money!