Дружим WebP и EvolutionCMS

формат webp

WebP — формат изображений для веба, который активно пиарит компания Google. Есть он и есть, казалось бы, много каких форматов есть, если бы не одно но: при проверке через новый гугл-спид за отсутствие онных изображений сильно снижаются оценки. И если вам не приходилось выслушивать от клиентов или сеошников то, что показатели гугл-спида низкие и это срочно нужно поправить, то знайте: вы счастливчик. Ну да это все лирика.

Начнем с проблем с этим форматом:

  1. Большинство графических редакторов с ним не дружат.
  2. phpthumb с ним не дружит
  3. Apple с ним не дружит
  4. С ним вообще никто не дружит, кроме гугла)
Как быть и что с ним делать?

Вариант номер один: забить. Тысячу раз так делал — реально работает и ничего делать не надо)
Вариант номер два, если первый ну вообще никак не получается — последовать дальнейшей инструкции.

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 комментариев

avatar
Вот эта строчка лишняя так как автолоад у нас и так уже подключается в index.php

 require $modx->config['base_path'].'vendor/autoload.php';
avatar
Не придирки ради, а справедливости для… Многие программисты в сообществе выпускают компоненты беря за основу код из других компонентов, которые зачастую устаревшие. Поэтому просто оставлю свои примечания к коду

Использование $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)
avatar
Если бы ещё об этом всём где-то писалось.
В документации синтаксис прежний. В релизах по этой теме ничего не говорится.
Как ещё людям узнавать о таких вещах, если они не разработчики самой системы? Не будут же следить за каждым пул-реквестом.
Комментарий отредактирован 2019-04-08 23:12:40 пользователем akool
avatar
Вообще не понял, как оно работает. Абсолютно ничего не происходит, какртинки как были, так и остаются в jpeg,png
avatar
Перед выводом страницы на экран идет проверка на браузер. Если находится браузер, который не поддерживает данный формат — прекращает работу (ничего не делает).
Далее скрипт находит картинки используемые на странице. Далее проверяет — есть ли картинка с таким же названием, но с webp расширением. Если есть, то просто меняет ссылку на нужную. Если нет, то создает картинку и также меняет ссылку на нужную.
Скрипт проверен на десятках сайтах, поэтому почему конкретно у вас ничего не происходит — нужно разбираться.
avatar
Посмотрел на маке и на винде, закомментировал условие — всё равно нифига. Хром, кстати, вне зависимости от OC понимает 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

Но как бы то ни было — фигу
avatar
Посмотри на моем сайте. Если также не открываются webp, следовательно что-то с юзер-агентом нужно думать. Если открываются, нужно разбираться с конкретно твоим сайтом. Тут логика то самого скрипта проста же…
avatar
Хром мак


Хром винда


Вот же блин, а у меня и на винде не подсасывает
avatar
Еще firefox тоже умеет теперь webp
Надо как-то проверять поддержку по-другому ИМХО. Для того же
Есть правило например такое

<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'] надо копаться
пример из фаерфокса
Комментарий отредактирован 2019-03-19 13:04:40 пользователем alexbeep
avatar
На EVO 1.4.8 из экстраса compozer не встаёт. Точнее встаёт и при попытке запуска ругается на базу.
avatar
А вот подскажите, где можно подкрутить качество сжатия?
avatar
Есть плагин для modx Webp converter for MODX который осуществляет конвертацию графических файлов в формат webp.
avatar
Ну так это для Рево, и там принцип несколько иной.
avatar
Этот плагин работает как надстройка, там используются методы ядра только в нескольких местах, его можно приспособить под любую CMS.
меняем

$output= &$modx->resource->_output;
на
$output = $modx->event->params['documentOutput'];
в плагине. Отключаем проверку авторизации в обработчике ajax, и меняем li элемент в js. И плагин будет работать в Evo
avatar
liberpro В алгоритме кодирования есть ошибка: Исходник для кодирования в webp используется уже сжатый jpg, что приводит к замыленным картинкам на качестве 90% и ниже. Т.е. по факту исходная картинка жмется дважды — в jpg, а затем уже в webp.

Алгоритм должен быть такой:
1) Изменить размер картинки без потерь качества
2) Сжать в нужный формат (jpg, webp, и можно уже задумываться о формате avif) с нужным коэффициентом сжатия, который должен задаваться для каждого формата свой
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.