Современные форматы сжатых изображений стали достаточно хороши для того, чтобы вытеснить традиционный JPEG. Внедрять их в дело с помощью разнообразных плагинов и уж тем более внешних сервисов желания не возникает как в силу замороченности и полуплатности плагинов, так и в силу неудобных алгоритмов их работы. Без вмешательства в работу сайта оно как-то логичнее.
Написал скриптик по изготовлению кэша с конвертированными в форматы WEBP и AVIF файлами:
#! /bin/bash
############################################################
## ##
## Конвертация картинок сайта в более экономные форматы ##
## v 1.1 ##
## 2024-02-23 ##
## ##
############################################################
## Планируемые доработки:
## 1. Сделать обратную конвертацию в jpeg для webp и avif
## файлов в целях совместимости со старыми браузерами
# Путь к папке сайта с исходными картинками (вложенные папки перенесутся автоматически)
SOURCE_DIR='<путь к папке>/uploads';
# Путь к папке кэша с набором конвертированных картинок
TARGET_DIR='<путь к папке>/cache';
cd $SOURCE_DIR;
# Ищем в исходной папке файлы под конвертацию
ARRAY=()
while read FILE; do
ARRAY+=("${FILE%$SUFFIX}")
done < <(find . -type f -regextype posix-egrep -regex "^.*(.jpg|.jpeg|.png|.gif)$" -mtime -1)
for ITEM in "${ARRAY[@]}"; do
LOCALPATH="${ITEM:1}"
SUFFIX="${LOCALPATH##*.}"
NAME=${LOCALPATH%%.*}
SOURCE_FILE="$SOURCE_DIR$LOCALPATH"
echo " "
if [ -f "$SOURCE_FILE" ]; then
z=$(stat -c '%s' "$SOURCE_FILE")
echo "├── $z $SOURCE_FILE"
if [[ $SUFFIX =~ ^(jpg|jpeg|png|gif)$ ]]; then
TARGET_FILE="$TARGET_DIR$NAME.webp"
# поверяем наличие папки в кэше и создаём если её нет
if [ ! -d $(dirname "$TARGET_FILE") ]; then
mkdir -p $(dirname "$TARGET_FILE")
fi
if [ ! -f $TARGET_FILE ]; then
convert $SOURCE_FILE $TARGET_FILE
else
echo "├── Файл webp уже есть"
fi
z=$(stat -c '%s' "$TARGET_FILE")
echo "├── $z $TARGET_FILE"
if [[ $SUFFIX =~ ^(jpg|jpeg)$ ]]; then
TARGET_FILE="$TARGET_DIR$NAME.avif"
if [ ! -f $TARGET_FILE ]; then
convert $SOURCE_FILE $TARGET_FILE
else
echo "├── Файл avif уже есть"
fi
z=$(stat -c '%s' "$TARGET_FILE")
echo "├── $z $TARGET_FILE"
fi
else
echo "├── пропускаем";
fi
fi
done
Первый раз прогнал его, подправив в поиске время на -mmin +300, а в дальнейшем поставил в крон раз в сутки.
После этого, осталось только внести изменения в настройки веб-сервера Angie (для Nginx всё идентично в данном случае)
# раздача статики
location ~ \.(css|js|gif|webp|avif|jpg|jpeg|jpe|asf|asx|wax|wmv|wmx|avi|avifs|bmp|class|divx|doc|docx|exe|gz|gzip|ico|json|mdb|mid|midi|mov|qt|mp3|m4a|mp4|m4v|mpeg|mpg|mpe|webm|mpp|_otf|odb|odc|odf|odg|odp|ods|odt|ogg|ogv|pdf|png|pot|pps|ppt|pptx|ra|ram|svg|svgz|swf|tar|tif|tiff|_ttf|wav|wma|wri|xla|xls|xlsx|xlt|xlw|zip|ttf|woff|woff2|eot)$ {
expires 300d;
etag on;
if_modified_since exact;
add_header Pragma "public";
add_header Cache-Control "public";
add_header Referrer-Policy "no-referrer-when-downgrade";
# список расширений должен совпадать со списком в скрипте-обработчике
location ~* ^/wp-content/uploads(?<path>.+)\.(jpe?g|png|gif)$ {
add_header Vary Accept;
try_files /<путь к папке>/cache${path}.avif /<путь к папке>/cache{path}.webp $uri /index.php?$args;
}
# необходима для избежания зацикливания в try_files предыдущей location
location /<путь к папке>/cache {
add_header Vary Accept;
}
try_files $uri $uri/ /index.php?$args;
}
Плюсы: работает в том числе и на WordPress, можно не включать конвертированные изображения в бэкап для уменьшения его размеров. При желании можно безболезненно поиграться с водяными знаками, например, или наконвертировать дополнительных размеров для превьюшек.
Минусы: конвертированные копии файлов занимают некоторое место.