SW Shopware 6 Intermédiaire

DataFirefly Image Optimizer — Documentation Shopware 6

Installation, configuration WebP/AVIF, intégration CDN, API Twig et dépannage du plugin Image Optimizer pour Shopware 6.6 et 6.7.

Mis à jour Version du module 1.0.0

DataFirefly Image Optimizer transforme automatiquement chaque image média Shopware en variantes WebP et AVIF, recompresse les JPEG et PNG d’origine, et réécrit les URLs vers votre CDN — sans modification de thème. Cette documentation couvre l’installation, la configuration complète, l’API Twig exposée aux thèmes, et le dépannage.

Installation

Le plugin est livré sous forme de ZIP. Deux méthodes d’installation, équivalentes fonctionnellement.

Via l’administration Shopware

  1. Réglages → Système → Extensions → Téléverser une extension
  2. Sélectionnez DfImageOptimizer-1.0.0.zip
  3. Cliquez sur Installer puis Activer
  4. Vider le cache : Réglages → Système → Cache & Index → Vider

Via CLI (recommandé)

cd /chemin/vers/shopware
unzip DfImageOptimizer-1.0.0.zip -d custom/plugins/

sudo -u www-data setsid php bin/console plugin:refresh
sudo -u www-data setsid php bin/console plugin:install --activate DfImageOptimizer
sudo -u www-data setsid php bin/console cache:clear
sudo -u www-data setsid php bin/console theme:compile
Astuce. theme:compile est obligatoire après installation pour que l’override Twig du composant thumbnail soit actif sur le storefront. Sans cette étape, les balises <picture> ne seront pas générées même si WebP et AVIF sont produits.

Vérification post-installation

Allez dans le menu admin Catalogues → Image Optimizer. Le dashboard doit s’afficher avec une carte Compatibilité serveur indiquant en temps réel :

  • Version PHP détectée (8.2 minimum)
  • Présence d’Imagick (recommandé)
  • Présence de GD (obligatoire)
  • Support effectif WebP — doit être ✓
  • Support effectif AVIF — peut être ✗ selon le serveur, pas bloquant
  • Moteur recommandé : Imagick ou GD

Architecture en deux mots

Quand une image est uploadée, le plugin écoute l’événement entity media.written, charge l’image dans un fichier temporaire local, puis produit en parallèle :

  • L’original recompressé (remplace le fichier d’origine si Compresser original est coché)
  • Un sibling WebP à côté avec extension cumulée : foo.jpgfoo.jpg.webp
  • Un sibling AVIF à côté : foo.jpgfoo.jpg.avif

Les vignettes Shopware générées par le ThumbnailService natif sont traitées de la même manière. Côté storefront, l’override Twig de storefront/component/image/thumbnail.html.twig wrappe la balise <img> dans un <picture> avec sources AVIF, WebP, et fallback original — le navigateur choisit automatiquement le format le plus léger qu’il supporte.

Configuration

Accès : Réglages → Système → Extensions → DfImageOptimizer → Configurer. Sept cartes regroupent les options.

Carte « Général »

Option Défaut Effet
Auto-optimisation à l’upload Activé Déclenche le pipeline immédiatement à chaque upload. Désactivez si vous préférez tout faire en arrière-plan via le cron.
Traiter les vignettes Activé Génère WebP/AVIF aussi pour les vignettes Shopware (typiquement 4 à 6 tailles par image source).

Carte « WebP »

Option Défaut Recommandation
Activer WebP Activé À garder activé sauf cas très spécifique. WebP est supporté par 96 % des navigateurs.
Qualité WebP (1-100) 82 75-85 pour un bon compromis. 90+ pour photographie haut de gamme, 70 pour catalogue volumineux.
Lossless pour PNG Désactivé Activez seulement si vos PNG contiennent du texte ou des graphiques nets (logos, icônes). Sinon le mode lossy donne de meilleurs gains.

Carte « AVIF »

Option Défaut Recommandation
Activer AVIF Désactivé Activez si le dashboard indique que votre serveur supporte AVIF. Gain typique de 50 % vs JPEG, mais encodage plus lent que WebP.
Qualité AVIF (1-100) 55 45-65 pour un excellent rendu. AVIF tolère des qualités plus basses que JPEG/WebP grâce à son codec moderne.
Largeur max pour AVIF (px) 2400 Garde-fou CPU. Les images au-delà sont sautées pour AVIF mais conservent leur WebP. Augmentez si vous avez un serveur puissant et besoin d’AVIF sur grandes images.
À propos d’AVIF. L’encodage AVIF nécessite soit PHP 8.1+ avec le flag IMG_AVIF compilé, soit Imagick avec libheif. Le dashboard Compatibilité serveur vous indique exactement ce qui est disponible. Si AVIF n’est pas supporté, l’option reste inopérante même cochée — pas d’erreur, juste pas de génération AVIF.

Carte « Compression »

Option Défaut Recommandation
Compresser les JPG/PNG originaux Activé Remplace l’original par sa version recompressée. Action irréversible — désactivez si vous voulez conserver les sources brutes pour des retouches futures.
Qualité JPEG (1-100) 85 85 est le standard photo web. Descendre à 80 pour gain supplémentaire si la qualité reste acceptable visuellement.
Niveau de compression PNG (0-9) 7 9 = compression maximale mais 3-4× plus lente. 7 est l’équilibre standard.
Supprimer les métadonnées EXIF/ICC Activé Gain typique 5 à 30 Ko par photo issue d’appareil. Conservez si vous gérez du contenu nécessitant des profils colorimétriques précis.

Carte « CDN »

Option Défaut Explication
Activer la réécriture CDN Désactivé Si désactivé, les URLs pointent vers votre origine. Activez après avoir configuré votre CDN.
URL de base du CDN Format : https://cdn.exemple.com sans slash final. Ex : https://shop-cdn.b-cdn.net pour BunnyCDN.
Portée de réécriture Médias uniquement Voir détail ci-dessous.
Conserver les query strings Activé Préserve les paramètres de cache-busting (?v=1234) lors de la réécriture.

Détail des trois portées :

  • Médias uniquement — réécrit uniquement les URLs commençant par /media/. C’est le plus sûr et couvre 95 % des cas d’usage typiques.
  • Médias + vignettes — ajoute /thumbnail/. Utile si votre storefront sert beaucoup de vignettes générées dynamiquement.
  • Tous les assets statiques — ajoute /theme/, /bundles/ et /assets/. Ne choisissez cette option que si votre CDN est correctement configuré pour pull-cache tous les assets et que vous avez testé en staging.

Carte « Rendu frontend »

Option Défaut Effet
Sortie en balise <picture> Activé Wrappe les <img> du storefront dans un <picture> avec sources AVIF/WebP.
Ajouter loading="lazy" Activé Lazy-loading natif navigateur. À conserver sauf si vous avez votre propre solution.
Ajouter decoding="async" Activé Permet au navigateur de décoder en parallèle du parsing HTML.
Forcer width/height Activé Anti-CLS (Cumulative Layout Shift). Le navigateur réserve la place du visuel avant son chargement.

Carte « Traitement en lot »

Option Défaut Recommandation
Taille de lot pour la tâche cron 50 50 est un bon équilibre. Montez à 100-200 si vous avez besoin de rattraper un gros catalogue rapidement et que votre serveur tient.
Intervalle cron (minutes) 15 Information seule — l’intervalle réel est défini par la classe OptimizeImagesTask::getDefaultInterval(). Pour changer effectivement, modifiez la valeur dans la table scheduled_task ou réinstallez le plugin après modification.

Configurer un CDN — exemples concrets

BunnyCDN (recommandé)

  1. Créez une Pull Zone sur bunny.net avec votre URL d’origine, par exemple https://shop.exemple.com
  2. BunnyCDN vous donne un hostname du type shop-cdn.b-cdn.net
  3. Dans la config du plugin, mettez : https://shop-cdn.b-cdn.net
  4. Choisissez la portée Médias uniquement pour démarrer
  5. Activez la réécriture CDN

Le plugin injecte automatiquement <link rel="dns-prefetch" href="https://shop-cdn.b-cdn.net"> et <link rel="preconnect" href="https://shop-cdn.b-cdn.net" crossorigin> dans le <head> du storefront — gain de 50 à 200 ms sur la première requête CDN.

Cloudflare

Cloudflare en mode proxy DNS standard ne nécessite pas de réécriture CDN — Cloudflare cache automatiquement sur votre hostname principal. Mais si vous utilisez un Custom Hostname Cloudflare dédié pour les assets (par exemple cdn.exemple.com), configurez-le ici. Activez aussi Cache Reserve ou Polish côté Cloudflare pour bénéficier en plus de l’optimisation Cloudflare par-dessus la vôtre.

KeyCDN

Configuration identique à BunnyCDN : créez une Pull Zone, récupérez l’URL du type shop-12345.kxcdn.com, configurez-la dans le plugin avec le préfixe https://.

AWS CloudFront

Créez une distribution CloudFront avec votre serveur Shopware comme origine. L’URL de distribution est du type https://d1234abc.cloudfront.net — ou votre domaine personnalisé si vous avez configuré un alias. Configurez le TTL minimum à 1 jour pour profiter pleinement du cache.

Pipeline d’optimisation détaillé

Pour chaque image (originale ou vignette) à traiter, le plugin exécute les étapes suivantes dans l’ordre :

  1. Téléchargement de l’image source depuis le filesystem public Shopware vers un fichier temporaire local (/tmp/dfimgopt_xxx.jpg)
  2. Si Compresser original activé : recompression in-place avec qualité configurée, suppression métadonnées si activé. Si la version recompressée est plus petite que l’originale, elle remplace le fichier d’origine sur le filesystem.
  3. Si WebP activé : conversion vers WebP, écriture du sibling foo.jpg.webp sur le filesystem public
  4. Si AVIF activé et largeur ≤ largeur max : conversion vers AVIF, écriture du sibling foo.jpg.avif
  5. Enregistrement dans la table df_image_optimizer avec compteurs et taille économisée
  6. Nettoyage du fichier temporaire local via bloc finally (même en cas d’erreur)

Imagick est utilisé en priorité quand disponible (qualité supérieure et seul moteur AVIF via libheif sur de nombreux serveurs). GD prend le relais sinon — il supporte WebP depuis longtemps et AVIF depuis PHP 8.1.

Compression du JPEG original — irréversible. Quand l’option Compresser original est cochée, la version compressée remplace l’originale sur le filesystem. Si vous avez besoin de retrouver les sources brutes pour d’autres usages (impression, retouches), désactivez cette option — vous garderez quand même les gains via WebP et AVIF.

Tâche planifiée — rattrapage des images existantes

Activer le plugin sur une boutique avec déjà des milliers d’images en base ne déclenche pas l’optimisation rétroactive. C’est intentionnel : convertir 50 000 images en AVIF d’un coup saturerait votre serveur. À la place, la tâche planifiée df_image_optimizer.optimize_pending s’exécute toutes les 15 minutes par défaut :

  1. Requête SQL via LEFT JOIN sur df_image_optimizer pour identifier les médias non encore optimisés
  2. Traite un lot de 50 images (taille de lot configurable)
  3. Termine et libère le worker pour la prochaine tâche

Sur une boutique de 10 000 images, comptez environ 50 heures pour tout rattraper en arrière-plan. Pour accélérer :

  • Augmentez la taille de lot dans la config (essayez 100 ou 200)
  • Utilisez le bouton Lancer un lot du dashboard plusieurs fois d’affilée
  • Exécutez la tâche en boucle manuellement via CLI :
    for i in {1..100}; do sudo -u www-data setsid php bin/console scheduled-task:run-single df_image_optimizer.optimize_pending; done

API Twig exposée aux thèmes

Deux helpers Twig sont enregistrés et utilisables dans n’importe quel template de thème ou plugin.

Filtre |df_cdn

Réécrit une URL vers le CDN si activé, sinon retourne l’URL inchangée. Utile pour les assets que vous incluez manuellement.

<img src="{{ media.url|df_cdn }}" alt="...">
<link rel="preload" as="image" href="{{ heroImage.url|df_cdn }}">
<style>
    .hero { background-image: url("{{ bgImage.url|df_cdn }}"); }
</style>

Fonction df_picture()

Rend une balise <picture> complète avec sources AVIF, WebP et fallback original, plus tous les attributs configurés (lazy, async, width/height).

{{ df_picture(
    media,
    alt='Description accessible',
    classes='product-image card-img',
    sizes='(max-width: 768px) 100vw, 50vw'
) }}

Génère :

<picture>
    <source type="image/avif"
            srcset="https://cdn.exemple.com/media/foo.jpg.avif"
            sizes="(max-width: 768px) 100vw, 50vw">
    <source type="image/webp"
            srcset="https://cdn.exemple.com/media/foo.jpg.webp"
            sizes="(max-width: 768px) 100vw, 50vw">
    <img src="https://cdn.exemple.com/media/foo.jpg"
         alt="Description accessible"
         class="product-image card-img"
         sizes="(max-width: 768px) 100vw, 50vw"
         loading="lazy"
         decoding="async"
         width="1200"
         height="800">
</picture>

Endpoints API admin

Trois endpoints REST sont disponibles, authentifiés via le Bearer token admin standard.

Méthode Route Description
GET /api/_action/df-image-optimizer/stats Vue d’ensemble + activité 30j + capacités serveur
POST /api/_action/df-image-optimizer/run-batch Lance un lot. Paramètre POST optionnel batchSize (défaut 50, max 500)
GET /api/_action/df-image-optimizer/capabilities Détection serveur (Imagick / GD / WebP / AVIF)

Exemple curl :

TOKEN=$(curl -s -X POST https://shop.exemple.com/api/oauth/token 
    -H "Content-Type: application/json" 
    -d '{"grant_type":"password","client_id":"administration","scope":"write","username":"admin","password":"shopware"}' 
    | jq -r .access_token)

curl -X POST https://shop.exemple.com/api/_action/df-image-optimizer/run-batch 
    -H "Authorization: Bearer $TOKEN" 
    -H "Content-Type: application/json" 
    -d '{"batchSize":200}'

Tables créées

df_image_optimizer

Une ligne par média optimisé. Clé unique sur media_id — une nouvelle optimisation du même média écrase la ligne.

id                BINARY(16)   UUID
media_id          BINARY(16)   FK media.id ON DELETE CASCADE, UNIQUE
has_webp          TINYINT(1)
has_avif          TINYINT(1)
compressed        TINYINT(1)
original_size     BIGINT       Poids original en octets
bytes_saved       BIGINT       Cumul économies (compression + delta WebP/AVIF)
sales_channel_id  BINARY(16)   FK sales_channel.id ON DELETE SET NULL
optimized_at      DATETIME(3)
created_at        DATETIME(3)

df_image_optimizer_log

Journal optionnel des erreurs. Lecture seule pour le debug — pas de purge automatique.

Dépannage

« Le dashboard affiche AVIF : Indisponible »

Votre serveur n’a pas la stack AVIF requise. Options :

  • Si GD-only : vérifiez php -m | grep gd et php -i | grep AVIF. Il faut PHP 8.1+ et GD compilé avec --with-avif. Sur Debian/Ubuntu récents, c’est par défaut.
  • Si Imagick disponible : vérifiez php -r "print_r(Imagick::queryFormats('AVIF'));". Vide ? Votre Imagick n’est pas compilé avec libheif — recompilation nécessaire ou passage à GD.
  • Fallback acceptable : laissez AVIF désactivé et concentrez-vous sur WebP. Le gain de WebP seul est déjà énorme par rapport au JPEG natif Shopware.

« Les images .webp sont bien générées mais le storefront affiche du JPEG »

Le compilateur de thème n’a pas pris en compte l’override Twig. Solution :

sudo -u www-data setsid php bin/console theme:compile
sudo -u www-data setsid php bin/console cache:clear

Vérifiez ensuite avec les DevTools du navigateur (Chrome ou Firefox) : ouvrez l’onglet Réseau, rechargez une page produit, et regardez le type MIME des images chargées. Vous devriez voir image/avif ou image/webp au lieu de image/jpeg.

« L’upload des médias est devenu lent »

La conversion AVIF en particulier est CPU-intensive — comptez 1 à 3 secondes par image. Si c’est gênant, désactivez l’auto-optimisation à l’upload (carte Général) et laissez uniquement la tâche planifiée traiter en arrière-plan. Les uploads redeviennent instantanés et les images sont optimisées sous 15 minutes max.

« Les vignettes .webp ne sont pas générées »

Vérifiez que Traiter les vignettes est coché dans la carte Général. Régénérez ensuite manuellement les vignettes pour qu’elles repassent dans le pipeline :

sudo -u www-data setsid php bin/console media:generate-thumbnails

« Comment vider tous les fichiers WebP/AVIF générés ? »

Le plugin ne les supprime pas automatiquement, même à la désinstallation (pour préserver vos sauvegardes). Pour les nettoyer manuellement :

cd /chemin/vers/shopware
find public/media -name "*.webp" -delete
find public/media -name "*.avif" -delete

« Les URLs CDN ne sont pas appliquées partout »

Vérifiez la portée configurée. Si vous voyez des URLs origine pour des assets de thème (/theme/.../style.css), c’est normal avec la portée par défaut Médias uniquement. Passez à Tous les assets statiques si votre CDN est configuré pour servir tous les assets.

Notez aussi que les URLs réécrites concernent le rendu Twig serveur. Si votre frontend appelle l’API Store-API et reconstruit les URLs côté JS, vous devrez appliquer la réécriture côté client séparément.

Désinstallation

sudo -u www-data setsid php bin/console plugin:uninstall DfImageOptimizer
sudo -u www-data setsid php bin/console plugin:remove DfImageOptimizer

Lors de la désinstallation, Shopware demande si vous voulez conserver les données utilisateur :

  • Conserver (par défaut) : les tables df_image_optimizer et df_image_optimizer_log restent en base. Réinstaller le plugin reprendra l’historique.
  • Ne pas conserver : les deux tables sont supprimées (DROP TABLE).

Dans les deux cas, les fichiers .webp et .avif sur le filesystem restent — utilisez les commandes find ci-dessus pour les nettoyer si nécessaire.

Pour aller plus loin

  • Surveillez votre score Core Web Vitals dans Google Search Console — le LCP doit baisser dans les 2 à 4 semaines suivant l’activation
  • Testez avec PageSpeed Insights avant/après — gain typique 20 à 40 points sur mobile
  • Activez aussi un outil HTTP/2 ou HTTP/3 côté serveur pour multiplier le bénéfice du CDN
  • Combinez avec un cache plein page Shopware pour des temps de réponse statiques
Cette page vous a-t-elle été utile ?

Toujours bloqué ? Contactez le support