Create and Serve WebP in Nginx / Apache - Ubuntu 18.04

image

sudo apt-get install webp
nano ~/webp-convert.sh
#!/bin/bash

# converting JPEG images
find $1 -type f -and \( -iname "*.jpg" -o -iname "*.jpeg" \) \
-exec bash -c '
webp_path=$(sed 's/\.[^.]*$/.webp/' <<< "$0");
if [ ! -f "$webp_path" ]; then
  cwebp -quiet -q 90 "$0" -o "$webp_path";
fi;' {} \;

# converting PNG images
find $1 -type f -and -iname "*.png" \
-exec bash -c '
webp_path=$(sed 's/\.[^.]*$/.webp/' <<< "$0");
if [ ! -f "$webp_path" ]; then
  cwebp -quiet -lossless "$0" -o "$webp_path";
fi;' {} \;

chmod a+x ~/webp-convert.sh
cd /var/www/html/wp-content/uploads/
~/webp-convert.sh

Automate WebP Generation

sudo apt-get install inotify-tools
nano ~/webp-watchers.sh
#!/bin/bash
echo "Setting up watches.";

# watch for any created, moved, or deleted image files
inotifywait -q -m -r --format '%e %w%f' -e close_write -e moved_from -e moved_to -e delete $1 \
| grep -i -E '\.(jpe?g|png)$' --line-buffered \
| while read operation path; do
  webp_path="$(sed 's/\.[^.]*$/.webp/' <<< "$path")";
  if [ $operation = "MOVED_FROM" ] || [ $operation = "DELETE" ]; then # if the file is moved or deleted
    if [ -f "$webp_path" ]; then
      $(rm -f "$webp_path");
    fi;
  elif [ $operation = "CLOSE_WRITE,CLOSE" ] || [ $operation = "MOVED_TO" ]; then  # if new file is created
     if [ $(grep -i '\.png$' <<< "$path") ]; then
       $(cwebp -quiet -lossless "$path" -o "$webp_path");
     else
       $(cwebp -quiet -q 90 "$path" -o "$webp_path");
     fi;
  fi;
done;
chmod a+x ~/webp-watchers.sh
./webp-watchers.sh /var/www/html/ > output.log 2>&1 &

NGINX

# http config block
map $http_accept $webp_ext {
    default "";
    "~*webp" ".webp";
}

fastcgi_cache_path /var/www/cache levels=1:2 keys_zone=WORDPRESS:100m inactive=6h;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
fastcgi_cache_use_stale error timeout invalid_header http_500;
fastcgi_ignore_headers Cache-Control Expires Set-Cookie;

server {
    listen         80;
    return 301 https://$host$request_uri;
}
server {
root /var/www/html;
index index.php index.html index.htm;
server_name .example.com;
client_max_body_size 0;

    listen [::]:443 ssl http2 ipv6only=on;
    listen 443 ssl http2;
        ssl on;
        ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
        ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
        ssl_prefer_server_ciphers on;
        ssl_session_cache   shared:SSL:20m;
        ssl_session_timeout 20m;
        ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';

error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;

# server config block
location ~* ^(/wp-content/.+)\.(png|jpg)$ {
    set $img_path $1;
    add_header Vary Accept;
    try_files $img_path$webp_ext $uri =404;
    expires 1y;
}

set $skip_cache 0;
    if ($request_method = POST) {set $skip_cache 1;}
    if ($query_string != "") {set $skip_cache 1;}
    if ($request_uri ~* "/wp-admin/|/xmlrpc.php|/wp-.*.php|index.php|sitemap(_index)?.xml") {set $skip_cache 1;}
    if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in") {set $skip_cache 1;}

location / {
        try_files $uri $uri/ /index.php?$args;
}

Apache

<ifModule mod_rewrite.c>
  RewriteEngine On
  RewriteCond %{HTTP_ACCEPT} image/webp
  RewriteCond %{REQUEST_URI}  (?i)(.*)(\.jpe?g|\.png)$
  RewriteCond %{DOCUMENT_ROOT}%1.webp -f
  RewriteRule (?i)(.*)(\.jpe?g|\.png)$ %1\.webp [L,T=image/webp,R]
</IfModule>

<IfModule mod_headers.c>
  Header append Vary Accept env=REDIRECT_accept
</IfModule>

AddType image/webp .webp

Source 1, Source 2

4 Likes

I guess this is fine ?

Looks like those files were already converted to WebP?