webp Optimierung für alle – mit Fallback
Wer ohne lästige Plugins für nahezu alle Online-Shops und Webanwendungen wie WordPress zügig auf webp-Dateien umstellen möchte steht vor zwei Problemen. Darunter die schiere Menge an Dateien und natürlich das Problem mit der Rückwärtskompatabilität mit älteren Browsern und Geräten.
Nach einigen Tests kann ich heute eine praktische Lösung für nahezu alle Systeme vorstellen. Hierzu wird lediglich die .htaccess Datei angepasst und ein PHP-Script zur Generierung der webp-Dateien verwendet.
Das PHP-Script benötigt eine ausreichend lange Ausführungszeit. Es erstellt in allen Ordnern eine webp-Datei für jede Bilddatei. Bei einigen Bilddateien funktioniert dies jedoch nicht.
Ich empfehle auf jeden Fall Backups und ausreichende Tests vor einem produktiven Einsatz.
PHP-Script:
<?php
ini_set('opcache.enable', 0);
ini_set('opcache.enable_cli', 0);
$allowed_file_types = array('jpg', 'jpeg', 'png');
$webp_quality = 80;
function create_webp($source, $destination, $quality) {
try {
$image = imagecreatefromstring(file_get_contents($source));
if (!$image) {
error_log('Failed to create image resource from file: ' . $source);
return false;
}
if (!imageistruecolor($image)) {
// Skip paletted images
error_log('Skipping paletted image: ' . $source);
imagedestroy($image);
return false;
}
if (file_exists($destination) && !unlink($destination)) {
chmod($destination, 0755); // Set file permission to 755
error_log('Failed to remove existing WebP file: ' . $destination);
imagedestroy($image);
return false;
}
if (preg_match('/\.png$/i', $source)) {
$tmp_png = tempnam(sys_get_temp_dir(), 'png');
if (!$tmp_png || !imagepng($image, $tmp_png)) {
error_log('Failed to write PNG file to disk: ' . $tmp_png);
imagedestroy($image);
return false;
}
$image = imagecreatefrompng($tmp_png);
if (!$image) {
error_log('Failed to create image resource from PNG file: ' . $tmp_png);
unlink($tmp_png);
return false;
}
unlink($tmp_png);
}
$result = imagewebp($image, $destination, $quality);
imagedestroy($image);
if (!$result) {
error_log('Failed to create WebP file: ' . $destination);
return false;
}
} catch (Exception $e) {
error_log('Caught exception while converting image: ' . $source . ' (' . $e->getMessage() . ')');
return false;
}
if (!file_exists($destination)) {
error_log('WebP file not created: ' . $destination);
return false;
}
return true;
}
function scan_directory($directory, $allowed_file_types, $webp_quality) {
$files = scandir($directory);
foreach ($files as $file) {
$file_path = $directory . '/' . $file;
if (is_file($file_path) && in_array(pathinfo($file_path, PATHINFO_EXTENSION), $allowed_file_types)) {
$webp_path = pathinfo($file_path, PATHINFO_DIRNAME) . '/' . pathinfo($file_path, PATHINFO_FILENAME) . '.webp';
if (!file_exists($webp_path)) {
create_webp($file_path, $webp_path, $webp_quality);
}
} elseif (is_dir($file_path) && $file != '.' && $file != '..') {
scan_directory($file_path, $allowed_file_types, $webp_quality);
}
}
}
scan_directory('.', $allowed_file_types, $webp_quality);
echo 'done';
?>
Die .htaccess Datei prüft ob der Browser webp unterstützt und ob eine webp-Datei vorhanden ist.
<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|gif)$ $1.webp [T=image/webp,E=REQUEST_image]
</IfModule>
<IfModule mod_headers.c>
# Vary: Accept for all the requests to jpeg, png and gif
Header append Vary Accept env=REQUEST_image
</IfModule>
<IfModule mod_mime.c>
AddType image/webp .webp
</IfModule>
Der .htaccess Part stammt von https://github.com/vincentorback/WebP-images-with-htaccess