In this article:
ShortPixel Image Optimizer (SPIO) has 2 native WebP/AVIF delivery methods, but sometimes neither is able to properly serve your next-gen format files, especially if you have an NGINX server (which does not support .htaccess
files). If this is the case for you, and you have ShortPixel properly configured to generate (but not deliver) WebP or AVIF files, the best option is to use the capabilities of NGINX and transparently serve the WebP/AVIF version of your original file, if supported.
The solution is simple, albeit manual: edit the NGINX configuration files, either nginx.conf
or, if you have a setup with multiple sites, the appropriate configuration file from /etc/nginx/sites-available
.
Stop here! Before reading the instructions, make sure you understand the following:
- This method does not work for websites with Cloudflare's free plan.
- After everything is configured, your WebP or AVIF files will show up with the same URL and extension. Your browser will display
image.jpg
, but the image will actually be a WebP/AVIF file. - This solution is the version we have found to accomplish this task most successfully. If it does not work as expected or does not meet your requirements, we recommend you to get professional help from an NGINX expert. Hey, if you find something better, drop us a line too!
- If you are using a CDN provider that is not Cloudflare, or if you have a paid plan from Cloudflare, you need to make sure it supports the
Vary
header and is properly configured to deliver WebP and AVIF from the same URL based on browser capabilities so that it knows (and caches and delivers accordingly) that there could be 3 different files to deliver for the same URL depending on theAccept
header sent by the browser.- Examples: bunny.net / Cloudflare
- If you are using a CDN that does not support the
Vary
header, or if you do not have the technical knowledge to implement it, you should not use this solution at all, or you may end up serving WebP/AVIF images to browsers that do not support them. Instead, use one of the alternative solutions described at the end of this article.
The instructions defer depending on what format(s) you want to deliver.
WebP and AVIF
These instructions are valid for when you have enabled the "Create WebP versions of the images" and "Create AVIF versions of the images" options, which means that you want to serve AVIF and WebP files (WebP will only be served when AVIF is not supported by the visitor's browser).
- Add the necessary AVIF MIME type in the NGINX configuration. For this, follow this guide.
- Insert this block before the server directive, which creates the
$webp_suffix
and$avif_suffix
variables if the visitor's browser has WebP and/or AVIF capabilities:
map $http_accept $webp_suffix {
default "";
"~*webp" ".webp";
}
map $http_accept $avif_suffix {
default "";
"~*avif" ".avif";
}
- Insert this block inside the server directive:
location ~* ^(/wp-content/.+).(png|jpe?g)$ {
set $base $1;
set $double_extension $1.$2;
add_header Vary Accept;
try_files $double_extension$avif_suffix$webp_suffix $base$avif_suffix$webp_suffix $double_extension$avif_suffix $base$avif_suffix $double_extension$webp_suffix $base$webp_suffix $uri =404;
}
- Disable ShortPixel's native delivery method. Go to Settings > ShortPixel > Advanced and uncheck the box "Deliver the next generation versions of the images in the front-end":
Only WebP
These instructions are valid for when you have enabled only the "Create WebP versions of the images" option, which means that you want to serve WebP files (and not AVIF).
- Insert this block before the server directive, which creates the
$webp_suffix
if the browser supports WebP:
map $http_accept $webp_suffix {
default "";
"~*webp" ".webp";
}
- Insert this block inside the server directive:
location ~* ^(/wp-content/.+).(png|jpe?g)$ {
set $base $1;
set $webp_uri $base$webp_suffix;
set $webp_old_uri $base.$2$webp_suffix;
set $root "<<FULL PATH OF WP-CONTENT PARENT>>";
root $root;
add_header Vary Accept;
if ( !-f $root$webp_uri ) {
add_header X_WebP_SP_Miss $root$webp_uri;
}
try_files $webp_uri $webp_old_uri $uri =404;
}
- Make sure to replace
<<FULL PATH OF WP-CONTENT PARENT>>
with the actual absolute path to the wp-content folder, without the folder itself. Example:/home/john/public_html/
. TheX_WebP_SP_Miss
header is not necessary, but useful for testing – this header is set if the browser has WebP capabilities, but no WebP version of the image is found on disk. You can disable it later by commenting out the entireif
directive. - Disable ShortPixel's native delivery method. Go to Settings > ShortPixel > Advanced and uncheck the box "Deliver the next generation versions of the images in the front-end".
Only AVIF
These instructions are valid for when you have enabled only the "Create AVIF versions of the images" option, which means that you want to serve AVIF files (and not WebP).
- Add the necessary AVIF MIME type in the NGINX configuration. For this, follow this guide.
- Insert this block before the server directive, which creates the
$avif_suffix
if the browser has AVIF capability:
map $http_accept $avif_suffix {
default "";
"~*avif" ".avif";
}
- Insert this block inside the server directive:
location ~* ^(/wp-content/.+).(png|jpe?g)$ {
set $base $1;
set $avif_uri $base$avif_suffix;
set $avif_old_uri $base.$2$avif_suffix;
set $root "<<FULL PATH OF WP-CONTENT PARENT>>";
root $root;
add_header Vary Accept;
if ( !-f $root$avif_uri ) {
add_header X_AVIF_SP_Miss $root$avif_uri;
}
try_files $avif_uri $avif_old_uri $uri =404;
}
- Make sure to replace
<<FULL PATH OF WP-CONTENT PARENT>>
with the actual absolute path to the wp-content folder, without the folder itself. Example:/home/john/public_html/
. TheX_AVIF_SP_Miss
header is not necessary, but useful for testing – this header is set if the browser has AVIF capabilities, but no AVIF version of the image is found on disk. You can disable it later by commenting out the entireif
directive. - Disable ShortPixel's native delivery method. Go to Settings > ShortPixel > Advanced and uncheck the box "Deliver the next generation versions of the images in the front-end".
Example (Plesk)
Let us say you want to only deliver WebP files. If you use Plesk to manage your NGINX server, you can follow these instructions.
- Connect to the Plesk server via SSH.
- Create the /etc/nginx/conf.d/webp.conf file by entering the following command:
touch /etc/nginx/conf.d/webp.conf
- Open the webp.conf file in a text editor (e.g. vi editor) and add the following content:
map $http_accept $webp_suffix {
default "";
"~*webp" ".webp";
}
- Save the changes and close the file.
-
Log in to Plesk and go to Domains > yourdomain.com > Hosting & DNS > Apache & nginx settings.
- Paste the following code snippet into the Additional nginx directives field. Don't forget to replace
YOUR_DOMAIN
with your actual domain name (withoutwww
orhttps://
):
location ~* ^(/wp-content/.+).(png|jpe?g)$ {
set $base $1;
set $webp_uri $base$webp_suffix;
set $webp_old_uri $base.$2$webp_suffix;
set $root "/var/www/vhosts/YOUR_DOMAIN/httpdocs/";
root $root;
add_header Vary Accept;
if ( !-f $root$webp_uri ) {
add_header X_WebP_SP_Miss $root$webp_uri;
}
try_files $webp_uri $webp_old_uri $uri =404;
}
- Go back to your SSH connection and enter the following command to restart the nginx service and apply the changes:
service nginx restart
Example (RunCloud)
This guide was kindly provided to us by Gustavo, a dear customer of ShortPixel (thank you!). We assume that your server is running Ubuntu and your web app is running NGINX, and that you want to deliver both WebP and AVIF.
Important: Make sure that there is no expiration header cache rule set by NGINX that controls the expiration time of the files in question (jpg|jpeg|png|webp|avif). When this rule is enabled, the server returns only the original images (PNG or JPG) and not the optimized images (WebP or AVIF, as supported by the browser).
- Make sure that the required AVIF MIME types are present in the NGINX configuration. To do this, connect to your server and edit the /etc/nginx-rc/mime.types file.
- Make sure you see the following lines, and if not, add them:
image/avif avif;
image/avif-sequence avifs;
- Now go to /etc/nginx-rc/conf.d/ and once in it, create a configuration file there with the name of your choice (in this example it is images.conf).
- Edit the images.conf file and insert the following code:
map $http_accept $webp_suffix {
default "";
"~*webp" ".webp";
}
map $http_accept $avif_suffix {
default "";
"~*avif" ".avif";
}
-
Log in to your RunCloud dashboard, select the web app of your choice and click on NGINX Config.
- Click on the button Add a New Config.
- On the new screen, select the following:
- Predefined Config: I want to write my own config
- Type: location.main-before
- Config Name: whatever you want, e.g. shortpixel
- Insert this block:
location ~* ^(/wp-content/.+).(png|jpe?g)$ {
set $base $1;
set $double_extension $1.$2;
add_header Vary Accept;
try_files $double_extension$avif_suffix$webp_suffix $base$avif_suffix$webp_suffix $double_extension$avif_suffix $base$avif_suffix $double_extension$webp_suffix $base$webp_suffix $uri =404;
}
-
Save the new file and go to the main dashboard of your server in RunCloud. There go to Services > NGINX and click on Reload.
Alternatives
If you cannot use this method, you should try an alternative solution for WebP or AVIF image delivery:
- Use one of the WebP/AVIF delivery options built into SPIO: WebP instructions / AVIF instructions.
- Replace ShortPixel Image Optimizer with ShortPixel Adaptive Images.
- Use another plugin to deliver the WebP/AVIF files created by ShortPixel, such as Cache Enabler or WP Rocket.
- If you use LiteSpeed Cache, you can use it to deliver the WebP files generated by ShortPixel.