MODX + WebP: оптимизация изображений для ускорения сайта

MODX CMS, with images optimized in WebP format for fast loading. The interface showcases a visually clean and fa MODX Revo
Скорость загрузки сайта – это один из ключевых факторов, влияющих на то, насколько хорошо он работает. Чем быстрее загружается ваш сайт, тем лучше для пользователей, поисковых систем и, в конечном итоге, для вашего бизнеса. Одним из самых эффективных способов ускорить сайт является оптимизация изображений. В этой статье мы рассмотрим, как использовать формат WebP для оптимизации изображений в системе управления контентом (CMS) MODX.

Что такое WebP?

Прежде чем углубиться в тему, давайте разберемся с основными понятиями. WebP – это формат изображений, разработанный Google. Он был создан для того, чтобы заменить более старые форматы, такие как JPEG и PNG. Преимущество WebP заключается в том, что он позволяет уменьшить размер изображений на 25–35% без видимой потери качества.

Почему использование WebP важно для сайтов на MODX?

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

  • Сокращение времени загрузки сайта.
  • Улучшение показателей Core Web Vitals, таких как Largest Contentful Paint (LCP).
  • Снижение нагрузки на сервер за счет уменьшения размера файлов.
  • Повышение позиций в результатах поисковой выдачи (Google учитывает скорость сайта при ранжировании).

Как создать или конвертировать изображения в WebP?

Существует несколько способов преобразовать изображения в формат WebP. Вот некоторые из них:

1. Онлайн-сервисы

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

  • ToWebp или AnyWebp – бесплатные сервисы для массовой конвертации изображений JPG, PNG, GIF, SVG, ICO, BMP, и AVIF в WebP.
  • Squoosh – сервис и веб-приложение от Google, которое позволяет сжимать изображения и выбирать различные форматы.

2. Программы для компьютера

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

  • Adobe Photoshop – в последней версии можно сохранить изображение в формате WebP.
  • GIMP – бесплатная альтернатива Photoshop, поддерживающая экспорт в WebP с помощью дополнительных плагинов.
  • XnView — бесплатное кроссплатформенное приложение, которое умеет массово конвертировать изображения в WebP.

Как внедрить WebP в MODX?

Теперь, когда у вас есть изображения в формате WebP, важно правильно внедрить их в MODX, чтобы они отображались только в тех браузерах, которые поддерживают этот формат. Для этого есть несколько способов.

1. Руками

Т.е. берем скачиваем все изображения с сайта, делаем их копии с теми же именами в формате webp. Заливаем их в те же папки, а затем лазим по шаблонам, чанками и т.д. и в место обычных вызовов: <img src="image.jpg" alt="Описание изображения"> пишемем вот такие конструкции:

<picture>
   <source srcset="image.webp" type="image/webp">
   <img src="image.jpg" alt="Описание изображения">
</picture>

Этот код проверяет, поддерживает ли браузер формат WebP, и отображает его, если поддержка есть. В противном случае, загружается стандартное изображение в формате JPEG или PNG.

2. Использование встроенной библиотеки phpThumb

Библиотека phpThumb внедрена в ядро MODX. С ней взаимодействуют некоторые бесплатные MODX дополнения, например: pThumb (или его альтернативы phpThumbOf, phpThumbOn). Использовать их можно примерно также как и в первом случае: находим в шаблонах, чанках и т.д. вызовы обычных изображений и заменяем их вот на такие конструкции:

<picture>
   <source srcset="[[+image:pthumb=`w=550&h=400&zc=1&f=webP`]]" type="image/webp">
   <img src="[[+image:pthumb=`w=550&h=400&zc=1&f=webP`]]" alt="Описание изображения">
</picture>

3. Использование готовых решений

В MODX существует несколько готовых решений, которые помогут автоматизировать процесс. Например, можно использовать:

  • webpgenerator — недорогое дополнение (290 р.) для конвертации изображений в формат webp.
  • modxWebpConverter — это бесплатный плагин, который осуществляет конвертацию графических файлов в формат webp.
  • OptiPic CDN — недорогой CDN сервис, который сделает умную конвертацию устаревших форматов изображений в формат WebP на ленту (подключается к MODX с помощью удобного модуля).
  • Ну и если вы ас, можно написать свое решение в виде сниппета или плагина, вот вам пример рабочего кода для вдохновения:
<?php
/**
 * OnManagerPageBeforeRender
 * OnWebPagePrerender
 * OnSiteRefresh
 * 
 * Generate Webp image format
 * 
 * Uses either Imagick or imagewebp to generate webp image
 * 
 * @param string $file Path to image being converted.
 * @param int $compression_quality Quality ranges from 0 (worst quality, smaller file) to 100 (best quality, biggest file).
 * 
 * @return false|string Returns path to generated webp image, otherwise returns false.
 */

if(
	$modx->event->name == 'OnSiteRefresh' ||
	$modx->event->name == 'OnTemplateSave' ||
	$modx->event->name == 'OnChunkSave' ||
	$modx->event->name == 'OnPluginSave' ||
	$modx->event->name == 'OnTemplateVarSave' ||
	$modx->event->name == 'OnDocFormSave' ||
	$modx->event->name == 'OnSnippetSave'
) {
	$options= [xPDO::OPT_CACHE_KEY=>'webp_on_page']; // Clear webp modx cache
	$modx->cacheManager->clean($options);
}

function jcphp01_modx_custom_generate_webp_image($file, $compression_quality = 80)
{
    
    
    $fileWithBasePath = preg_replace("~\/(?!.*\/)(.*)~", '', MODX_BASE_PATH) . $file;
    
    // check if file exists
    if (!file_exists($fileWithBasePath)) {
        return false;
    }

    // If output file already exists return path
    $output_file = $file . '.webp';
    $outputFileWithBasePath = $fileWithBasePath . '.webp';
    
    if (file_exists($outputFileWithBasePath)) {
        return $output_file;
    }
    
    
    $file_type = strtolower(pathinfo($fileWithBasePath, PATHINFO_EXTENSION));

    if (function_exists('imagewebp')) {
        
        switch ($file_type) {
            case 'jpeg':
            case 'jpg':
                $image = imagecreatefromjpeg($fileWithBasePath);
                break;

            case 'png':
                $image = imagecreatefrompng($fileWithBasePath);
                imagepalettetotruecolor($image);
                imagealphablending($image, true);
                imagesavealpha($image, true);
                break;

            case 'gif':
                $image = imagecreatefromgif($fileWithBasePath);
                break;
            default:
                return false;
        }

        // Save the image
        $result = imagewebp($image, $outputFileWithBasePath, $compression_quality);
        if (false === $result) {
            return false;
        }

        // Free up memory
        imagedestroy($image);

        return $output_file;
    } elseif (class_exists('Imagick')) {
        $image = new Imagick();
        $image->readImage($fileWithBasePath);

        if ($file_type === 'png') {
            $image->setImageFormat('webp');
            $image->setImageCompressionQuality($compression_quality);
            $image->setOption('webp:lossless', 'true');
        }

        $image->writeImage($outputFileWithBasePath);
        return $output_file;
    }

    return false;
}

function check_image_file_for_webp_converter_custom($img_real, &$webp_on_page){
	static $uniq_imgs= [];
	

	$img_real= trim($img_real);
	if(in_array($img_real, $uniq_imgs)) return;
	$uniq_imgs[]= $img_real;
	
	$ext= strtolower(pathinfo($img_real, PATHINFO_EXTENSION));
	if(
		$ext == 'jpg' ||
		$ext == 'jpeg' ||
		$ext == 'png' 
	) {
		$abs= jcphp01_modx_custom_generate_webp_image($img_real);
		$abs_base= str_replace('//', '/', MODX_BASE_PATH.$abs);

		if( file_exists($abs_base)){
			$webp_on_page[$img_real]= $abs;
		}
	}
}

try{

    if( // replace jpg and png images to webp
    	$modx->event->name == 'OnWebPagePrerender' && 
    	stripos($_SERVER['HTTP_ACCEPT'], 'image/webp') !== false
    ){
        
    	if($disable_replacing_for_logged_user && $modx->user->hasSessionContext('mgr')) return ''; 
    	
    	$options= [xPDO::OPT_CACHE_KEY=>'webp_on_page'];
    	$cache_key= md5(MODX_SITE_URL.$_SERVER['REQUEST_URI']);
    
    	$cached_webp_on_page= $modx->cacheManager->get($cache_key, $options);
    	$output= &$modx->resource->_output;
    
        
    
    	if( empty($cached_webp_on_page) ){
    		$webp_on_page= [];
    		
    		preg_match_all('/<img[^>]+>/i', $output, $result);
    		
    		if(count($result)){ // Search images in img tag
    			foreach($result[0] as $img_tag)	{
    				$img_tag= str_replace("'", '"', $img_tag); // src
    				preg_match('/(src)=("[^"]*")/i', $img_tag, $img[$img_tag]);						
    				$img_real= str_replace('"', '', $img[$img_tag][2]);
    				check_image_file_for_webp_converter_custom($img_real, $webp_on_page);
    				
    				preg_match('/(data-src)=("[^"]*")/i', $img_tag, $img[$img_tag]); // data-src					
    				$img_real= str_replace('"', '', $img[$img_tag][2]);
    				check_image_file_for_webp_converter_custom($img_real, $webp_on_page);
    				
    				preg_match('/(srcset)=("[^"]*")/i', $img_tag, $img[$img_tag]); // srcset
    				$srcset= explode(',', str_replace('"', '', $img[$img_tag][2]));
    				foreach($srcset as $src_item){
    				    $src_a= explode(' ', $src_item);
    				    if(isset($src_a[0]) && !empty($src_a[0])) {
    				        check_image_file_for_webp_converter_custom($src_a[0], $webp_on_page);
    				    } else {
    				        if(isset($src_a[1]) && !empty($src_a[1])) {
    				            check_image_file_for_webp_converter_custom($src_a[1], $webp_on_page);
    				        }
    				    }
    				}
    			}
    		}
    
    		preg_match_all('/url\(([^)]*)"?\)/iu', $output, $result);
    		if(count($result)){ // Search images in url css rules
    			foreach($result[1] as $img_tag)	{
    				if(stripos($img_real, 'data:')) continue;
    				$img_real= str_replace(['"',"'"], '', $img_tag);
    				check_image_file_for_webp_converter_custom($img_real, $webp_on_page);
    			}
    		}
    		
    		$webp_on_page['/webp/webp/']= '/webp/';
    		$webp_on_page['//webp/']= '/webp/';
    		$webp_on_page['.webp.webp']= '.webp';
    		
    		if(count($webp_on_page)) $output= str_replace(array_keys($webp_on_page), array_values($webp_on_page), $output);
    		$modx->cacheManager->set($cache_key, serialize($webp_on_page), 0, $options);
    	} else {
    		$webp_on_page= unserialize($cached_webp_on_page);
    		if(count($webp_on_page)){
    			$output= str_replace(array_keys($webp_on_page), array_values($webp_on_page), $output);
    		}
    	}
    	return '';
    }
    
} catch (Exception $e){
    $modx->log(1, $e);
}

Первые 2 решения работают не на всех хостингах!

Автоматическая конвертация изображений в WebP на сервере

Для тех, кто хочет полностью автоматизировать процесс, можно настроить сервер (например, Nginx или Apache) на автоматическую конвертацию изображений. Это можно сделать с помощью таких инструментов, как Imagick или GD.

Для настройки Nginx, например, можно использовать следующие команды:

location ~* ^.+\.(jpg|jpeg|png)$ {
  add_header Vary Accept;
  try_files $uri.webp $uri =404;
}

Этот код будет автоматически проверять наличие WebP версии изображения и, если она существует, отдавать именно ее.

Для Apache можно использовать директивы в файле .htaccess, чтобы настроить автоматическую подмену изображений на WebP, если они поддерживаются браузером пользователя. Вот пример кода для настройки:

<IfModule mod_rewrite.c>
    RewriteEngine On
    # Проверка поддержки WebP браузером
    RewriteCond %{HTTP_ACCEPT} image/webp
    # Если есть WebP версия, используем её
    RewriteCond %{REQUEST_FILENAME} \.(jpe?g|png)$
    RewriteCond %{DOCUMENT_ROOT}/$1.webp -f
    RewriteRule (.+)\.(jpe?g|png)$ $1.webp [T=image/webp,E=webp,L]
</IfModule>

# Установка заголовков для кеширования и корректного отображения WebP
<IfModule mod_headers.c>
    <FilesMatch "\.(jpe?g|png|webp)$">
        Header append Vary Accept
    </FilesMatch>
</IfModule>

Что делает этот код:

  1. RewriteEngine On — включает механизм переадресации в Apache.
  2. RewriteCond %{HTTP_ACCEPT} image/webp — проверяет, поддерживает ли браузер формат WebP.
  3. RewriteCond %{REQUEST_FILENAME} .(jpe?g|png)$ — проверяет, что исходный файл имеет расширение .jpg, .jpeg или .png.
  4. RewriteCond %{DOCUMENT_ROOT}/$1.webp -f — проверяет, существует ли WebP-версия изображения.
  5. RewriteRule (.+).(jpe?g|png)$ $1.webp [T=image/webp,E=webp,L] — если WebP-версия существует, она будет отдана браузеру.
  6. Header append Vary Accept — добавляет заголовок Vary, чтобы сервер корректно понимал запросы WebP.

Этот код настроит автоматическую подмену изображений на WebP для тех браузеров, которые поддерживают этот формат, без необходимости менять HTML-код сайта.

Тестирование и оптимизация сайта

После внедрения WebP важно проверить, как изменились показатели вашего сайта. Для этого можно воспользоваться следующими инструментами:

  • Google PageSpeed Insights – оценка производительности сайта.
  • Lighthouse – встроенный инструмент в браузере Chrome, который анализирует скорость загрузки страниц.

Эти инструменты позволят вам увидеть, насколько уменьшилось время загрузки страниц после внедрения WebP, и помогут оценить, насколько улучшились показатели Core Web Vitals.

Заключение

Оптимизация изображений с помощью WebP – это один из самых простых и эффективных способов ускорить сайт на MODX. Уменьшение размера изображений снижает нагрузку на сервер, ускоряет загрузку страниц и улучшает пользовательский опыт. Благодаря интеграции WebP ваш сайт станет быстрее и более эффективным, что положительно скажется как на его SEO, так и на общем восприятии пользователями.

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

Поделиться с друзьями
Алексей

Веб-дизайнер и SEO оптимизатор. Занимаюсь созданием сайтов с 2010 года и их продвижение с 2012 года!

Оцените автора
( 2 оценки, среднее 3.5 из 5 )
Web-Revenue.ru
Добавить комментарий