
Возможно, у некоторых из Вас, возник вопрос, с чем это всё связано и почему, такой ажиотаж вокруг данного формата. А, ну-ка догадайтесь, и Вы как всегда правы! Ветер дует из страны SEO и всяческих ТОПов. Но давайте всё рассмотрим последовательно, ведь мы с Вами труженики ножа и топора, о, прошу прощения, подработки у всех разные, ну так, о чем, это я? Ага, давайте, сначала немного о новом формате, от которого всё просто бегают по-маленькому, образно говоря. Что же это за формат WebP и откуда он вдруг, нарисовался на наши с Вами головы?
Знакомьтесь формат графических изображений WebP
WebP — формат графических изображений, который был разработан в недрах Google аж в 2010 году. Задумка у хитрого Google была в том, что надо бы, взять всё лучшее от форматов PNG, JPG и GIF, да и засунуть всё в один формат. Собственно, у них получилось, причем очень даже. Вот официальное исследование от Google https://developers.google.com/speed/webp/docs/webp_study, если кому интересно. Но в рамках этой статьи мы не рассматриваем данный формат, поэтому в картце о его преимуществах и недостатках, и затем, идём дальше.
Преимущества и недостатки WebP
Преимущества формата:
- сохраняет такое же качество при меньшем размере картинки: при сжатии с потерями размер будет в среднем на 30% меньше, чем в JPEG, а без потерь в среднем на 25% меньше, чем PNG;
- сочетает в себе все преимущества PNG, JPEG и GIF, поддерживает прозрачность и анимацию.
Недостатки формата:
- формат поддерживают не все браузеры;
- в пиксельной графике может потеряться часть цветов;
- при сжатии с потерями изображение может выглядеть плоским.
И немного Вам, экспертного мнения:
Google активно продвигает WebP и будет продолжать это делать. Но, как известно, данный формат поддерживают 75% браузеров.
Хорошим решением будет наличие нескольких форматов изображений и выдача нужного типа изображения по ответу браузера — поддерживает WebP или нет. Да, это приведёт к увеличению количества файлов и заполнения дискового пространства, но даст определенные преимущества перед теми, кто не пользуется новыми форматами.
Положительное влияние наличия формата WebP на сайте на поисковую выдачу уже замечено.
(с) Андрей Прудко, директор студии интернет-маркетинга и веб-брендинга «Большая Буква»
Ну, а теперь к нашим с Вами делам, хотя дела у прокурора, а у нас простых web-мастеров, небольшие дельца.
Плагин MODX Revolution для отображения на сайте формата WebP
Многие пытливые умы, читающие эту статью, уже набросали себе парочку путей, по которым можно решить данную проблему. Первоначально услышав, что именно надо сделать, моя ленивая натура решила, создать TV и чтобы клиент добавлял туда второй тип изображения. Данную идею, я сразу отмел, достаточно было взглянуть на сайт клиента, там не просто было куча изображений. Но они были, немного не мало, вставлены в поле content. И главное ресурсов на сайте уже была большая куча и маленькая тележка. Копать всё и перекапывать, это надо сказать, было бы, покруче подвига Геракла в Авдеевых конюшнях.
Да, именно, так, мой дорогой друг, твой пытливый ум, прав! Я взглянул в сторону сниппета, который можно, было бы вызвать, где-нибудь в дебрях шаблонов и чанков. Но после мысленного подзатыльника, элемент ментального БДСМ, я вперил свои зоркие глазки в плагин. О, да, это то, что надо. И вот что у меня получилось.
Первая задача, определить работает ли браузер с форматом WebP и, если работает, отдать ему его, а если нет оставить первоначальный. Чудо, великие умы, уже об этом позаботились. Да, мой дорогой друг, наши с тобой умы не единственные величайшие в этом мире. Так вот в HTML 5 уже все есть, а именно волшебная конструкция тега picture. Вот так это будет:
Конечно, там можно другие форматы напихать, но об этом дальше.
Дело осталось за малым, найти и подменить обычный тег img нашим picture, при этом проверив есть ли файл формата WebP. Ну не буду томить, вот код плагина:
<?php $output = &$modx->resource->_output; $img = array(); preg_match_all('/<img[^>]+>/i',$output, $result); foreach($result[0] as $img_tag){ preg_match_all('/([a-zA-Z0-9_-]{1,})=(["|\'][^"]*["|\'])/i',$img_tag, $img); $atr = array(); foreach ($img[1] as $k => $v){ $atr[$v]=str_replace('"','',$img[2][$k]); } $finfo=pathinfo($atr['src']); $fname=$finfo['dirname'].'/'.$finfo['filename'].'.webp'; if (stristr($fname,':')){ $file_headers=@get_headers($fname); if($file_headers[0] == 'HTTP/1.1 200 OK'){ $rout = "<picture><source type='image/webp' srcset='$fname'>"; if ($finfo['extension'] == 'jpg' || $finfo['extension'] == 'jpeg') $rout .= "<source type='image/jpeg' srcset='".$atr['src']."'>"; if ($finfo['extension'] == 'png') $rout .= "<source type='image/png' srcset='".$atr['src']."'>"; if ($finfo['extension'] == 'gif') $rout .= "<source type='image/gif' srcset='".$atr['src']."'>"; $rout .= "<img src='".$atr['src']."'"; $falt = true; foreach ($atr as $k => $v){ if ($k != 'src') $rout .= ' '.$k.'="'.$v.'"'; if ($k == 'alt') $falt = false; } if ($falt) $rout .= ' alt="Изображение"'; unset($atr); $rout .= "></picture>"; $output = str_replace($img_tag, $rout, $output); } }else{ if(file_exists($fname)){ $rout = "<picture><source type='image/webp' srcset='$fname'>"; if ($finfo['extension'] == 'jpg' || $finfo['extension'] == 'jpeg') $rout .= "<source type='image/jpeg' srcset='".$atr['src']."'>"; if ($finfo['extension'] == 'png') $rout .= "<source type='image/png' srcset='".$atr['src']."'>"; if ($finfo['extension'] == 'gif') $rout .= "<source type='image/gif' srcset='".$atr['src']."'>"; $rout .= "<img src='".$atr['src']."'"; $falt = true; foreach ($atr as $k => $v){ if ($k != 'src') $rout .= ' '.$k.'="'.$v.'"'; if ($k == 'alt') $falt = false; } if ($falt) $rout .= ' alt="Изображение"'; unset($atr); $rout .= "></picture>"; $output = str_replace($img_tag, $rout, $output); } } }
Событие, на которое он реагирует выставляем OnWebPagePrerender. Суть, данное событие вызывается, когда страница готова отправиться браузеру. В этот момент мы хватаем всё то, что отправляется браузеру под видом страницы сайта. И исследуем с помощью регулярного выражения, отлавливая все теги img полностью. Полностью, потому как нам надо если вдруг есть файл с таким же названием, но с расширением webp, заменить весь тег нашим тегом picture.
Сформировав массив изображений, мы его перебираем и вновь используя регулярное выражение, вытаскиваем все атрибуты тега img и сохраняем их в массив $atr.
После того как мы всё вытащили, уже с помощью pathinfo расчленяем атрибут src. Получив таким образом все необходимое для формирования пути и имени файла с расширением webp.
Далее интересный момент, file_exists не работает с полными путями, только с относительными. Поэтому выполняем простенькую проверку на наличие в пути двоеточия, если есть, значит путь полный и мы ппроверяем наличие файла с помощью отправки заголовка, если нету, значит путь относительный мы проверяем наличие файла с помощью file_exists. Если наличие файла подтверждено, то формируем наш тег picture и заменяем текущий тег img, не забыв ему прикрепить все его атрибуты.
Твой острый ум, отметил, почему атрибут alt при своём отсутствии, всё равно заполняется и отображается. Всё просто, великий валидатор validator.w3.org указал матом на то, что данному атрибуту быть надо. Мы лишь скромные падованы, и выполняем требования великого мастера.
Из кода видно, что плагин работает с форматами png, jpeg, jpg и gif. После того как плагин запущен, всё что надо это по ftp закинуть в тоже место, где и изначальный файл изображения его копию в формате WebP. Вот один из конверторов https://image.online-convert.com/ru/convert-to-webp, сам пользовал, ощущений масса.
Да, совсем забыл, чтобы загружать изображения формата WebP, стандартными средствами MODX Revolution, надо будет залезть в системные настройки и там "Core -> Файловая система", добавить формат к разрешенным к загруке файлам и изображениям.
На этом всё, успехов тебе дорогой читатель и великих свершений!
03.08.2019 Исправлено: плагин прикручивал атрибуты предыдущего изображения к текущему.