WordPress: WebP/AVIF не відображаються — причини й правильне налаштування
December 18, 2025 • February 3, 2026 • Читання: 3 хв • Views: 9
Було корисно?
У медіа-бібліотеці все виглядає нормально. Тема не змінювалася. У HTML сторінки є <img>-теги. І все одно — порожні квадрати, зламані мініатюри або повідомлення «зображення не може бути відображене, бо містить помилки».
Це типовий випадок невідображення WebP/AVIF: файл існує, URL відповідає, але браузер відмовляється його рендерити. Причина зазвичай не в «WordPress» як такому. Це ланцюжок дрібних налаштувань: MIME‑типи, ключі кешу, погодження вмісту, інструменти конвертації і плагін, який став занадто самовпевненим.
Швидкий план діагностики
Якщо у вас є п’ять хвилин до того, як хтось оголосить «критичний інцидент», зробіть це в такому порядку. Мета — швидко знайти вузьке місце: чи відмовляється відображати байти браузер, чи сервер повертає неправильні заголовки, чи CDN кешує неправильний варіант?
Перший крок: підтвердіть, що отримує браузер
Відкрийте DevTools → Network → клікніть по запиту зображення, що не вдалось.
Перевірте Status (200/304/403/404/500), Content-Type, Content-Length та будь-які помилки типу «CORB», «MIME type mismatch» або «Failed to decode image».
Подивіться на вкладку Response: чи це справді зображення, або ж HTML (наприклад сторінка 403, сторінка входу або блок WAF)?
Другий крок: відтворіть за допомогою curl з «чистого» місця
Завантажте URL з заголовками: підтвердіть Content-Type: image/webp або image/avif, а не text/html.
Спробуйте з та без заголовка Accept, щоб виявити проблеми в контент‑неготіації.
Порівняйте відповіді CDN edge та origin.
Третій крок: перевірте ключі кешу та логіку вибору варіантів
Чи CDN враховує Accept при варіюванні кешу? Якщо ні, нещасливий запит може отруїти кеш (AVIF буде подано клієнту без підтримки, або навпаки).
Чи якийсь плагін WordPress переписує URL на .webp/.avif, не перевіривши, що файли існують?
Чи сервер надсилає неправильний Content-Type для .webp/.avif?
Четвертий крок: тільки тоді торкайтеся WordPress
Перевірте згенерований HTML: src, srcset, порядок picture/source.
Перегляньте плагіни, що займаються конвертацією, lazy-load, CDN offload та кеш/мінімізацією. Вимикайте по одному.
Переконайтеся, що файли дійсно існують там, де WordPress вважає (wp-content/uploads або віддалене сховище).
Що фактично ламається, коли WebP/AVIF не відображаються
Браузери толерантні до багатьох речей. Декодування зображень — не одна з них. Коли зображення «не відображається», зазвичай це одна з чотирьох категорій:
Неправильні байти: URL закінчується на .webp, але повертаються байти JPEG (або HTML). Деякі браузери пробують відкрити, більшість відмовляється.
Неправильні заголовки: Байти коректні, але Content-Type неправильний (наприклад text/plain), що викликає жорстку поведінку або ламає проміжні ланки.
Неправильний варіант: CDN кешує AVIF і віддає його клієнту, що підтримує лише WebP/JPEG, бо ключ кешу ігнорує Accept.
Неправильний HTML: Розмітка вказує напряму на .avif без запасного варіанту, або плагін пошкодив srcset.
Є також «п’ята категорія»: у вас WAF або захист від гарячих посилань, що блокує запити без Referer, і ваш плагін оптимізації отримує зображення так, що тригерить правило. Продукти безпеки люблять бути такими «корисними».
Цитата, яку варто мати на стікері, бо вона стосується кожної з цих відмов: «Сподівання — не план». Ви не вгадаєте шлях до вирішення; ви будете спостерігати і підтверджувати.
Факти та коротка історія, що допоможуть в налагодженні
Це не тривіальні відомості для вікторини. Вони пояснюють, чому ваш стек поводиться саме так.
WebP з’явився від Google у 2010 як формат на основі VP8; ранні прогалини в підтримці породили роки уявлень «працює в Chrome».
AVIF базується на AV1 (відеокодек). Статичні зображення успадковують ефективність і складність стиснення AV1, що важливо для CPU і часу конвертації.
Підтримка WebP в Safari з’явилася пізніше (Safari 14). Багато старих налаштувань WordPress все ще мають «якщо Safari — то JPEG» як мінні поля.
Підтримка AVIF ще новіша і фрагментованіша; деякі браузери підтримують, деякі мають часткові або багаті декодери, а у корпоративних середовищах браузери можуть бути зафіксовані версіями.
Подача сучасних форматів часто робиться через контент‑неготіацію з використанням заголовка Accept, що ламається ефектно, якщо кеші не варіюють правильно.
WordPress історично обмежував типи завантажень; сучасні версії підтримують WebP, але серверні бібліотеки (GD/Imagick) можуть не підтримувати відповідні формати.
CDN можуть «допомагати» авто-конвертацією зображень, але це може конфліктувати з плагінами WordPress, що роблять те ж саме, призводячи до подвійної оптимізації або неправильних варіантів.
AVIF може бути меншим за WebP, але повільніший в кодуванні. Команди часто виявляють це під час розгортання. Невдалий таймінг — це теж формат.
Багато інцидентів із зламаними зображеннями — насправді HTML-помилки, що повертаються зі статусом 200; браузер отримує «зображення», а насправді це сторінка входу.
Жарт #1: WebP не є «захищеним від вебу». Якби був, ми б не тут, і я би писав про щось заспокійливе — наприклад, BGP.
Режими відмов: браузер, сервер, CDN, WordPress
1) Відмова на боці браузера: помилка декодування або ненадійна підтримка формату
Якщо ви жорстко прописали .avif у <img src> без запасного варіанту, браузер без підтримки AVIF не понизить формат самостійно. Він просто нічого не покаже. Правильний шаблон — це <picture> з впорядкованими елементами <source type>, і фінальним <img> як запасним варіантом.
Ще одна помилка на стороні браузера: пошкоджені файли. Це трапляється, коли конвертація перервалася, або плагін записав частковий вивід та все одно оновив метадані.
2) Відмова на боці сервера: неправильні MIME‑типи, відсутні модулі, погані правила перепису
Подача WebP/AVIF не складна, але легко зробити помилку, яка виглядає правильним на перший погляд.
Відсутній MIME‑тип: Сервер повертає application/octet-stream або text/plain. Деякі браузери все одно рендерять; деякі проміжні вузли — ні.
Перепис правил надто «хитрі»: Ви безумовно переписуєте .jpg на .webp. Якщо .webp не існує, ви отримуєте 404 по всьому сайту.
Обробка статичних файлів через PHP: Неправильно налаштований блок location відсилає .webp через PHP (повільно) або блокує його через правила безпеки.
3) Відмова CDN: отруєння кешу через невідповідність варіантів
Це велика проблема. Origin робить правильно: якщо Accept містить image/avif, повертає AVIF; інакше WebP; інакше JPEG. Але CDN кешує першу відповідь під ключем тільки URL. Наступний клієнт отримує закешований AVIF, навіть якщо його браузер не підтримує AVIF. Бум: зламані зображення, але тільки для деяких користувачів і тільки іноді. Ідеально для витрат часу.
4) Відмова WordPress: плагіни переписують URL та метадані
WordPress за замовчуванням не робить повної контент‑неготіації для сучасних форматів. Більшість сайтів покладаються на плагін або CDN‑функцію. Плагіни значно різняться за якістю. Типові точки поломки:
Вони генерують .webp/.avif, але не оновлюють srcset коректно.
Оновлюють посилання в БД, але не регенерують мініатюри.
Не враховують віддалене сховище (S3‑сумісне) і створюють локальні шляхи, які ніколи не існуватимуть.
Конфліктують з кеш/мінімізуючими плагінами, що перевиписують HTML пізніше.
Практичні завдання (команди, виходи, рішення)
Нижче — реальні перевірки, які ви можете виконати. Кожна включає: команду, вихід, який важливий, і наступне рішення. Виконуйте їх із shell сервера (або на ноутбуці для перевірок curl). Не «міняйте речі, щоб подивитися, чи допоможе». Спочатку спостерігайте.
Завдання 1: Підтвердіть, що URL, що падає, повертає реальне зображення (не HTML)
Що це означає: Статус 200 і content-type відповідає AVIF. Добрий знак.
Рішення: Якщо content-type — text/html або файл дуже маленький (1–5 KB), відкрийте тіло відповіді: ймовірно це сторінка помилки, блок WAF або ланцюг редиректів.
Завдання 2: Визначте тип файлу по магічних байтах (не довіряйте розширенням)
cr0x@server:~$ file -b /tmp/img.bin
ISO Media, AVIF Image
Що це означає: Байти справді AVIF.
Рішення: Якщо вивід говорить «HTML document» або «JPEG image data», у вас плутанина між переписами/CDN/origin. Виправте це перед тим, як торкатися WordPress.
Завдання 3: Перевірте, що відбувається для клієнтів без підтримки AVIF/WebP
Що це означає: Сервер веде переговори і повертає JPEG, і ставить Vary: Accept. Це бажано.
Рішення: Якщо Vary: Accept відсутній, ваш CDN може кешувати неправильний варіант, якщо ви не налаштуєте його явно. Додайте Vary і переконайтеся, що CDN його дотримується (або використовуйте різні URL‑и для форматів).
Завдання 4: Порівняйте заголовки edge CDN vs origin
Що це означає: CDN віддає AVIF з кешу (HIT), і Vary присутній.
Рішення: Якщо edge відповідає інакше, ніж origin (неправильний content-type, відсутній vary), почистіть CDN і виправте ключ кешу / обробку vary. Не робіть очищення кешу звичкою.
Завдання 5: Перевірте, що nginx знає MIME‑типи для WebP/AVIF
Що це означає: Apache має потрібні модулі для AddType і Header правил.
Рішення: Якщо mime_module відсутній, Apache може неправильно віддавати невідомі типи. Увімкніть його, потім додайте AddType image/webp .webp і AddType image/avif .avif.
Завдання 7: Перевірте, чи сервер випадково не стиснув зображення gzip
Що це означає: Немає Content-Encoding: gzip (добре). Стискати вже стиснуті формати марно і іноді шкідливо з багатьма проміжними вузлами.
Рішення: Якщо ви бачите content-encoding: gzip для зображень, виправте правила стиснення, щоб виключити image/* (особливо WebP/AVIF).
Завдання 8: Підтвердіть, що файл існує на диску (перевірка origin)
cr0x@server:~$ sudo ls -lh /var/www/html/wp-content/uploads/2025/11/hero.avif
-rw-r--r-- 1 www-data www-data 48K Nov 20 09:14 /var/www/html/wp-content/uploads/2025/11/hero.avif
Що це означає: Origin має файл, права виглядають нормально.
Рішення: Якщо він відсутній, плагін ніколи не згенерував його, або ви відклали медіа в offload і забули, що файловий простір origin не є джерелом правди.
Завдання 9: Виявлення часткових/пошкоджених конверсій за допомогою ffmpeg або avifdec
Що це означає: Відсутність виводу означає, що ffmpeg зміг розпарсити і декодувати файл без помилок.
Рішення: Якщо бачите помилки декодування, перевідтворіть цей ресурс і дослідіть ваш конвертер (CPU/пам’ять/тайм‑аути).
Завдання 10: Перевірте, чи WordPress вважає метадані вкладення коректними
cr0x@server:~$ wp post meta get 123 _wp_attachment_metadata --format=json | head -c 220; echo
{"width":2400,"height":1600,"file":"2025/11/hero.jpg","sizes":{"thumbnail":{"file":"hero-150x150.jpg","width":150,"height":150,"mime-type":"image/jpeg"}...
Що це означає: Метадані WordPress посилаються на оригінал JPEG і його похідні розміри. Багато плагінів зберігають WebP/AVIF окремо.
Рішення: Якщо метадані посилаються на .webp/.avif, але файли не існують (або навпаки), у вас невідповідність. Перегенеруйте мініатюри та повторно запустіть «bulk optimize» плагіна з правильними налаштуваннями.
Завдання 11: Проскануйте згенерований HTML на наявність picture, srcset і порядку
Що це означає: Це коректно: AVIF перший, WebP другий, JPEG як запасний.
Рішення: Якщо ви бачите <img src="...avif"> без запасного варіанту, виправте тему/плагін. Якщо type неправильний або відсутній, деякі браузери не оберуть джерело.
Завдання 12: Виявлення «заблоковано WAF/захистом від гарячих посилань», що маскується під зображення
Що це означає: 403 з HTML‑тілом. Браузер запитав зображення, отримав сторінку відмови.
Рішення: Налаштуйте правила WAF, захист від гарячих посилань або логіку підписаних URL так, щоб легітимні запити на зображення дозволялися. Також переконайтеся, що ваш оптимайзер не отримує зображення з дивними заголовками, які викликають блокування.
Завдання 13: Переконайтеся, що CDN/origin повертають коректний Content-Length і підтримують range-запити
Що це означає: Range‑запити працюють. Це важливо для деяких клієнтів, проміжних вузлів і поведінки продуктивності.
Рішення: Якщо range не працюють, а ваш CDN очікує їх, ви можете отримувати часткові завантаження або дивну поведінку клієнтів. Виправте обробку статичних файлів і налаштування проксі.
Завдання 14: Підтвердіть підтримку конвертації у бібліотеках PHP (GD/Imagick)
cr0x@server:~$ php -r 'print_r(function_exists("gd_info")?gd_info():["gd"=>"missing"]);' | egrep -i 'WebP Support|AVIF Support|JPEG Support'
WebP Support => 1
AVIF Support => 0
JPEG Support => 1
Що це означає: GD може записувати WebP, але не AVIF. Багато плагінів WordPress тихо відколупуються або генерують лише деякі формати.
Рішення: Якщо вам потрібен AVIF, використовуйте конвертер з підтримкою (часто через Imagick з libheif або зовнішні інструменти), або делегуйте конвертацію CDN і зберігайте origin як JPEG/PNG/WebP.
Завдання 15: Перевірте підтримку кодеків в Imagick
Що це означає: Imagick на цьому хості підтримує AVIF і WebP. Це привід тихо відсвяткувати.
Рішення: Якщо AVIF відсутній, ви можете встановити/збірку Imagick з libheif, або перестати обіцяти AVIF від origin і використовувати WebP + JPEG як запасний варіант.
Завдання 16: Перевірте наявність правил перепису, що примушують .webp навіть коли він відсутній
Що це означає: Цей rewrite безумовний. Якщо hero.webp не існує, ви отримаєте 404.
Рішення: Замість переписів використовуйте логіку try_files, що перевіряє наявність файлу і коректно відпадає назад.
Правильна конфігурація: розумна, нудна, надійна
Ви хочете сучасні формати без драм. Ось конфігурація, що переживе трафік, CDN та оновлення плагінів.
Принцип 1: Віддавайте перевагу <picture> замість перепису URL
Якщо ви контролюєте генерацію розмітки (рівень теми або добросовісний плагін), використовуйте:
<source type="image/avif"> першим
<source type="image/webp"> другим
<img src="...jpg/png"> як запасний
Це уникає складності ключів кешу, бо різні формати мають різні URL. Це не так «хитро», і в цьому його сенс.
Принцип 2: Якщо робите контент‑неготіацію, ставте кешування у пріоритет
Контент‑неготіація означає один URL, різні байти. Це працює лише коли:
Origin надсилає Vary: Accept
CDN кешує окремо по Accept (або ви налаштували різні ключі кешу)
У вас є стратегія очищення при зміні налаштувань конвертації
Без цього неготіація перетворюється на «лотерею випадкових зображень».
Принцип 3: Не вимагайте AVIF, якщо не можете його надійно виробляти
AVIF чудовий. Він також вимогливий до середовища: потрібні правильні бібліотеки, а кодування витратне по CPU. Якщо ви не можете гарантувати завершення конвертації та коректні заголовки, спочатку використовуйте WebP і трактуйте AVIF як опціональний.
Конфігурація сервера: nginx (мінімально, але правильно)
Переконайтеся, що nginx знає MIME‑типи. У вашому mime.types або блоці http:
Якщо потрібно мапити JPEG/PNG на WebP коли доступний, робіть це з try_files, а не безумовним rewrite. Приклад (концептуальний; адаптуйте уважно під свої шляхи):
cr0x@server:~$ sudo nginx -T 2>/dev/null | sed -n '180,260p'
location ~* \.(png|jpe?g)$ {
add_header Vary Accept;
set $webp_suffix "";
if ($http_accept ~* "image/webp") {
set $webp_suffix ".webp";
}
try_files $uri$webp_suffix $uri =404;
}
Чому це працює: Він віддає .webp лише якщо він існує. Інакше віддає оригінал. Ніяких 404‑штормів.
Конфігурація сервера: Apache (мінімально, але правильно)
Визначте MIME‑типи і переконайтеся, що модуль headers доступний. В Apache конфіг або .htaccess (якщо дозволено):
cr0x@server:~$ sudo apachectl -t -D DUMP_INCLUDES 2>/dev/null | head
Included configuration files:
(/etc/apache2/apache2.conf)
(/etc/apache2/conf-enabled/*.conf)
(/etc/apache2/sites-enabled/000-default.conf)
Налаштування WordPress: вирішіть, хто відповідає за конвертацію
Є три життєздатні моделі відповідальності. Виберіть одну і дотримуйтеся. Мішання створює привидні баги.
Плагін відповідає за конвертацію, origin віддає статичні сучасні формати: Найпоширеніше. Працює, якщо на сервері є бібліотеки і ви керуєте інвалідацією кешу.
CDN відповідає за конвертацію: Origin зберігає JPEG/PNG, CDN віддає WebP/AVIF клієнтам, які їх підтримують. Менше навантаження на сервери, менше проблем з бібліотеками. Вимагає дисципліни в налаштуванні CDN.
Пайплайн збірки відповідає за конвертацію: Ви конвертуєте зображення до завантаження/деплойменту. Чудово для контрольованих сайтів, менш зручно для генерації контенту користувачами.
Виберіть стратегію відкату і протестуйте її, як ніби від неї залежить production (бо так і є)
Мінімально прийнятна поведінка:
Будь‑який клієнт отримує зображення (хіба що JPEG/PNG як крайній варіант).
Жоден плагін не повинен замінювати єдиний URL на AVIF без запасного варіанту.
Пошкоджена конвертація не повинна ламати існуючі сторінки (під час обробки служіть старий формат).
Жарт #2: Єдине «безвтратне» в оптимізації зображень — це ваше терпіння, коли ключ кешу ігнорує Accept.
Типові помилки (симптом → корінна причина → виправлення)
1) Симптом: Зламані зображення лише в Safari або на старих пристроях
Корінна причина: Ви віддаєте AVIF (або WebP) без запасного варіанта, або CDN закешував AVIF і віддає його всім.
Виправлення: Використовуйте <picture> з JPEG‑запасним, або забезпечте Vary: Accept і налаштуйте CDN на варіацію по Accept. Очистіть кеш після змін.
2) Симптом: DevTools показує 200 OK, але зображення порожнє
Корінна причина: Тіло відповіді не є зображенням (HTML‑сторінка відмови, блок WAF або «soft 404»), яка повертається з 200 або 403.
Виправлення: Завантажте з curl і перевірте Content-Type та магічні байти. Виправте правила WAF/захист від гарячих посилань; переконайтеся, що статичні шляхи обходять автентифікацію і виклики безпеки.
3) Симптом: Деякі користувачі бачать зображення, інші — зламані іконки; очищення кешів «вирішує» тимчасово
Корінна причина: Отруєння кешу CDN через відсутність vary/правильного ключа кешування. Перший запит виграє.
Виправлення: Налаштуйте CDN на варіацію по Accept (або використайте окремі URL для форматів). Переконайтеся, що origin ставить Vary: Accept. Очистіть уражені об’єкти.
4) Симптом: 404 для .webp після включення плагіна оптимізації
Корінна причина: Плагін переписав URL на .webp, але не згенерував ці файли (або збоїв під час партії).
Виправлення: Вимкніть переписування URL, запустіть масову генерацію, підтвердіть цільові шляхи файлової системи/оффлоаду, потім знову увімкніть. Додайте безпечний серверний try_files fallback, якщо наполягаєте на переписах.
5) Симптом: Зображення завантажуються замість відображення
Корінна причина: Неправильний Content-Type, іноді application/octet-stream.
Виправлення: Додайте правильні MIME‑типи в nginx/Apache. Перевірте заголовки. Деякі CDN також потребують явного мапінгу типів.
6) Симптом: Зламані мініатюри, але оригінали завантажуються
Корінна причина: Похідні розміри не були конвертовані/перегенеровані; srcset посилається на варіанти, яких не існує.
Виправлення: Перегенеруйте мініатюри; повторно прогоніть конвертер для всіх розмірів; перевірте метадані для прикладу вкладення.
7) Симптом: Високі сплески CPU при увімкненні AVIF; сторінки таймаутяться
Корінна причина: Конвертація виконується під час запитів або пакетні роботи виснажують хост. Кодування AVIF вимогливе.
Виправлення: Виконуйте офлайн/пакетну конвертацію з обмеженнями; використовуйте черги й воркери; або делегуйте конвертацію CDN. Встановіть жорсткі ліміти на паралельні кодування.
8) Симптом: Лише адміністратор бачить коректні зображення; незалоговані користувачі — ні
Корінна причина: Кеш варіюється по куках/авторизації, або плагін оптимізації обходить конвертацію для авторизованих, або CDN віддає різні варіанти.
Виправлення: Порівняйте відповіді з куками і без. Виправте правила кешування і забезпечте той самий URL для анонімного трафіку.
Контрольні списки / покроковий план
Покроково: дійдіть до коректної бази (без героїзму)
Виберіть власника: плагін, CDN або пайплайн збірки. Не запускайте два конвертери одночасно.
Встановіть запасну розмітку: віддавайте перевагу <picture> з JPEG/PNG запасним.
Виправте MIME‑типи: переконайтеся, що image/webp та image/avif коректні на origin і в CDN.
Підтвердіть, що байти відповідають заголовкам:file проти завантаженого контенту; жодних HTML‑сторінок помилок.
Виправте варіацію кешу: якщо ви ведете переговори через Accept, origin має ставити Vary: Accept і CDN має варіювати кеш.
Перегенеруйте похідні: мініатюри і responsive‑розміри — там ховається мовчазна поломка.
Протестуйте робочий процес конвертації під навантаженням: AVIF‑кодування може наситити CPU. Плануйте, куди йде навантаження.
Налаштуйте моніторинг: відслідковуйте рівні 404/403 на .webp/.avif, слідкуйте за mismatch‑ами Content-Type, якщо можете.
Чекліст релізу для ввімкнення AVIF/WebP у продакшені
Тестування принаймні трьома профілями браузерів: AVIF‑сумісний, лише WebP, і ні один (примусова перевірка заголовка Accept).
Перевірено ключ кешу CDN щодо поведінки варіантів, або використано окремі URL для форматів.
Origin повертає коректні MIME‑типи і не gzip‑ить зображення.
Конвертаційні завдання виконуються поза шляхом запитів або строго лімітовані.
План відкату: вимкнути перепис/неготіацію без ламання URL зображень.
Коли щось зламалося: чекліст стримування
Зупиніть витік: вимкніть перепис URL, що примушує .avif/.webp, якщо файли не гарантовані.
Очищуйте кеш CDN тільки для уражених шляхів (не робіть carpet‑bomb, якщо не любите самостійні відключення).
Поверніться до запасної розмітки JPEG/PNG, якщо тема/плагін це підтримує.
Переконайтеся, що відповіді 200 — це реальні зображення (не HTML).
Три корпоративні історії з практики
Міні‑історія 1: Інцидент через невірне припущення
Середній e‑commerce сайт захотів «сучасні зображення скрізь». План звучав просто: увімкнути AVIF‑конвертацію в плагіні оптимізації, включити nginx‑переписи щоб .jpg став .avif для сумісних браузерів, а потім дати CDN робити свою звичну роботу.
Хтось припустив, що CDN автоматично варіює кеш по Accept. Ні — принаймні для того правила кешування він цього не робив. Перший запит після деплою прийшов від Chrome з підтримкою AVIF. CDN закешував AVIF‑відповідь під URL‑ом JPEG.
Наступний хвилі трафіку включали вбудовані браузери мобільних додатків і старі пристрої. Вони попросили той самий JPEG‑URL, отримали AVIF‑байти і не змогли декодувати. Дошка інцидентів показувала «помилки завантаження зображень», але стан origin був зеленим. Бо, звісно, був.
Фікс не був магічним: налаштували варіацію кешу правильно (або перестали вести переговори на тому самому URL), очистили отруєні об’єкти і додали тест, що робить curl для набору image URL з різними Accept заголовками перед кожним релізом. Урок не в тому, щоб не використовувати AVIF. Урок — не віддавати припущення кешу на відкуп.
Міні‑історія 2: Оптимізація, що вдарила по продуктивності
Внутрішня платформа комунікацій виросла настільки, що зберігання медіа стало значною статтею витрат. Хтось запропонував агресивний AVIF для всього, з on‑demand конвертацією: коли користувач вперше переглядає сторінку, сервер конвертує відсутні AVIF‑варіанти і кешує їх. Це начебто «розтягне роботу».
Вона розтягла — але на веб‑шари під час піку. Бібліотека конвертації була вимоглива до CPU. Запити стали чекати. PHP‑воркери зависли у очікуванні конвертацій і записів у файлову систему. Затримки зросли, потім тайм‑аути, а кеш шар почав повторювати запити upstream, що ніколи не закінчується добре.
Гірше, деякі конверсії переривалися. Часткові файли записалися, але оновлення метаданих пройшло. Декілька користувачів отримали корумповані AVIF з правильним Content-Type. Це найнеприємніші відмови, бо вони виглядають «правильно», доки не декодуєш байти.
Відкат був простим: припинити on‑demand конвертацію, перемістити конвертацію в керовану чергу з обмеженнями на конкуренцію і віддавати WebP/JPEG, поки варіанти готуються. Економія диску повернулася, але система припинила намагатися підпалити себе задля кількох кілобайт.
Міні‑історія 3: Нудна практика, що врятувала день
Видавнича компанія керувала кількома WordPress‑властивостями за одним CDN. У них було правило, що звучало болісно нецікаво: кожен новий тип активу отримує «тест контракту заголовків» в CI. Він перевіряє коди статусу, Content-Type, Cache-Control і поведінку варіантів з різними Accept заголовками.
Коли вони додали WebP, а потім AVIF, вони не просто натиснули перемикач плагіна і молилися. Вони деплоїли на staging‑домен, що використовував ту саму конфігурацію CDN, що й production. CI‑джоб забирав набір канонічних зображень через CDN і напряму з origin, порівнював заголовки і падав збірку, якщо вони розходилися.
Перший AVIF‑тест упав: CDN прибрав Vary: Accept на одному шляховому правилі кешу. У ручному тестуванні ніхто цього не помітив, бо їхні браузери були сучасні. Тест помітив, бо змусив Accept, що виключає AVIF, і очікував JPEG‑запасний.
Вони виправили правило CDN до того, як це побачили користувачі. Нічого не вибухнуло. Ніхто не отримав виклику. Ось що купує вам «нудна» практика: сон і довіру.
Питання та відповіді (FAQ)
1) Чи варто подавати AVIF, WebP, або обидва?
Обидва, якщо ви можете це робити надійно. AVIF першим для сумісних клієнтів, WebP другим, JPEG/PNG як запасний. Якщо ваш сервер не може стабільно кодувати AVIF, подавайте WebP + JPEG і робіть AVIF опціональним (часто CDN‑сторона — компроміс).
2) Чому я отримую 200 OK, але зображення все одно не показується?
Бо «200» — це не обіцянка, що байти — це зображення. Перевірте Content-Type і подивіться тіло відповіді. Сторінка входу з кодом 200 для URL зображення все одно буде зламаним зображенням.
3) Чи потрібно додавати MIME‑типи для WebP і AVIF?
Так. Багато серверів не вгадають правильно. Потрібні image/webp і image/avif. Неправильні MIME‑типи можуть викликати завантаження файлу, блокування рендерингу або дивну поведінку CDN.
4) Чи можна покладатися тільки на плагін WordPress?
Можна, але перевіряйте весь ланцюжок: підтримку інструментів конвертації (GD/Imagick), перегенерацію мініатюр і як плагін переписує HTML/URL. Плагіни часто працюють ідеально, доки ви не додасте CDN, оффлоад медіа або інший «корисний» оптимайзер.
5) Який найнадійніший спосіб впровадити сучасні формати у WordPress?
Використовуйте <picture> і різні URL для форматів. Це уникає складності варіації кешу. Якщо потрібна неготіація, розглядайте Vary: Accept і ключі кешу як беззастережні вимоги.
6) Мій CDN каже, що автоматично підтримує WebP/AVIF. Чому зображення ламаються?
Тому що «підтримує» може означати «може конвертувати», але не «варіює кеш правильно для ваших правил». Підтвердіть поведінку ключа кешу, перевірте Vary: Accept, і дізнайтеся, чи origin вже робить конвертацію — подвійна оптимізація і плутанина варіантів — часті причини.
7) Чому лише мініатюри ламаються?
Тому що мініатюри — це окремі файли. Оригінал міг бути конвертований, а похідні розміри, що використовуються в srcset, — ні або були збережені в іншому місці (особливо при offload).
8) Чи AVIF завжди менший за WebP?
Часто, але не завжди. Залежить від контенту. AVIF добре для фотознімків, але може бути повільнішим у кодуванні і не завжди виправдовуєся для дрібних UI‑зображень. Вимірюйте; не припускайте.
9) Чому увімкнення AVIF спричинило сплески CPU і уповільнення сайту?
Бо кодування витратне. Якщо конвертація відбувається в запиті, ви поклали на веб‑шар відеокодек‑рівень навантаження. Перенесіть конвертацію в фон, обмежте конкуренцію або делегуйте CDN.
10) Чи потрібно очищати кеш після ввімкнення WebP/AVIF?
Зазвичай так — особливо якщо ви змінили правила перепису, неготіації або поведінку CDN. Інакше ви ризикуєте подавати застарілі варіанти або тримати отруєні об’єкти в кеші довше, ніж вам подобається.
Наступні кроки, які можна виконати сьогодні
Якщо WebP/AVIF зображення не відображаються, не починайте з перевстановлення плагінів. Почніть з підтвердження, які байти повертаються, з якими заголовками і хто їх кешує.
Візьміть один неробочий URL і виконайте перевірки curl + file. Підтвердіть: статус, Content-Type і магічні байти узгоджуються.
Якщо ви використовуєте контент‑неготіацію, перевірте Vary: Accept і поведінку ключа кешу CDN. Якщо не можете цього гарантувати — перейдіть на <picture> з окремими URL для форматів.
Перевірте MIME‑типи сервера для .webp і .avif. Виправте їх на origin; не покладайтеся на «CDN все вирішить».
Аудитуйте плагіни WordPress: один конвертер, один переписувач HTML, один плагін кешування (або принаймні один, що «відповідає»). Все інше — змагання, хто останній зламає розмітку.
Перегенеруйте мініатюри і перевірте srcset для декількох репрезентативних вкладень.
Сучасні формати того варті. Просто не впроваджуйте їх як фокус трюку. Робіть це як оператор: спостережувана поведінка, безпечні запасні варіанти і кеші, які налаштовані — а не надіяні.