Хотите ускорить сайт на вашем VPS без переписывания шаблонов? Рассказываем, как научить Nginx сам выбирать лучший формат картинок — AVIF, WebP или оригинал — в зависимости от браузера.
Введение
Изобилие картинок на сайте — настоящее испытание для скорости загрузки. Каждый дополнительный мегабайт изображений замедляет работу страницы, отпугивает посетителей и ухудшает показатели Core Web Vitals. Современные форматы WebP и AVIF позволяют существенно уменьшить размер файлов без потери качества, но как внедрить их поддержку на своём сервере без тотальной переделки всего HTML-кода?
В статье рассказали, как включить поддержку форматов WebP и AVIF на сервере и настроить Nginx для автоматической обработки изображений.
Чем так хороши форматы WebP и AVIF
WebP — формат изображений от Google, появившийся уже более десяти лет назад. Он поддерживает как сжатие с потерями, так и без, умеет работать с прозрачностью и при этом выдаёт файлы ощутимо меньше по размеру, чем JPEG или PNG.
AVIF — более новый формат на основе кодека AV1. Он сжимает ещё сильнее. При похожем качестве картинки AVIF-файл может весить на десятки процентов меньше, чем даже WebP. Оба формата уже поддерживаются основными браузерами.
Зачастую использование WebP/AVIF на сайте требует изменить HTML-код, например, вставлять теги <picture> с разными версиями картинок или подключать специальные скрипты. Для пары изображений это ещё ничего, а если их тысячи? Если переписывать шаблоны, следить, чтобы у каждой картинки были альтернативы, можно легко запутаться и ошибиться. К тому же в некоторых CMS добавление новых форматов может быть ограничено. Однако есть альтернативный подход: настроить веб-сервер так, чтобы он сам подменял изображения на лету в зависимости от возможностей браузера.
Nginx не занимается конвертацией изображений, он может только выбрать нужный файл и отдать его, поэтому создайте версии изображений в WebP и AVIF заранее. Вы можете воспользоваться утилитами либо онлайн-конвертерами и плагинами к вашему движку сайта. Важно сохранить структуру и имена, например, для image.jpg делаете image.webp и image.avif.
Добавление MIME-типов WebP и AVIF в конфигурацию
Чтобы Nginx начал обслуживать файлы с расширениями .webp и .avif, он должен знать о типе этих данных. Обычно в конфигурации присутствует файл mime.types, где перечислены все поддерживаемые форматы. Откройте его (как правило, /etc/nginx/mime.types) и проверьте, есть ли там строки для WebP и AVIF. В свежих версиях Nginx WebP может быть прописан, а AVIF до недавнего времени отсутствовал. Если их нет, добавьте вручную, например:
image/webp webp;
image/avif avif;
Сохраните изменения. Теперь при отдаче .webp или .avif сервер будет посылать правильный заголовок Content-Type, и браузер поймёт, что получил изображение. Казалось бы, мелочь, а без этого двигаться дальше нельзя.
Проверка возможностей браузера через заголовок Accept
Самое интересное начинается здесь. Когда браузер запрашивает картинку, он отправляет заголовок Accept — список форматов, которые умеет отображать. Вам нужно выхватить оттуда упоминания WebP и AVIF. К счастью, Nginx позволяет на лету анализировать заголовки и сохранять результаты в переменные. Нужно создать две переменные, где одна будет отвечать за WebP, а вторая за AVIF. Откройте основной конфиг Nginx и в секции http { ... } добавьте следующие директивы map:
map $http_accept $webp_suffix {
default "";
"~image/webp" ".webp";
}
map $http_accept $avif_suffix {
default "";
"~image/avif" ".avif";
}
Эти конструкции создают переменные $webp_suffix и $avif_suffix в контексте http. Если в заголовке Accept обнаружится строка "image/webp", то $webp_suffix будет равна ".webp", иначе останется пустой. Аналогично для $avif_suffix при наличии "image/avif".
Директива map должна находиться именно в блоке http{} глобальной конфигурации. Если попытаться вставить её внутрь server{} или location{}, Nginx не запустится. Поэтому перепроверьте, в правильное ли место вы добавили код.
Правило раздачи изображений с помощью try_files
Теперь перейдём непосредственно к разделу сайта, где нужно применять правило. Откройте конфигурацию вашего сайта. Вам потребуется добавить новый блок location, который перехватит запросы картинок и попытается подменить их на более современный формат. Например:
server {
…
location ~* \.(?:jpe?g|png)$ {
add_header Vary Accept;
try_files $uri$avif_suffix $uri$webp_suffix $uri =404;
}
…
}
Здесь задаётся блок location с регулярным выражением для изображений .jpg, .jpeg и .png. Ключ ~* делает правило нечувствительным к регистру.
add_header Vary Accept; добавляет заголовок Vary: Accept к ответам с картинками. Это важно для корректного кеширования. CDN или прокси понимают, что разные браузеры требуют разные версии файла. Например, Chrome может запросить WebP, а Safari нет, и благодаря этому заголовку они не получат неверный вариант из кеша.
try_files $uri$avif_suffix $uri$webp_suffix $uri =404;
Это директива, которая по очереди проверяет, какой файл отдать:
- $uri$avif_suffix — сначала ищется вариант с суффиксом .avif, например, picture.jpg.avif.
- $uri$webp_suffix — если AVIF нет или не поддерживается, пробуется .webp, например, picture.jpg.webp.
- $uri — отдаётся исходный файл (JPEG/PNG).
- =404 — если ничего не найдено, возвращается ошибка 404.
Так Nginx автоматически выбирает подходящий формат: AVIF при поддержке, WebP как запасной вариант и оригинал в крайнем случае.
После добавления блока сохраните конфигурацию и проверьте, чтобы не было дублирующих location для картинок, новый блок должен иметь приоритет.
Перезапуск и проверка
Когда новые параметры внесены, перезапустите Nginx, чтобы они вступили в силу:
sudo systemctl restart nginx
Если всё сделано правильно, сервер запустится без ошибок. Теперь нужно протестировать. Самый простой способ — открыть сайт в разных браузерах и посмотреть, какие файлы они получают. В Chrome или другом Chromium-браузере, который поддерживает и WebP, и AVIF, зайдите на страницу с картинками и откройте инструменты разработчика (F12). В разделе Network найдите запрос изображения и посмотрите, что вернулось. В идеале Content-Type ответа будет image/avif. Можно увидеть и имя файла, если взглянуть в логи сервера или временно добавить в конфиг отладочный заголовок. Например, для проверки вы можете ненадолго вставить строку внутри того же location:
add_header X-Debug-Files "$uri$avif_suffix | $uri$webp_suffix";
Она покажет в ответе, какие пути проверялись. Но не забывайте удалить её после тестов. Затем откройте тот же URL изображения в браузере без поддержки AVIF, но с поддержкой WebP, например, Safari 14 или Edge старых версий. Там в DevTools должен прийти Content-Type: image/webp. Наконец, попробуйте совсем старый браузер, не умеющий ни WebP, ни AVIF, или временно отключите их поддержку. Сервер должен вернуться к Content-Type: image/jpeg или image/png. Если так, значит, всё работает как задумано, и каждый получает то, что сможет отобразить.
Важные замечания
Убедитесь, что у вас действительно созданы альтернативные файлы изображений. Nginx не генерирует WebP/AVIF автоматически. Если каких-то файлов нет, сервер просто отдаст оригинал. Для полноценного эффекта стоит конвертировать все важные картинки на сайте. Начните хотя бы с тех, что весят больше всего или встречаются на каждой странице.
Помните про обновление контента. Если контент-менеджеры или редакторы будут загружать новые изображения, нужно позаботиться об их конвертации. Можно настроить скрипт, который при загрузке jpg/png сразу делает копии в WebP и AVIF. В некоторых CMS это решается плагинами. Например, для WordPress существуют плагины, автоматически создающие WebP-версии и дающие инструкции для Nginx. Наш подход универсален и подходит для любого сайта, но автоматизация генерации изображений значительно упростит жизнь в продакшене.
На виртуальном хостинге реализовать подобную схему не выйдет. Дело в том, что на большинстве шаред-хостингов Nginx либо недоступен для изменения, либо работает в паре с Apache, где статику раздаёт фронтенд Nginx без возможности правки конфигов. Наше решение рассчитано на виртуальные серверы и VPS с полноценным доступом к настройкам. Если вы используете собственный сервер, проблем нет. Если же сайт размещён на тарифе без доступа к nginx.conf, стоит задуматься об изменении хостинга или перейти на VPS, где сможете внедрять такие оптимизации.
Заключение
Теперь Nginx сам распределяет, какой формат изображения отдать пользователю, основываясь на возможностях его браузера. Внешне сайт остался прежним, никаких правок в HTML, тегах <img> или <picture> не потребовалось, а выигрыш в скорости существенный. Картинки в формате WebP и AVIF весят гораздо меньше привычных JPEG, иногда экономия достигает 30–50 %. Страницы начинают грузиться заметно быстрее, особенно на мобильных устройствах или при медленном Интернете. При этом вы по-прежнему храните оригиналы в хорошем качестве, а посетители с устаревшими браузерами увидят контент без проблем.
Читайте в блоге:
- Настройка редиректа с HTTP на HTTPS в Nginx без ошибок
- Настройка связки Nginx, PHP-FPM и ISPmanager вручную
- Настройка NGINX на Ubuntu 24.04 LTS: от первого запуска до HTTPS