WordPress, Nginx, Apache and webp images
So you want to use webp with WordPress but not install just another (paid) plugin? With the help of some bash, ImageMagick and nginx or apache you're ready to go.
Why not installing another plugin?
Feel free to buy one of the many image optimization and converting plugins out there! Many of them are good and convenient.
I wanted to keep the plugin count down and not pay for something that's actually not that hard to achieve.
So I thought a bit about the problem, wrote a little bash script and did some research about the best ways to use the images in WordPress.
Ok, now show me the script, please!
Hold your horses! This is actually a very nice task which can be done quite easily if you have access to the webserver. First, the requirements:
- You need access to your webserver via ssh (it's a bash script after all)
- You need ImageMagick installed (we need
convert
) - You need to be able to create cronjobs (
crontab -e
) - For nginx, you need access to the webserver's config
All set? Let's continue then...
The script convert-webp.bash
:
#!/bin/bash
if [ -z "$1" ]; then
echo "missing base target path parameter"
exit 1
fi
BASE=$1
find "$BASE"/* -type f \( -iname \*.jpg -o -iname \*.png -o -iname \*.jpeg \) | while IFS= read -r file; do
# if the conversion target already exists, we continue
if [ -f "$file.webp" ]; then
continue;
fi
# make sure we do not convert accidentally included webp files, again
if [[ $file = *".webp" ]]; then
echo "ignoring webp files"
continue;
fi
# now doing the conversion, we could also tune the quality a bit here
convert "$file" -quality 50 -define webp:lossless=false "$file".webp
echo wrote "$file.webp"
done
Now make the script executable: chmod +x convert-webp.bash
.
The script can be called via ./convert-webp.bash path/to/your/wp-content/uploads
.
To create a cronjob: crontab -e
and set:
*/30 * * * * bash /path/to/script/convert-webp.sh /path/to/your/wp-content/uploads
So the first part is done!
Configure nginx or apache
Normally using webp if existing can be done with all webservers. Nginx can do a lot of things especially for static files or for caching and that's why I chose it here.
Nginx config changes
I did this first with nginx since I created my own webserver and added the following:
First, in the http
level or the root
level for a vhost definition, configure the webp suffix:
map $http_accept $webp_suffix {
default "";
"~image/webp" ".webp";
}
In the server
level add a location (or change the existing) for images:
location ~* \.(jpg|jpeg|gif|png|webp)$ {
add_header Vary Accept;
add_header Cache-Control "public, immutable";
try_files $uri$webp_suffix $uri =404;
expires 1y;
}
This tells the webserver to always try using the webp_suffixed file if it exists. Otherwise, it would use the original or give a 404 error if nothing found.
Also, using a long cache time is recommended for assets, so we're going with 1 year here.
Apache .htaccess changes
Ok, I haven't tested this yet, but in theory it should look something like this:
RewriteCond %{HTTP_ACCEPT} image/webp
RewriteCond %{REQUEST_FILENAME} (.*)\.(png|gif|jpe?g)$
RewriteCond %{REQUEST_FILENAME}\.webp -f
RewriteRule ^ %{REQUEST_FILENAME}\.webp [L,T=image/webp]
<IfModule mod_headers.c>
<FilesMatch "\.(png|gif|jpe?g)$">
Header append Vary Accept
</FilesMatch>
</IfModule>
This should do the same as the nginx config from above:
- Check if the webp file exists and use it as a replacement for any other image type.
- Add the Vary Accept header
And now have fun!
Image Attribution
Main image WordPress Plugins Stephen Phillips - Hostreviews.co.uk auf Unsplash