В данной статье приведены примеры как сделать подгрузку WebP вместо jpg и png в тех браузерах где он поддерживается.
Самый быстрый способ – конвертировать изображения с помощью утилиты cwebp (если он установлен на сервере) через SSH.
Нужно выполнить следующую команду, например через PuTTY, которая найдет все файлы изображений и сгенерирует рядом с ними файлы WebP.
find /public_html/www -iname '*.jpg' -o -iname '*.jpeg' -o -iname '*.png' -exec sh -c 'cwebp -lossless $1 -o "${1%.*}.webp"' _ {} \;
/public_html/www
– директория, в которой будет осуществляться поиск. Если указать ./
то поиск и конвертация пройдет на всем сервере.
Если сайт очень редко обновляется, то можно выкачивать весь сайт по FTP, конвертировать изображение и закачать обратно.
Пакетно перекодировать изображения можно с помощью программы XnConvert.
Еще один вариант конвертации – PHP-скрипт, который вызывается по URL на несуществующий файл *.webp, ищет в той же директории файл с расширением png или jpg и создает из него файл WebP.
Главное чтобы на хостинге была установлена библиотека GD версией не ниже 2.2.5, т.к. в более ранних версиях у WebP нет поддержки прозрачности при конвертации из PNG.
Посмотреть версию GD можно в phpinfo()
:
Для работы скрипта нужно добавить правило в корневой файл .httaccess.
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} /uploads/.*?\.webp$
RewriteRule ^(.*)$ auto-webp.php [L]
auto-webp.php
<?php
//phpinfo();
/* Путь до корневой директории сайта */
$base_dir = __DIR__;
if (!empty($_SERVER['REQUEST_URI']) && !is_file($base_dir . $_SERVER['REQUEST_URI'])) {
/* Разбор полученного URL */
$url = explode('?', trim($_SERVER['REQUEST_URI'], '/'));
$new = $base_dir . '/' . $url[0];
$file = preg_replace('/\.webp$/', '', $new);
// Поиск оригинального файла (png или jpg), с учетом регистра.
$src = '';
foreach (array('PNG', 'PNG', 'jpg', 'JPG', 'jpeg', 'JPEG', 'png') as $row) {
if (is_file($file . '.' . $row)) {
$src = $file . '.' . $row;
break;
}
}
// Преобразование
if (!empty($src)) {
$img = false;
$info = getimagesize($src);
switch ($info[2]) {
case 2:
$img = imageCreateFromJpeg($src);
imageWebp($src, $new, 100);
imagedestroy($img);
break;
case 3:
$img = imageCreateFromPng($src);
imagepalettetotruecolor($img);
imagealphablending($img, true);
imagesavealpha($img, true);
imageWebp($img, $new, 100);
imagedestroy($img);
break;
}
if ($img) {
//fix for corrupted WEBPs
if (filesize($new) % 2 == 1) {
file_put_contents($new, "\0", FILE_APPEND);
}
// Вывод webp в браузер
header('Content-Length: ' . filesize($new));
readfile($new);
exit();
}
}
}
header('HTTP/1.0 404 Not Found');
exit();
После выбора метода и генерации изображений встает вопрос о выводе их на сайте, специально для этого есть элементы <picture>
и <source>
, которые дают возможность браузеру выбрать более подходящее для него формат.
По спецификации изображение WebP правильно вывести в таком виде, с дублированием основного изображения.
<picture>
<source type="image/webp" srcset="/image.webp">
<source type="image/png" srcset="/image.png">
<img src="/image.png" alt="">
</picture>
Но во всех браузерах работает и так:
<picture>
<source type="image/webp" srcset="/image.webp">
<img src="/image.png" alt="">
</picture>
<?php
$img = '/uploads/image.png';
$webp = preg_replace('".(jpg|jpeg|png)$"', '.webp', $img);
?>
<picture>
<source type="image/webp" srcset="<?php echo $webp; ?>">
<img src="<?php echo $img; ?>" alt="">
</picture>
Второй вариант – полная замена расширений в тегах <img>
если браузер передал в user agent что поддерживает WebP с помощью PHP буферизации и её функции обратного вызова.