Тяжёлые картинки тихо съедают вашу прибыль: руководство вебмастера по PageSpeed и оптимизации изображений

Вы запускаете сайт. Он проходит тесты на стейджинге, вы выкатываете его в прод, прогоняете контрольную проверку — вроде всё хорошо. Сайт работает пару месяцев, вы не делаете ничего, кроме наполнения контентом, и вдруг кто-то присылает отчёт PageSpeed, залитый оранжевым и красным. Структурно ничего не менялось. Вы просто наполнили страницы картинками. И скорость загрузки тихо просела.
Если вы зарабатываете на сайтах — будь то партнёрки, интернет-магазины, лидогенерация или контентные порталы с медийной рекламой, — это не косметическая проблема. Это проблема денег. В этом материале разберём, почему вес изображений утекает деньгами, а затем покажем на коде, как это чинить, чтобы проблема перестала возвращаться.
Почему медленный сайт — это дорогой сайт
Прежде чем трогать хоть один файл, стоит чётко понимать, что на самом деле стоит на кону. «Балл в PageSpeed упал» — слишком абстрактная формулировка, её легко игнорировать, пока не свяжешь её с деньгами.
Ранжирование. Google использует Core Web Vitals — LCP (Largest Contentful Paint), CLS (Cumulative Layout Shift) и INP (Interaction to Next Paint) — как сигналы ранжирования. Это не единственные сигналы, и они редко перевешивают хороший контент, но на конкурентных запросах, где десять результатов одинаково «нормальные», скорость становится тем, что решает спор. Страница, скатившаяся с 3-й позиции на 7-ю, теряет большую часть органических кликов. Для сайта, который живёт на органическом трафике, это прямой удар по выручке.
Конверсия. Каждая дополнительная секунда загрузки измеримо увеличивает показатель отказов и снижает конверсию. Конкретные цифры варьируются от исследования к исследованию и от ниши к нише, но направление неизменно: медленные страницы конвертируют хуже. Для магазина или воронки лидогенерации ускорение первого экрана на полсекунды способно сдвинуть ту самую метрику, которая платит по счетам.
Доход с рекламы. Если вы монетизируете сайт медийной рекламой, ваш эффективный доход на тысячу показов (RPM) завязан на вовлечённость и видимость. Посетитель, который ушёл до отрисовки страницы, не увидел ни одного объявления и ни одной страницы. Скачки вёрстки (CLS) от картинок, которые грузятся без заранее зарезервированных размеров, к тому же сдвигают контент прямо во время прокрутки и портят тот пользовательский опыт, за который рекламные сети платят больше.
Стоимость хостинга и трафика. Каждый отданный мегабайт — это мегабайт, за который вы платите. Раздутые изображения умножают исходящий трафик, счёт за CDN и нагрузку на сервер. Оптимизация картинок снижает инфраструктурные расходы одновременно с ростом позиций — редкий случай, когда SEO-фикс и сокращение затрат — это одно и то же действие.
Важен и режим троттлинга. PageSpeed намеренно тестирует в жёстких условиях: без кэша, на симуляции мобильного соединения где-то между быстрым 3G и медленным 4G. Это не выдуманный худший случай — это реальные условия для большой доли мобильных пользователей, а мобильный трафик составляет большинство. Хуже того, Google индексирует сначала мобильную версию сайта. То есть медленный, без кэша, мобильный опыт, который симулирует PageSpeed, — это для целей ранжирования самая важная версия вашего сайта.
Почему именно изображения
Когда начинаешь копать медленный сайт, почти всегда всплывает один и тот же виновник — изображения. Их неправильно готовят: не ресайзят, игнорируют соотношение сторон, не конвертируют в современные форматы, заливают «как есть». Откройте мобильную страницу — и часто увидите картинку во всю ширину десктопа, сжатую силами CSS так, что она выглядит нормально, но весит в разы больше, чем должна.
На вопрос «почему так?» обычно отвечают: «всё с макета, perfect pixel» или «с дизайном согласовано». А значит, риск надо было закрывать на этапе дизайна и разработки — но на практике его обнаруживают, когда прод уже горит, а SEO-отдел заводит задачи.
Хорошая новость: изображения — это и самый высокорычажный объект для исправления. Они тяжёлые, они на критичном первом экране, и они полностью под вашим контролем. Разберём по шагам.
Пункт 0. Оценка масштабов катастрофы
Открываем DevTools, вкладку «Сеть», перезагружаем, смотрим на запросы. Обычные виновники — логотип, изображение в хедере и иконки интерфейса: всё, что на первом экране, потому что именно это определяет, как быстро посетитель что-то увидит и составит первое впечатление.
Теперь суммируем вес изображений. То, что раньше измерялось в килобайтах, перевалило за мегабайты. И это только картинки — весомая, но не единственная часть нагрузки. Вывод нулевого пункта прост: сайт не просто «работает», а планомерно обрастает тяжёлым контентом. С этим надо что-то делать.
Пункт 1. Размеры и формат
Дизайнеры нарезают красивые макеты, но в админке картинки заливает контент-менеджер, и его логика проста: «Если поле позволяет загрузить PNG в 4K — почему бы и нет? Предварительная конвертация требует времени, а время — деньги компании». А PageSpeed упорно пишет, что изображения больше, чем нужно, и съедают лишние ресурсы.
Решение — заложить обработку на уровне кода заранее или, если проект уже в проде, внедрить её сейчас. Можно выполнять вместе или выборочно. (Логично, что AVIF уже легче JPEG, а нарезанная мобильная версия легче десктопной.)
Ресайз под реально используемые размеры. Смотрим, какие размеры используются на ключевых разрешениях, и делаем автоматическую нарезку под них. Например, для фото в шапку во всю ширину валидны вариации: десктоп (1280px), планшет (768px), мобилка (320px). Нет никакого смысла отдавать 1280 пикселей картинки на телефон шириной 320 пикселей.
Конвертация в WebP, AVIF или JPG. Частая ошибка — использовать PNG для всего подряд, в том числе там, где нет прозрачности; при этом упускают, что даже оптимизированный PNG весит больше JPG. Автоматика плохо отслеживает прозрачность, но при ручной заливке стоит сменить расширение PNG-исходника на правильное. Дальше генерируем веб-форматы. Почему именно WebP и AVIF? Потому что они проектировались для веба и дают лучшее соотношение качество / вес / поддержка. Оговорка: иногда WebP может весить больше исходника, а AVIF больше WebP — но это исключения. Для статики просто выбираем самый лёгкий формат. В идеале соблюдается неравенство: вес исходника > вес WebP > вес AVIF.
Сжатие без видимых потерь. С этим хорошо справляются Pillow (Python), Sharp (Node) или ImageMagick. Для автоматического сжатия начните с 20% — при таком значении видимые потери почти незаметны — а дальше подгоните по необходимости.
Что учесть при конвертации и сжатии:
- То, что уже залито, зачастую легче перезалить руками — так вы не потеряете контроль над тем, что получилось после нарезки.
- AVIF сжимает агрессивно. При ручной заливке можно показать результат в админке и проконтролировать качество; при полной автоматике можно получить вместо картинки набор цветных полосок. У WebP таких проблем, как правило, нет, но контроль лишним не бывает.
- Для CKEditor и подобных редакторов — парсим сохранённый HTML (например, через BeautifulSoup), подменяем картинки и сохраняем в отдельное поле для отображения.
- Меняем <img> на <picture> с источниками для разных форматов, разрешений и вариаций. Браузер загрузит только ту вариацию, чей type он умеет декодировать. Поскольку мобильный трафик в большинстве, а Google индексирует mobile-first, в <img> ставим мобильную картинку как fallback, а в width и height — размеры мобильной версии.
Даже когда изображение изначально было в AVIF, такой проход срезает передаваемый вес на 50 КБ и больше. Звучит скромно, пока не вспомнишь, что страницы собраны из повторяющихся блоков — блок статей с 3–4 превью, блок отзывов с 2–3 фото клиентов. Возьмём консервативное число и выгоду от одной картинки:
50 КБ × (3 превью статей + 2 фото отзывов) = 250 КБ
Четверть мегабайта переданных данных долой, от одного прохода оптимизации, на одном паттерне блока. Помножьте на весь сайт — и одна только экономия на инфраструктуре оправдывает работу.
Пункт 2. Ленивая загрузка и предзагрузка
Всё, что видно на первом мобильном экране, грузим сразу (preload). Всё, что ниже, — с loading="lazy" и decoding="async". И обязательно проставляем width и height, чтобы вёрстка не прыгала по мере подгрузки картинок — именно за этот прыжок наказывает CLS.
Вот примерно как выглядит результат. Предзагрузка героя, где бэкенд по user-agent решает, поддерживает ли браузер AVIF/WebP:
<!-- В <head> -->
{% if page.use_avif %}
<link rel="preload" as="image"
href="{{ page.background.mobile.url_avif }}"
type="image/avif" media="(max-width: 768px)">
<link rel="preload" as="image"
href="{{ page.background.tablet.url_avif }}"
type="image/avif" media="(min-width: 769px) and (max-width: 1024px)">
<link rel="preload" as="image"
href="{{ page.background.desktop.url_avif }}"
type="image/avif" media="(min-width: 1025px)">
{% elif page.use_webp %}
<link rel="preload" as="image"
href="{{ page.background.mobile.url_webp }}"
type="image/webp" media="(max-width: 768px)">
<!-- ...планшет / десктоп webp... -->
{% else %}
<link rel="preload" as="image"
href="{{ page.background.mobile.url }}"
type="image/jpeg" media="(max-width: 768px)">
<!-- ...планшет / десктоп jpeg... -->
{% endif %}
А для картинок, спрятанных ниже первого экрана:
<picture>
{% if property.preview.normal.srcset_avif %}
<source srcset="{{ property.preview.normal.srcset_avif }}"
sizes="100vw" type="image/avif" media="(min-width: 1024px)">
{% endif %}
{% if property.preview.normal.srcset_webp %}
<source srcset="{{ property.preview.normal.srcset_webp }}"
sizes="100vw" type="image/webp" media="(min-width: 1024px)">
{% endif %}
<source srcset="{{ property.preview.normal.srcset }}"
sizes="100vw" type="image/jpeg" media="(min-width: 1024px)">
{% if property.preview.mobile.srcset_avif %}
<source srcset="{{ property.preview.mobile.srcset_avif }}"
sizes="100vw" type="image/avif">
{% endif %}
{% if property.preview.mobile.srcset_webp %}
<source srcset="{{ property.preview.mobile.srcset_webp }}"
sizes="100vw" type="image/webp">
{% endif %}
<source srcset="{{ property.preview.mobile.srcset }}"
sizes="100vw" type="image/jpeg">
<img src="{{ property.preview.mobile.url }}"
alt="{{ property.full_address() }}"
loading="lazy" decoding="async"
width="{{ property.preview.mobile.target_width }}"
height="{{ property.preview.mobile.target_height }}">
</picture>
Итог пункта: вы убрали скачки вёрстки, за которые наказывает CLS (через width/height), ускорили самый важный для первого впечатления первый экран (через preload) и вынесли из начальной загрузки всё, что посетитель сразу не увидит (через lazy + async).
Пункт 3. CSS background-image
Картинка в стилях — не проблема. Скриптом определяем поддержку WebP/AVIF (например, через попытку загрузить однопиксельную тестовую картинку нужного формата), затем добавляем к тегу <html> класс вроде avif или webp. В стилях через вложенные селекторы переключаем источник в зависимости от формата и брейкпоинта. На SCSS:
.banner {
// Мобильная версия (базовая, до 768px)
background-image: url('/static/img/banner-mobile.jpg');
.avif & { background-image: url('/static/img/banner-mobile.avif'); }
.webp & { background-image: url('/static/img/banner-mobile.webp'); }
@media (min-width: 768px) { // Планшет
background-image: url('/static/img/banner-tablet.jpg');
.avif & { background-image: url('/static/img/banner-tablet.avif'); }
.webp & { background-image: url('/static/img/banner-tablet.webp'); }
}
@media (min-width: 1280px) { // Десктоп
background-image: url('/static/img/banner-desktop.jpg');
.avif & { background-image: url('/static/img/banner-desktop.avif'); }
.webp & { background-image: url('/static/img/banner-desktop.webp'); }
}
}
Для background-image нельзя использовать <picture>, поэтому поддержку форматов подкладываем через класс на <html>: скрипт проверяет, с чем умеет работать браузер, добавляет класс, а SCSS уже подставляет правильный URL. Фон на любом устройстве грузится в оптимальном формате, без лишнего веса.
Пункт 4. SVG
SVG — это векторная графика, она не должна весить мегабайты. Увидели подозрительно тяжёлый SVG — открываем файл в любом текстовом редакторе. Если внутри data:image/jpeg;base64,, значит, дизайнер просто воткнул растровую картинку в векторную обёртку. Идём к нему и договариваемся о нормальном векторе, содержащем лишь векторные примитивы.
Также мелкие SVG, грузящиеся по отдельности, лучше сразу собрать в спрайт и подключать одним файлом, особенно когда их много (соцсети, иконки разделов). Каждый отдельный запрос — это обращение к серверу и трата его ресурсов; чем меньше запросов, тем меньше нагрузка и больше ресурсов остаётся на других посетителей.
Пункт 5 (добавлено). Вынести на край — CDN и кэширование
Когда сами файлы стали лёгкими, следующий по силе рычаг для денежного сайта — откуда они отдаются. Несколько дополнений, которых нет в исходном туториале:
- Положите изображения на CDN. Раздача статики с пограничных узлов рядом с посетителем резко снижает задержку, особенно для международного трафика, и снимает нагрузку с исходного сервера — а значит, прямо сокращает счёт за хостинг.
- Поставьте длинные заголовки кэширования на статику. Используйте далёкий
Cache-Control(например,max-age=31536000, immutable) на версионированных именах файлов, чтобы вернувшиеся посетители и краулеры ничего не перекачивали. Учтите: PageSpeed тестирует без кэша, так что сам балл это не поднимет, но реальных вернувшихся пользователей ускорит ощутимо и снизит нагрузку на origin. - Рассмотрите сервисы обработки картинок на лету. Если вручную вести вариации слишком тяжело, image CDN (или собственный resizing-прокси) умеет генерировать форматы и размеры из одного исходника по запросу, с кэшем. Это обмен небольшой стоимости запроса на гораздо меньше ручной работы.
- Включите HTTP/2 или HTTP/3 и Brotli/gzip на сервере, чтобы множество мелких запросов типичной страницы мультиплексировались эффективно, а не выстраивались в очередь.
Пункт 6 (добавлено). Измеряйте как бизнес-метрику, а не разово
Балл, который вы проверили один раз, протухает в момент, когда следующий контент-менеджер зальёт 4K PNG. Относитесь к скорости как к постоянной метрике:
- Используйте полевые данные, а не только лабораторные. Лабораторный прогон PageSpeed — это симуляция; отчёт Chrome User Experience Report (CrUX) и раздел Core Web Vitals в Search Console показывают, что реально видят посетители. Оптимизируйте под полевые цифры — именно они влияют на ранжирование.
- Задайте бюджет производительности. Определите максимальный вес страницы и вес картинок первого экрана и считайте превышение багом, а не пожеланием.
- Автоматизируйте проверку в пайплайне. Lighthouse CI или плановый скан поймают регрессию до того, как она попадёт в прод и до того, как SEO заведёт задачу.
Вывод
Качество сайта деградирует тихо, ради экономии пары минут на заливке, и вы обычно не замечаете этого, пока позиции или конверсия уже не просели. Технологии не стоят на месте — формулы расчёта баллов ужесточаются, методы сжатия совершенствуются, — так что проблема, проигнорированная сегодня, складывается в одну большую и болезненную завтра, из тех, что тяжело чинить без вреда контенту и без потери времени. Задача — продумать риск заранее.
Оптимизация изображений — это только начало, но одна из самых высокорычажных частей: тяжёлая, на виду и полностью под вашим контролем. Скрипты, шрифты и кэширование — следующие слои.
Чек-лист: заложить оптимизацию с самого начала
- Договоритесь с дизайнером заранее — иконки в настоящем SVG (без вшитого base64), растровые изображения не больше 1920px (или сколько реально нужно макету).
- Автоматизируйте обработку загрузок — ресайз и конвертацию в WebP/AVIF прямо в момент заливки. В Django, например, можно сжимать через Pillow при загрузке в админку.
- Используйте
<picture>иsrcsetс рождения — верстайте с адаптивными картинками сразу, а не заменяйте потом. - Проставляйте
width/heightна каждом<img>— даже когда хочется «потом проставим». Это самая дешёвая страховка от CLS. - Собирайте мелкие SVG в спрайт — один файл на иконки и соцсети, а не десятки отдельных запросов, каждый из которых бьёт по серверу.
- Кладите статику на CDN с длинным кэшем — быстрее пользователям, дешевле вам.
- Следите за полевыми Core Web Vitals в Search Console — чтобы следующая регрессия всплыла у вас на дашборде, а не в гневной SEO-задаче через два месяца.
Скорость — это не балл для красоты. Для сайта, который зарабатывает, это одновременно позиции, конверсия, рекламный RPM и стоимость хостинга — и изображения тот рычаг, что двигает все четыре с наименьшими усилиями.
Поделиться статьёй
Отправьте её в соцсети или скопируйте AI-промпт.


