Оптимизация изображений на PHP-сайте без потери управляемости

На небольших PHP-сайтах производительность часто упирается не в PHP, а в изображения. Главная страница может отдавать HTML за 100 миллисекунд, но пользователь всё равно ждёт, потому что баннер весит 4 мегабайта, карточки товаров загружают оригиналы, а изображения ниже первого экрана грузятся сразу.

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

Проверить фактический вес страницы

Начать лучше с браузера. Во вкладке Network видно, какие изображения грузятся, сколько весят и блокируют ли первый экран.

Через консоль можно проверить отдельный файл:

curl -I https://example.ru/uploads/banner.jpg
du -h web/uploads/banner.jpg

Если картинка отображается в блоке 600 пикселей шириной, а фактически имеет 4000 пикселей, сервер и пользователь гоняют лишние данные.

Реальные размеры

Нельзя полагаться только на CSS-уменьшение. Браузер всё равно скачает исходный большой файл.

<img src="/uploads/photo-4000.jpg" width="600" height="400" alt="">

Лучше заранее создать размер под место отображения:

<img src="/uploads/cache/photo-600.jpg" width="600" height="400" alt="">

WebP и fallback

WebP часто заметно уменьшает вес изображений. Для простого сайта можно хранить WebP-версии рядом с исходниками и отдавать их в шаблоне.

<picture>
    <source srcset="/uploads/cache/photo-600.webp" type="image/webp">
    <img src="/uploads/cache/photo-600.jpg" width="600" height="400" alt="">
</picture>

Если используется автоматическая обработка, важно не пересоздавать изображения на каждом запросе. Генерация должна происходить при загрузке, в фоне или один раз при первом запросе с сохранением результата.

Lazy loading

Изображения ниже первого экрана можно загружать лениво. Для многих страниц достаточно стандартного loading="lazy".

<img src="/uploads/cache/product-300.webp" loading="lazy" width="300" height="300" alt="">

Для изображений первого экрана lazy loading лучше использовать осторожно. Главный баннер или основное фото товара должны появляться быстро.

srcset для разных экранов

Если один и тот же блок открывается на телефоне и на широком мониторе, полезно отдавать разные размеры.

<img
    src="/uploads/cache/photo-600.webp"
    srcset="/uploads/cache/photo-300.webp 300w, /uploads/cache/photo-600.webp 600w, /uploads/cache/photo-1200.webp 1200w"
    sizes="(max-width: 600px) 300px, 600px"
    width="600"
    height="400"
    alt="">

Это особенно полезно для каталогов и блогов, где много превью.

Обработка загружаемых файлов

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

public function rules()
{
    return [
        [
            ['image'],
            'file',
            'extensions' => ['jpg', 'jpeg', 'png', 'webp'],
            'maxSize' => 8 * 1024 * 1024,
        ],
    ];
}

После загрузки можно создать несколько производных размеров. Важно хранить оригинал отдельно или хотя бы понимать, можно ли его удалить.

Кэширование статики

Оптимизированные изображения должны нормально кэшироваться браузером. Для файлов с неизменяемым именем нельзя ставить слишком долгий кэш без версии. Для файлов с hash или уникальным именем долгий кэш подходит лучше.

location ~* \.(jpg|jpeg|png|webp|gif|svg|ico)$ {
    expires 30d;
    add_header Cache-Control "public";
}

Не забыть alt и размеры

Оптимизация — не только сжатие. У изображений должны быть width и height, чтобы страница не прыгала при загрузке. alt нужен для доступности и нормального описания контента.

<img src="/uploads/cache/service.webp" width="800" height="500" alt="Настройка сайта">

Чек-лист

  1. Проверить вес изображений во вкладке Network.
  2. Не отдавать оригиналы там, где нужны превью.
  3. Создать размеры под реальные блоки.
  4. Использовать WebP там, где это уместно.
  5. Добавить lazy loading для изображений ниже первого экрана.
  6. Использовать srcset для разных экранов.
  7. Ограничить загрузки через админку.
  8. Настроить кэширование статики.

Изображения лучше оптимизировать системно. Разовая ручная сжатая картинка помогает только до следующей загрузки через админку. Нормальный процесс обработки экономит трафик постоянно и снижает риск, что сайт снова станет тяжёлым через месяц.

Комментарии (0)

Пока нет комментариев. Будьте первым!