Bis heute (Version 5.5.7) besteht ein Bug im Mediaoptimizer. Dadurch werden beim optimieren von Bildern über sw:media:optimize keine Bilder optimiert. Ihr bekommt das auch leider nicht durch einen Error oder Warning mit, sondern nur wenn Ihr tatsächlich mal die Bilder vor und nach dem optimieren prüft.
Bild-Optimierung
Ich habe schon einmal über die Bildoptimierung in Shopware geschrieben und gehe daher nicht näher auf die Details und Funktionen ein. Der Beitrag bezieht sich auf jedes Setup welches einen anderen Adapter als „local“ benutzt. In meinem Fall ist es der S3 Adapter von Amazon.
php bin/console sw:media:optimize media/image/0a/02/df -f
Bei dem Befehl werden nur Bilder in media/image/0a/02/df optimiert und mit -f wird die Abfrage ob man dies auch wirklich machen möchte (kann etwas dauern, da die Dateien erst vom S3 auf den Server geschrieben, dann optimiert und wieder hochgeladen werden).
Problem
Beim ausführen des Befehls wurde statt updateStream() -> writeStream() benutzt. Die File existierte da bereits und wurde nicht geupdated (da nur bei neuen Files erlaubt). Vielen Dank an Shyim für das herausfinden (siehe Shopwareforum). Möchte hier keine Lorbeeren sammeln, sondern einfach Shopware-Nutzer darauf hinweisen 🙂
Fix
Ich gehe davon aus, dass der Bugfix im nächsten Patch Release gefixt wird, aber hier dennoch ein Quickfix für alle die noch nicht updaten können oder wollen:
engine/Shopware/Bundle/MediaBundle/CdnOptimizerService.php
/**
* {@inheritdoc}
*/
public function optimize($filepath)
{
// If the file is on the local filesystem we can optimize it directly
if ($this->mediaService->getAdapterType() === 'local') {
$this->optimizerService->optimize($filepath);
return;
}
// Generate unique temporary file name
$tempFileName = uniqid('CdnOptimizerTemp-', true);
$mediaServiceAdapter = $this->mediaService->getFilesystem();
try {
// Load file from remote filesystem, optimize it and upload it back again.
$this->filesystem->writeStream($tempFileName, $mediaServiceAdapter->readStream($filepath));
$this->optimizerService->optimize(sys_get_temp_dir() . '/' . $tempFileName);
$mediaServiceAdapter->updateStream($filepath, $this->filesystem->readStream($tempFileName));
} catch (\League\Flysystem\Exception $exception) {
throw $exception;
} finally {
try {
$this->filesystem->delete($tempFileName);
} catch (\Exception $exception) {
// Empty catch intended, an exception thrown here could hide possible other exception.
}
}
}
engine/Shopware/Bundle/MediaBundle/Adapters/AwsS3v3Factory.php
/**
* @param array $definition
*
* @return array
*/
private function resolveS3Options(array $definition)
{
$options = new OptionsResolver();
$options->setRequired(['credentials', 'bucket', 'region']);
$options->setDefined(['version', 'root', 'type', 'mediaUrl', 'url', 'endpoint']);
$options->setDefined(['version', 'root', 'type', 'mediaUrl', 'url', 'endpoint', 'use_path_style_endpoint']);
$options->setAllowedTypes('credentials', 'array');
$options->setAllowedTypes('region', 'string');
$options->setAllowedTypes('version', 'string');
$options->setAllowedTypes('root', 'string');
$options->setDefault('version', 'latest');
$options->setDefault('root', '');
$options->setDefault('endpoint', null);
$config = $options->resolve($definition);
$config['credentials'] = $this->resolveCredentialsOptions($config['credentials']);
return $config;
}
Was bringt sowas überhaupt?
Diese Optimierung hat bei einem Kunden in dem Fall über 2 Gigabyte von 25 GB eingespart (exakt 8,3%) . Im Schnitt wurde der Pagespeed Score damit um gute 2-6 % nach oben gebracht. Ist also auf jeden Fall empfehlenswert.