KakapoWPKakapoWP
ВходПопробовать
Справочный центр/Performance/Настройка WebP и AVIF

Настройка WebP и AVIF

Относится к: Kakapo Performance·6 мин чтения

Сначала посмотреть, что умеет твой сервер

В разделе «Изображения» стоит карточка «Возможности этого сервера». Она показывает не то, что написано на бумаге, а то, что измерено на работающем PHP: библиотека изображений GD вместе с версией, чтение JPEG, чтение PNG, чтение WebP, запись WebP, запись AVIF. Спрашивается при этом дважды — функция должна существовать, и формат должен стоять в imagetypes(). Это важно, потому что некоторые хостеры собирают GD без WebP или AVIF: imagewebp() тогда имеется и отказывает лишь при вызове.

Если формата нет, соответствующий переключатель остаётся видимым, но выключен и несёт обоснование. Для WebP оно гласит: GD должен быть собран с libwebp. Для AVIF: PHP 8.1 или новее с libavif. И то и другое — дело твоего хостера. Обходной путь через AJAX-вызов не поможет — сервер прямо отклоняет включение недоступного формата.

Строка «Imagick» — чистая информация. Этот модуль Imagick не использует; если там стоит «отсутствует», это ничего не меняет.

Включить и задать три числа

Есть три переключателя и три числовых поля. «Создавать WebP» и «Создавать AVIF» по умолчанию выключены, «Отдавать через <picture>» включено. Разделение сделано намеренно: можно сначала дать файлам появиться, а выдачу подключить позже. И наоборот: если выключить выдачу, файлы продолжают создаваться, но к посетителям уходит неизменённая разметка.

Качество WebP стоит на 82, качество AVIF — на 50. Оба поля принимают значения от 30 до 100, всё выше или ниже обрезается до этого диапазона. Разные значения по умолчанию — не оплошность: AVIF измеряет иначе, чем JPEG, 50 выглядит там уже очень чисто. Выше 90 у WebP файл растёт быстрее, чем видимый выигрыш.

Верхняя граница в мегапикселях стоит на 40 и принимает значения от 4 до 400. Она защищает от лимита памяти: фотография 6000 × 4000 занимает при декодировании около 96 МБ, независимо от того, насколько велик её файл. Кроме того, перед каждым декодированием Kakapo считает против действительно ещё свободной памяти и пропускает файл, вместо того чтобы дать загрузке умереть на пределе.

Если ты меняешь один из трёх переключателей, сохранённый кеш страниц отбрасывается. Качество и предел мегапикселей его не трогают — они действуют лишь при следующей загрузке и не делают неверной ни одну уже сохранённую страницу.

Что происходит при загрузке

Преобразование идёт в конце загрузки, как только WordPress создал все размеры изображения. Обрабатываются файл из метаданных и каждый созданный размер — но не сохранённый ядром оригинал, который всё равно никогда не отдаётся.

Каждый производный файл лежит рядом со своим исходником как сопутствующий и носит его полное имя плюс расширение: из bild.jpg получается bild.jpg.webp, а не bild.webp. Причина: в одной папке могут рядом лежать bild.jpg и bild.png; при простой замене расширения один производный файл затирал бы другой. Если в целевом месте уже что-то лежит, оно не трогается.

Запись идёт сначала в побочный файл, в имени которого стоят номер процесса и случайная часть. Только если он по измерению меньше исходника, он переставляется на своё место через rename. Если он больше или такой же по размеру, он удаляется и остаётся исходник. Поэтому прерванный прогон никогда не оставляет слишком большой производный файл.

У загрузки есть бюджет времени в 12 секунд. AVIF создаётся в разы медленнее, чем WebP, и шесть размеров на два формата иначе упрутся во время выполнения веб-сервера — владелец сайта увидел бы прерванную загрузку. То, что уже не помещается, добирает однократный догоняющий проход: он планируется на 30 секунд позже и имеет тогда 90 секунд. И сделанное, и пропущенное отмечается у вложения, чтобы одна и та же попытка не повторялась при каждом новом создании.

У JPEG поворот из EXIF применяется дополнительно, потому что WebP и AVIF из GD эту запись с собой не несут. Для исходников PNG Kakapo сначала пробует WebP без потерь — логотипы, графика и скриншоты так часто становятся меньше, а края при этом не разлохмачиваются. Прозрачность сохраняется в обоих целевых форматах.

Как происходит выдача

Kakapo заключает <img> в <picture> и ставит перед ним источники AVIF и WebP, сначала AVIF — браузер берёт первый источник, который понимает. Элемент <picture> получает display:contents, чтобы во flex- и grid-раскладках твоей темы он не вставлял в расположение лишний блок.

Сознательный выбор против варианта через .htaccess: согласование содержимого требует правил Apache, на nginx не действует вовсе и конфликтует с промежуточными хранилищами CDN, которые не варьируют заголовок Accept. С <picture> решение принимает браузер, без единой строки серверной конфигурации.

Обрабатываются содержимое записей и изображения записей, с приоритетом 22 — после Lazy-Load (20), перед переписыванием CDN (25), чтобы и вновь возникшие источники шли через CDN. Уже имеющиеся блоки <picture> остаются нетронутыми, как и изображения с чужих хостов и всё за пределами папки uploads.

Одно правило стоит знать: формат предлагается только тогда, когда для самой большой версии в srcset есть производный файл. Если недостаёт средней или маленькой, браузер берёт следующую по величине — на несколько килобайт больше, но никогда не размытое изображение. Если бы недоставало самой большой, широкий экран уже не смог бы выйти на полное разрешение; именно этот случай исключается.

Если ничего не возникает: читать причины

Карточка «Созданные файлы & реальная экономия» показывает по каждому формату число файлов, сумму исходников, сумму производных файлов и разницу. Каждое число берётся из сравнения двух фактических размеров файлов в момент создания — ничего не оценено и не рассчитано приблизительно. «Исходники» — это при этом лишь сумма тех файлов, для которых возник производный файл, а не весь твой медиафонд.

Ниже стоит то, что не было преобразовано, с причиной. Самые важные:

«Результат оказался больше исходника» — это не ошибка. У очень маленьких миниатюр с AVIF это происходит регулярно; исходник остаётся, а остальные размеры всё равно получают свой производный файл.

«Не записывается» — проверить права в папке uploads. Это единственная причина, которая действительно требует твоего вмешательства.

«В целевом месте уже лежал файл» — он не был перезаписан. Обычно он появился при пакетном прогоне по имеющимся файлам и уже является ровно тем, что должно было здесь возникнуть.

«Не поместилось в память» — повысить предел мегапикселей или лимит памяти PHP.

«Не читается» — повреждённый файл, CMYK-JPEG или экзотический вариант. «Не JPEG/PNG/WebP» — анимации GIF и PDF сознательно не трогаются.

Если карточка пуста, включи WebP и загрузи изображение. Изображения, которые уже лежат в медиатеке, так не охватываются — для них есть пакетный прогон ниже на той же странице.

Эта статья оказалась полезной?