WebP Delivery
While conversion is relatively straight-forward, WebP delivery can get more complex.
There are several delivery/rewriting options available directly in the EWWW IO plugin: Apache/Litespeed rewrite rules (.htaccess), JS WebP Rewriting, and <picture> WebP Rewriting.
All methods for WebP delivery can be split into two categories:
- Server-based delivery: in this mode, the image URLs in your page will not change, and the rewriting happens (in place) when the visitor's browser actually requests the image. Examples include Apache/Litespeed/Nginx rewrite rules, and CDN-based delivery like our Easy IO CDN.
- HTML-based delivery: these methods typically involve changing the markup/structure of the page, or at the very least adding the WebP image URLs into the HTML for a given page.
If your web host features any sort of server-level caching solution, you deliver your images through a CDN (content distribution network), or you use a cloud security service like Cloudflare or Sucuri, you may not be able to use server-based rewrite rules. Check our instructions for known-working CDNs.
Server-level Caching
WP Engine uses server-level caching on all accounts by default. You can ask them to setup WebP rewriting rules for you, or just use JS WebP Rewriting. Any web host that has server-level asset caching--that is, caching of images, JS, CSS, and so on--must be able to vary the cache content based on whether the browser supports WebP. If they don't have the ability to vary the cache content, old browsers will have broken images, and posting to services like Slack, Facebok, and Twitter may fail miserably.
Cloudways servers use server-level caching, but as of 2022/06, one can enable the WebP Redirection option under Application Settings and then use the EWWW IO .htaccess rules for Apache (detailed below).
SiteGround Hosting
If you use SiteGround (and their new Site Tools console), you can enable built-in server-based WebP delivery, with no further action required (beyond converting your images to the WebP format).
Server-based WebP Delivery
Rewriting with Apache & Litespeed
Many web servers run Apache (or Litespeed), and for those sites, the EWWW IO plugin has a one-click button to modify the rewrite rules in your .htaccess file. This will send WebP images to supported browsers, though only if a WebP file exists. When you enable WebP conversion, the rewrite rules will be displayed, but only if your site does not use Cloudflare. The plugin will also display a test image by the WebP settings: a red PNG image indicates the server is not sending WebP images, or your browser does not support them.
When you insert the rules, you will get a success message if it worked, and it will attempt to reload the test image. It may sometimes be necessary to reload the page to get the right test image to load.
*EWWW IO will also attempt to automatically verify whether your server is delivering WebP images properly, in case your browser is being stubborn and not letting you see the green WebP image. This also helps to verify things are working if you see an error about mod_headers or mod_rewrite.
This video demonstrates two of the WebP delivery methods, and how to verify that they are working (<picture> WebP can be verified much like JS WebP, by looking at the actual filenames):
If you're running a multi-site WordPress install, you may have to put the rewrite rules above your Wordpress rules for them to take effect. And if the rewrite rules aren't working, you can try the JS WebP Rewriting instead.
Rewriting (via map) with Nginx
EWWW IO can't directly modify your Nginx configuration, so the solution is a bit different for Nginx. You need to potentially modify three different files here:
First, we need to add a map directive to your http config, usually in the /etc/nginx/nginx.conf file. The map directive must be inside of the http{} section/block, before the server{} block:
map $http_accept $webp_suffix { default ""; "~*webp" ".webp"; }
That tells Nginx to set $webp_suffix to ".webp" if the browser's Accept header contains "webp". Note that if your Nginx configuration has a modular setup, like SpinupWP, you can put it in a separate config file, so long as that config file is prior to the server{} block. On SpinupWP, that would be a folder like /etc/nginx/sites-available/example.com/server/
The second change is to be sure that Nginx knows what a .webp file is. While newer versions of Nginx should already recognize the WebP format, we may need to modify the mime.types file (also in /etc/nginx/) to tell Nginx about this new file type. Look for this line, and add it if you can't find it:
image/webp webp;
The last change is to setup a location block within your server block to handle PNG and JPG images that might have WebP versions. If you only have one server block, it is usually located in /etc/nginx/sites-enabled/default. Add this within the server {} section:
location ~* ^.+\.(png|jpe?g|gif)$ { add_header Vary Accept; try_files $uri$webp_suffix $uri =404; }
This tells Nginx to apply the enclosed rules to any files that end with png, jpg, or jpeg. If you have .jpe files, add a second question mark after the g, so it looks like "jpe?g?". The first rule adds the "Vary Accept" header to the return response, which is what allows supported CDNs to cache different files for the same URL. The second rule tells Nginx to look for a file that matches the original URL/URI with our $webp_suffix appended (.webp), and if that fails, to just deliver the original URI or fallback to a 404 if the file doesn't exist at all.
Just like any server-based delivery method, your image URLs do not change, but the content (and corresponding content-type) will show as WebP:
HTML-based WebP Delivery
Unlike server-based delivery, these methods do change your URLs. But your server may not know what a WebP image is, resulting in this bit of odd behavior:
In this case, the file extension is your confirmation that things are working correctly, and you can ignore the Content Type displayed by your browser.
JS WebP Rewriting
This method uses a small bit of JavaScript to dynamically change the image URLs based on whether the visitor's browser supports the WebP format. This method may not work with some themes/plugins, so let us know if you find any conflicts!
Lazy Loading
When JS WebP is used with our built-in lazy loader, you get smaller images plus less page weight, and support for inline CSS background images. JS WebP is also compatible with these lazy load plugins.
<picture> WebP Rewriting
This method wraps your images inside an HTML "picture" element without using any JavaScript. However, it has no support for CSS background images, and if your theme can't cope with the modified HTML markup, your images won't be styled correctly.
SWIS WebP Rewriting
There is a WebP Variant option in our SWIS Performance plugin that works nicely with page caching and proxy servers, but it does not work if you have offloaded your images to S3.
AMP (Accelerated Mobile Pages)
AMP has this fabulous 'fallback' attribute that allows you to wrap one image element inside another. Then if the first image cannot be displayed, the second one loads instead. The AMP Project Docs even show an example of this, but it doesn't really work properly. The problem is that unsupported browsers will still load the webp image, and only then, after you've wasted precious mobile data, does it load the original (fallback) image.
Fortunately, any server-based WebP delivery method will still work with AMP, and that's the cleanest option anyway. If the Apache/Nginx rules are a non-starter, for example, if you're using Cloudflare, there are a couple different options. You can use our Easy IO CDN for automatic WebP conversion & delivery, or you can also use Cloudflare's Polish feature (available on Pro plans).