Урок 03

Оптимизация изображений: WebP, AVIF, srcset

Почему важно

Что тормозит:

  • Изображения — 60–80% трафика.
  • 1 МБ картинка на мобильном = 3 сек.
  • LCP — чаще всего картинка.
  • Трафик CDN — деньги.

Что даёт оптимизация:

  • LCP ↓ в 2–3×.
  • Трафик ↓ в 3–5×.
  • UX лучше.
  • SEO лучше.

Правило: изображения — первое, что оптимизируют.

Форматы

JPEG:

  • Фото без прозрачности.
  • Устаревает.

PNG:

  • Прозрачность.
  • Скриншоты.
  • Тяжёлый.

WebP:

  • Современный.
  • На 25–35% меньше.
  • Поддержка 95%+.

AVIF:

  • Ещё меньше на 20–30%.
  • Поддержка 80%+.
  • Кодирование медленнее.

SVG:

  • Иконки, лого.
  • Вектор.

GIF:

  • Устарел, заменять на MP4/WebM.

Правило: JPEG / PNG → WebP + AVIF.

Что выбрать

ТипФормат
ФотоAVIF + WebP + JPEG
ЛогоSVG
ИконкиSVG
СкриншотыWebP / AVIF
АнимацияMP4 / WebM
ПрозрачностьWebP / AVIF

Правило: нет одного формата для всего.

<picture>

<picture>
    <source srcset="img.avif" type="image/avif">
    <source srcset="img.webp" type="image/webp">
    <img src="img.jpg" alt="..." width="800" height="600" loading="lazy">
</picture>

Что делает: браузер выбирает лучший формат.

Правило: AVIF → WebP → JPEG.

srcset

<img
    src="img-800.jpg"
    srcset="
        img-400.jpg 400w,
        img-800.jpg 800w,
        img-1200.jpg 1200w,
        img-1600.jpg 1600w
    "
    sizes="
        (max-width: 600px) 100vw,
        (max-width: 1024px) 50vw,
        800px
    "
    alt="..."
    width="800"
    height="600"
    loading="lazy"
>

Что делает: выбирает подходящий размер.

Правило: srcset + sizes — обязательно.

sizes — что означает

sizes="
    (max-width: 600px) 100vw,   # на мобильном — весь экран
    (max-width: 1024px) 50vw,   # на планшете — половина
    800px                        # на десктопе — 800px
"

Что даёт: браузер знает, какой размер подходит.

Правило: sizes — точно по CSS.

Возможные размеры

Правило:

  • 400w — мобильные.
  • 800w — планшеты.
  • 1200w — десктоп.
  • 1600w — retina десктоп.
  • 2400w — retina 4K.

Правило: 3–5 вариантов достаточно.

DPR (retina)

<img
    src="img@1x.jpg"
    srcset="img@1x.jpg 1x, img@2x.jpg 2x, img@3x.jpg 3x"
    alt="..."
>

Что даёт: retina получает @2x/@3x.

Правило: srcset по DPR — для иконок.

width и height

Обязательно:

<img src="img.jpg" width="800" height="600" alt="...">

Что даёт: нет CLS.

Правило: всегда width/height.

aspect-ratio

.image {
    aspect-ratio: 16 / 9;
    width: 100%;
    object-fit: cover;
}

Что даёт: гибкий резерв.

object-fit

img {
    object-fit: cover;   /* обрезать */
    object-fit: contain; /* вписать */
}

Правило: cover — для карточек, contain — для логотипов.

Preload LCP

<link
    rel="preload"
    as="image"
    href="hero.avif"
    imagesrcset="hero-400.avif 400w, hero-800.avif 800w"
    imagesizes="100vw"
    fetchpriority="high"
>

Что даёт: LCP-картинка грузится сразу.

Правило: preload + fetchpriority для LCP.

Оптимизация в сборке

Vite:

npm install -D vite-imagetools
import hero from './hero.jpg?w=1200&format=avif';

Next.js: автоматически через next/image.

Nuxt: @nuxt/image.

Правило: оптимизация — в сборке, не вручную.

CLI оптимизация

cwebp:

cwebp -q 80 input.jpg -o output.webp

avifenc:

avifenc -q 60 input.jpg output.avif

sharp-cli:

npx sharp-cli -i input.jpg -o output.avif

Правило: для существующих картинок — batch через CLI.

CDN

Cloudflare Images:

https://cdn.example.com/image.jpg?w=800&format=auto&quality=80

imgix:

https://example.imgix.net/image.jpg?w=800&fm=webp&q=80

Cloudinary:

https://res.cloudinary.com/xxx/image/upload/w_800,f_auto,q_auto/image.jpg

Что даёт:

  • Оптимизация на лету.
  • Формат авто.
  • Размеры по URL.
  • Кэш на CDN.

Правило: для больших — CDN Images.

Правило 100 KB

Ориентиры:

  • Hero — до 200 KB.
  • Карточка — до 100 KB.
  • Аватар — до 30 KB.
  • Иконка — до 5 KB.

Правило: больше — оптимизировать.

Что НЕ делать

  • PNG для фото.
  • GIF для видео.
  • BMP / TIFF в проде.
  • JPEG для иконок — SVG.
  • Одну картинку для всех размеров.

Проверка

Что смотреть:

  • PageSpeed — размер изображений.
  • DevTools → Network — сортировка по размеру.
  • Coverage — загружено vs нужно.
  • Lighthouse — рекомендации.

Правило: топ-10 крупных — первыми.

Практика

1. Найдите топ-10 больших картинок.

2. Конвертируйте в WebP/AVIF.

3. Добавьте <picture> с fallback.

4. Настройте srcset + sizes.

5. LCP — preload + fetchpriority.

6. Включите CDN Images.

7. width/height — везде.

8. Замерьте LCP до/после.

9. Проверьте CLS.

10. Настройте авто-оптимизацию.

Частые ошибки

1. PNG для фото:

3× размер

Решение: WebP / AVIF.

2. Одна картинка для всех:

1600px на мобильном

Решение: srcset.

3. Без размеров:

CLS

Решение: width/height.

4. GIF для анимации:

10 MB

Решение: MP4.

5. Без preload LCP:

LCP медленный

Решение: preload.

6. Retina без @2x:

Мыльно

Решение: srcset по DPR.

7. Всё вручную:

Забывают

Решение: авто в сборке.

8. Без CDN:

Оригинал в проде

Решение: CDN.

Итог

  • WebP + AVIF — стандарт.
  • <picture> — fallback.
  • srcset + sizes — адаптив.
  • LCP — preload + fetchpriority.
  • width/height — против CLS.
  • SVG — для иконок.
  • MP4 — вместо GIF.
  • CDN — для больших.
  • Авто — в сборке.
  • 100 KB — ориентир.

Дальше — шрифты: preload, font-display.