Дружим WebP и EvolutionCMS
WebP — формат изображений для веба, который активно пиарит компания Google. Есть он и есть, казалось бы, много каких форматов есть, если бы не одно но: при проверке через новый гугл-спид за отсутствие онных изображений сильно снижаются оценки. И если вам не приходилось выслушивать от клиентов или сеошников то, что показатели гугл-спида низкие и это срочно нужно поправить, то знайте: вы счастливчик. Ну да это все лирика.
Начнем с проблем с этим форматом:
- Большинство графических редакторов с ним не дружат.
- phpthumb с ним не дружит
- Apple с ним не дружит
- С ним вообще никто не дружит, кроме гугла)
Вариант номер один: забить. Тысячу раз так делал — реально работает и ничего делать не надо)
Вариант номер два, если первый ну вообще никак не получается — последовать дальнейшей инструкции.
1) Проверяем чтобы gd или imagick на сервере были включены. Если нет — включаем.
2) Через composer (кстати, есть модуль в extrats) ставим либу rosell-dk/webp-convert. Если composer по каким-то причинам не работает, то ставим его отседова.
3) Создаем плагин WebP ставим галочку напротив события OnWebPagePrerender и вставляем в него нижеследующий код:
//<?php
$userAgent = strtolower($_SERVER['HTTP_USER_AGENT']);
$iosDevice = array('iphone', 'ipod', 'ipad','macintosh','mac os','Edge','MSIE');
foreach ($iosDevice as $val) {
if(stripos($userAgent, $val) !== false) return;
}
//require MODX_BASE_PATH.'vendor/autoload.php'; //если версия Evo ниже 1.4 или вообще Рево, то снимаем комментарий с этой строчки
use WebPConvert\WebPConvert;
$content = $modx->event->params['documentOutput'];
//$content = &$modx->resource->_output; //Для Revolution раскомментируйте эту строку и первую.
$imgs = array();
preg_match_all('/<img[^>]+>/i',$content, $result);
if (count($result))
{
foreach($result[0] as $img_tag)
{
preg_match('/(src)=("[^"]*")/i',$img_tag, $img[$img_tag]);
$img_real = str_replace('"','',$img[$img_tag][2]);
$img_real = str_replace('./','',$img_real);
if ((strpos($img_real, '.jpg')!==false) or (strpos($img_real, '.jpeg')!==false) or (strpos($img_real, '.png')!==false)) $imgs[] = $img_real;
}
$imgs = array_unique($imgs);
foreach($imgs as $img_real)
{
if(($img_real) && (file_exists($modx->config['base_path'].$img_real)))
{
if (!file_exists($modx->config['base_path'].$img_real.'.webp'))
{
$image = $modx->config['base_path'].$img_real;
$destination = $modx->config['base_path'].$img_real.'.webp';
if (WebPConvert::convert($image, $destination)) $i = $img_real.'.webp';
else $i = $img_real;
}
else $i = $img_real.'.webp';
$content = str_replace($img_real, $i, $content);
}
}
}
$modx->event->output($content);
4) Сохраняем. Радуемся. Все картинки на сайте у нас теперь в формате WebP. Получаем звонкие монеты от клиентов, не забываем делиться с автором. Хотя бы кармой) Если сработает — то позитивной, если нет — то гневной)
UPD: Для работы на Revolution замените соответствующую строку.
15 комментариев
Использование $modx->config['base_path'] (как и некоторых других параметров) в коде, мне кажется дурной тон. Глядя на такой код можно подумать, что путь к вашим файлам меняется через системные настройки. Но это не так, ведь значение берется из константы MODX_BASE_PATH. Поэтому, чтобы небыло разночтений или случайных ошибок вызванных перезаписью $modx->config['base_path'], рекомендуется обращаться именно к константе.
$modx->config['base_path'] определяется только с одной целью — доступ к абсолютному пути из парсера modx через плейсхолдер [(base_path)]
$modx->Eventявляется синонимом для $modx->event. Добавленый еще в какой-то лохматой версии. Так мы и тащим за собой это наследние. Поэтому тоже рекомендуется использовать $modx->event, чтобы не привязываться к устаревшему коду.Ну и наконец, с версии 1.4.6, вместо
$modx->event->output()рекомендуется использовать $modx->event->addOutput() как метод с более говорящим названием (в версии 2.0 метод output уже объявлен как deprecated)В документации синтаксис прежний. В релизах по этой теме ничего не говорится.
Как ещё людям узнавать о таких вещах, если они не разработчики самой системы? Не будут же следить за каждым пул-реквестом.
Далее скрипт находит картинки используемые на странице. Далее проверяет — есть ли картинка с таким же названием, но с webp расширением. Если есть, то просто меняет ссылку на нужную. Если нет, то создает картинку и также меняет ссылку на нужную.
Скрипт проверен на десятках сайтах, поэтому почему конкретно у вас ничего не происходит — нужно разбираться.
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36
Но как бы то ни было — фигу
Хром винда
Вот же блин, а у меня и на винде не подсасывает
Надо как-то проверять поддержку по-другому ИМХО. Для того же
Есть правило например такое
<IfModule mod_rewrite.c>
RewriteEngine On
# Check if browser supports WebP images
RewriteCond %{HTTP_ACCEPT} image/webp
# Check if WebP replacement image exists
RewriteCond %{DOCUMENT_ROOT}/$1.webp -f
# Serve WebP image instead
RewriteRule (.+)\.(jpe?g|png)$ $1.webp [T=image/webp]
Вот оно вроде как срабатывает если браузер принимает webp.
Но я не понимаю, как его переписать в php
Где-то в $_SERVER['HTTP_ACCEPT'] надо копаться
пример из фаерфокса
меняем
$output= &$modx->resource->_output;
на
$output = $modx->event->params['documentOutput'];
в плагине. Отключаем проверку авторизации в обработчике ajax, и меняем li элемент в js. И плагин будет работать в Evo
Алгоритм должен быть такой:
1) Изменить размер картинки без потерь качества
2) Сжать в нужный формат (jpg, webp, и можно уже задумываться о формате avif) с нужным коэффициентом сжатия, который должен задаваться для каждого формата свой