Недавно я поставил цель для одного из моих сайтов набрать 100 баллов в Google PageSpeed Insights. Одно из требований, которое необходимо выполнить, - обслуживать изображения в форматах следующего поколения. Для этого я выбрал стандарт Google WebP.
Мой SaaS довольно сложен, и я не хотел вручную конвертировать изображения в каждом контроллере / сервисе, который обрабатывает загрузку изображений. Также я хотел, чтобы мой веб-сайт поддерживался более старыми браузерами без поддержки WebP, поэтому я не хотел изменять какие-либо из моих представлений, чтобы реализовать какие-либо условия для обнаружения поддержки изображений. Я хотел сделать это более ООП.
Сначала я создал миграции, которые добавили столбцы для моих изображений WebP. Допустим, у меня есть users
таблица, а в этой таблице есть avatar
столбец, в котором есть путь для хранения изображений в стандартных форматах. Я добавил avatar_webp
столбец для изображений в формате следующего поколения. Учтите, что этого делать не нужно, если названия изображений будут одинаковыми (они могут отличаться только расширением). Я хотел сделать это в отдельных столбцах, потому что я храню изображения с именем, созданным по контрольной сумме из их содержимого.
Когда я подготовил свои столбцы, я создал статическое свойство (оно не обязательно должно быть статическим, если вы этого не хотите) $images = []
в User
модели с именами столбцов, которые содержат пути к изображениям. Также в этой модели я сопоставил свои пользовательские события: одно для преобразования изображений при сохранении модели, а другое для отображения этого изображения в WebP, если браузер поддерживает его.
class User extends Model { public static $images = ['avatar']; protected $dispatchesEvents = [ 'saving' => ImagesConvert::class, 'retrieved' => ImagesProperFormat::class, ]; }
ImagesConvert.php
будет выполняться, когда модель находится непосредственно перед сохранением в базе данных, поэтому в этом файле мы установим содержимое наших _webp
столбцов. ImagesProperFormat.php
будет выполняться каждый раз при получении модели, поэтому внутри мы заменим исходный столбец изображения на изображение WebP, если браузер поддерживает его.
class ImagesConvert { const WEBP_SUFFIX = '_webp'; /** * @var Model */ protected $model; public function __construct(Model $model) { $this->model = $model; $this->convertImages(); } protected function convertImages(): void { /** @var array $images */ foreach ($this->model::$images as $image) { if ( key_exists($image, $this->model->getDirty()) && $imagePath = $this->model->{$image} ) { $this->model->{$image.self::WEBP_SUFFIX} = ImageConvertService::convertToWebp($imagePath); } } } }
Я использовал метод getDirty()
, чтобы конвертировать только измененные изображения.
В этой статье я не рассматриваю саму конвертацию WebP. Вы можете написать свой собственный, который использует инструмент командной строки или использовать существующие пакеты, такие как buglinjo / laravel-webp, rosell-dk / webp-convert или что-то в этом роде.
Важно! Обратите внимание, что вам следует использовать Job для обработки изображений, если вы заботитесь о скорости сохранения.
class ImagesProperFormat { /** * @var Model */ protected $model; public function __construct(Model $model) { $this->model = $model; $this->setProperImagesFormat(); } protected function setProperImagesFormat(): void { /** @var array $images */ foreach ($this->model::$images as $image) { if ( support_webp() && key_exists($image, $this->model->getAttributes()) && $this->model->{$image} && $webpImagePath = $this->model->{$image.ImagesConvert::WEBP_SUFFIX} ) { $this->model->{$image} = $webpImagePath; } } } }
И функция support_webp()
, которая является моей глобальной функцией из моего помощника по изображениям. Вы можете использовать статический вспомогательный метод, если хотите.
function support_webp(): bool { return isset($_SERVER['HTTP_ACCEPT']) && strpos($_SERVER['HTTP_ACCEPT'], 'image/webp') !== false; }
Таким образом, таким простым способом вы можете конвертировать и показывать свои изображения в формате WebP следующего поколения, не беспокоясь о местах в вашем коде, где изображения загружаются или отображаются. Вам просто нужно отредактировать свои модели.