If you are checking your website's performance using Lighthouse, you might have noticed that one recommendation is to use "Serve images in next-gen formats" and by that, they mean WebP.
According to Google, if you compress PNG images, you will save 26% on average.
Compared to JPEG with a similar SSIM setting, the difference is even
more significant — 25%-34% depending on image type. We tested those
claims on our JPEG photos from a smartphone, read on to learn about the
Note: Be careful what type of image you compress
with WebP because it has no progressive loading like JPEG, so your hero
image in WebP might negatively impact First Contentful Paint.
If WebP is so good, why isn't everyone using it?
In short: Tooling.
- Your phone takes photos in JPEG.
- Your computer takes screenshots as PNG or JPEG.
- When you download images from a stock photo service, it's JPEG.
- Logotypes are often SVG.
- Your operating system most likely does not know how to preview WebP natively, so you need to download special software to do it.
All these are barriers to adoption for this format, which apart from
having better compression, has an alpha channel, which is missing from
One day, looking at a performance report from our social commerce marketplace template (see live demo at: https://getmarketplace.co/ ), I decided to do something about it and add WebP versions of the biggest images.
Why only the biggest images? Because the bigger the image, the bigger the savings.
Saving 20% from a 9 KB lazy-loaded image is a good thing, but saving
20% from 3 images eagerly-loaded, 500 KB each, is much better.
Not all browsers support WebP, so you'll need a fallback for those browsers. Luckily, the picture HTML tag takes care of that.
Read about browser support for WebP at caniuse.com: https://caniuse.com/?search=webp
In any case, you can use WebP nowadays with a fallback to JPEG - read how to do it (and more) in this excellent CSS-Tricks article.
platformOS image versions
Users very rarely have images in an optimal format or version. Often
users upload photos straight from their camera or photos in PNG format.
More often than not, you want to recompress those images to fit your
performance and quality vision. We implemented a feature that allows the
site owner to decide what to do with user-uploaded images.
After the user uploads the image directly to cloud storage to
speed up things by eliminating intermediaries, a function takes the
original file and generates new versions based on the configuration
defined in a YML file. It usually takes so little time that the user
will not notice when it happens, as it happens in the background,
In our case, the basic configuration looked like this:
- name: photo
- name: uncropped
This means whatever image the user uploads will be available to use in
its original form and an additional JPEG file will be generated called
uncropped with quality 80. We wanted to also have this image in WebP format, so I added the second version to the array:
- name: uncropped_webp
HTML and Liquid
To show the images we have to get objects from GraphQL and retrieve URLs to the generated versions and use picture element for fallback. Explore how to do it on platformOS in this gist.
I uploaded three photos straight from my smartphone:
They are very big in terms of dimensions (4608x2592 px) and size, so I
expected to see a lot smaller files at the end of this experiment.
Recompression to quality 80 in JPEG gave pretty good results:
Let's compare them to the WebP version (quality 70):
The images vary in many ways, including color distribution or the
numbers of edges. Because results depend on image content, an average is
most often used when describing compression results. The smallest
difference was 23%, and the biggest was 48%. That's a huge variance. In
total, those three images saved 1.7 MB.
├── [ 11M] original
│ ├── [3.5M] IMG_20201105_144639.jpg
│ ├── [4.2M] IMG_20201109_194144.jpg
│ └── [3.2M] IMG_20201115_001933.jpg
├── [4.7M] processed-jpeg
│ ├── [1.5M] uncropped_IMG_20201105_144639.jpg
│ ├── [1.9M] uncropped_IMG_20201109_194144.jpg
│ └── [1.3M] uncropped_IMG_20201115_001933.jpg
└── [3.0M] processed-webp
├── [1.0M] uncropped_webp_IMG_20201105_144639.webp
├── [1.0M] uncropped_webp_IMG_20201109_194144.webp
└── [996K] uncropped_webp_IMG_20201115_001933.webp
Saving 1.7 MB (or 36%) on three images without noticeable quality
degradation is a success in my book. We could turn up the quality knob
higher, and we'd still have plenty of headroom not to lose any detail at
all. It is a good result for a couple of lines of code. Especially if
the image you are optimizing is a crucial piece of content (in our case,
an item photo) and not some stock photo.
If you want to check out how the files are different visually, you can view them on my GitHub.