SW Shopware 6 Średnio zaawansowany

DataFirefly Image Optimizer: dokumentacja Shopware 6

Instalacja, konfiguracja WebP/AVIF, integracja CDN, API Twig i rozwiązywanie problemów pluginu Image Optimizer dla Shopware 6.6 i 6.7.

Zaktualizowano Wersja modułu 1.0.0

DataFirefly Image Optimizer automatycznie przekształca każdy obraz media Shopware w warianty WebP i AVIF, ponownie kompresuje oryginalne pliki JPEG i PNG oraz przepisuje adresy URL na Twój CDN, bez modyfikowania motywu. Ta dokumentacja obejmuje instalację, pełną konfigurację, API Twig udostępniane motywom i rozwiązywanie problemów.

Instalacja

Plugin jest dostarczany jako ZIP. Dwie metody instalacji, równoważne funkcjonalnie.

Przez administrację Shopware

  1. Ustawienia → System → Rozszerzenia → Prześlij rozszerzenie
  2. Wybierz DfImageOptimizer-1.0.0.zip
  3. Kliknij Zainstaluj, a następnie Aktywuj
  4. Wyczyść cache: Ustawienia → System → Cache i indeksy → Wyczyść

Przez CLI (zalecane)

cd /path/to/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
Wskazówka. theme:compile jest obowiązkowe po instalacji, aby override Twig komponentu thumbnail był aktywny w storefroncie. Bez tego kroku znaczniki <picture> nie będą generowane, nawet jeśli WebP i AVIF powstają.

Weryfikacja po instalacji

Wejdź w menu administracji Katalogi → Image Optimizer. Pulpit powinien się wyświetlić z kartą Zgodność serwera pokazującą w czasie rzeczywistym:

  • Wykrytą wersję PHP (minimum 8.2)
  • Obecność Imagick (zalecane)
  • Obecność GD (obowiązkowe)
  • Faktyczne wsparcie WebP, powinno być ✓
  • Faktyczne wsparcie AVIF, może być ✗ zależnie od serwera, nie blokuje działania
  • Zalecany silnik: Imagick albo GD

Architektura w dwóch słowach

Gdy obraz jest przesyłany, plugin nasłuchuje zdarzenia encji media.written, wczytuje obraz do lokalnego pliku tymczasowego, a następnie równolegle tworzy:

  • Ponownie skompresowany oryginał (zastępuje plik źródłowy, jeśli Kompresuj oryginał jest zaznaczone)
  • Bliźniaczy plik WebP obok, z kumulowanym rozszerzeniem: foo.jpgfoo.jpg.webp
  • Bliźniaczy plik AVIF obok: foo.jpgfoo.jpg.avif

Miniatury Shopware generowane przez natywny ThumbnailService są przetwarzane tak samo. Po stronie storefrontu override Twig pliku storefront/component/image/thumbnail.html.twig opakowuje znacznik <img> w <picture> ze źródłami AVIF, WebP i oryginalnym fallbackiem: przeglądarka automatycznie wybiera najlżejszy format, który obsługuje.

Konfiguracja

Dostęp: Ustawienia → System → Rozszerzenia → DfImageOptimizer → Konfiguruj. Opcje są zebrane w siedmiu kartach.

Karta “Ogólne”

Opcja Domyślnie Efekt
Autooptymalizacja przy przesyłaniu Włączone Uruchamia pipeline natychmiast przy każdym przesłaniu. Wyłącz, jeśli wolisz robić wszystko w tle przez cron.
Przetwarzaj miniatury Włączone Generuje WebP/AVIF także dla miniatur Shopware (zwykle od 4 do 6 rozmiarów na obraz źródłowy).

Karta “WebP”

Opcja Domyślnie Zalecenie
Włącz WebP Włączone Zostaw włączone poza bardzo specyficznymi przypadkami. WebP jest obsługiwany przez 96% przeglądarek.
Jakość WebP (1-100) 82 75-85 to dobry kompromis. 90+ dla fotografii premium, 70 dla bardzo dużych katalogów.
Bezstratny dla PNG Wyłączone Włącz tylko wtedy, gdy Twoje pliki PNG zawierają tekst albo ostrą grafikę (logotypy, ikony). W przeciwnym razie tryb stratny daje lepsze zyski.

Karta “AVIF”

Opcja Domyślnie Zalecenie
Włącz AVIF Wyłączone Włącz, jeśli pulpit wskazuje, że Twój serwer obsługuje AVIF. Typowy zysk 50% wobec JPEG, ale kodowanie wolniejsze niż WebP.
Jakość AVIF (1-100) 55 45-65 dla doskonałego efektu. AVIF toleruje niższe jakości niż JPEG/WebP dzięki nowoczesnemu kodekowi.
Maksymalna szerokość dla AVIF (px) 2400 Zabezpieczenie CPU. Obrazy powyżej są pomijane przy AVIF, ale zachowują swój WebP. Zwiększ, jeśli masz mocny serwer i potrzebujesz AVIF na dużych obrazach.
O AVIF. Kodowanie AVIF wymaga albo PHP 8.1+ ze skompilowaną flagą IMG_AVIF, albo Imagick z libheif. Pulpit Zgodność serwera pokazuje dokładnie, co jest dostępne. Jeśli AVIF nie jest obsługiwany, opcja pozostaje bezskuteczna nawet po zaznaczeniu: bez błędu, po prostu bez generowania AVIF.

Karta “Kompresja”

Opcja Domyślnie Zalecenie
Kompresuj oryginalne JPG/PNG Włączone Zastępuje oryginał wersją ponownie skompresowaną. Działanie nieodwracalne: wyłącz, jeśli chcesz zachować surowe źródła do przyszłych retuszy.
Jakość JPEG (1-100) 85 85 to standard fotografii webowej. Zejście do 80 daje dodatkowy zysk, jeśli jakość pozostaje wizualnie akceptowalna.
Poziom kompresji PNG (0-9) 7 9 = kompresja maksymalna, ale od 3 do 4 razy wolniejsza. 7 to standardowa równowaga.
Usuń metadane EXIF/ICC Włączone Typowy zysk od 5 do 30 KB na zdjęcie z aparatu. Zachowaj, jeśli obsługujesz treści wymagające precyzyjnych profili kolorystycznych.

Karta “CDN”

Opcja Domyślnie Wyjaśnienie
Włącz przepisywanie na CDN Wyłączone Po wyłączeniu adresy URL wskazują na Twój origin. Włącz po skonfigurowaniu CDN.
Bazowy adres URL CDN Format: https://cdn.example.com bez końcowego ukośnika. Np. https://shop-cdn.b-cdn.net dla BunnyCDN.
Zakres przepisywania Tylko media Szczegóły poniżej.
Zachowaj query string Włączone Zachowuje parametry cache-bustingu (?v=1234) przy przepisywaniu.

Szczegóły trzech zakresów:

  • Tylko media: przepisuje wyłącznie adresy zaczynające się od /media/. Najbezpieczniejsze i pokrywa 95% typowych zastosowań.
  • Media plus miniatury: dodaje /thumbnail/. Przydatne, jeśli Twój storefront serwuje dużo dynamicznie generowanych miniatur.
  • Wszystkie zasoby statyczne: dodaje /theme/, /bundles/ i /assets/. Wybierz tę opcję tylko wtedy, gdy Twój CDN jest poprawnie skonfigurowany do pull-cache wszystkich zasobów i przetestowałeś to na stagingu.

Karta “Renderowanie frontendu”

Opcja Domyślnie Efekt
Wyjście jako znacznik <picture> Włączone Opakowuje znaczniki <img> storefrontu w <picture> ze źródłami AVIF/WebP.
Dodaj loading="lazy" Włączone Natywne lazy-loading przeglądarki. Zostaw, chyba że masz własne rozwiązanie.
Dodaj decoding="async" Włączone Pozwala przeglądarce dekodować równolegle z parsowaniem HTML.
Wymuś width/height Włączone Ochrona przed CLS (Cumulative Layout Shift). Przeglądarka rezerwuje miejsce na wizualizację przed jej załadowaniem.

Karta “Przetwarzanie wsadowe”

Opcja Domyślnie Zalecenie
Rozmiar partii dla zadania cron 50 50 to dobra równowaga. Podnieś do 100-200, jeśli musisz szybko nadrobić duży katalog, a Twój serwer to wytrzyma.
Interwał crona (minuty) 15 Tylko informacyjnie: rzeczywisty interwał definiuje klasa OptimizeImagesTask::getDefaultInterval(). Aby faktycznie go zmienić, zmodyfikuj wartość w tabeli scheduled_task albo zainstaluj plugin ponownie po zmianie.

Konfiguracja CDN: konkretne przykłady

BunnyCDN (zalecane)

  1. Utwórz Pull Zone na bunny.net ze swoim adresem origin, na przykład https://shop.example.com
  2. BunnyCDN daje Ci hostname typu shop-cdn.b-cdn.net
  3. W konfiguracji pluginu wpisz: https://shop-cdn.b-cdn.net
  4. Na start wybierz zakres Tylko media
  5. Włącz przepisywanie na CDN

Plugin automatycznie wstrzykuje <link rel="dns-prefetch" href="https://shop-cdn.b-cdn.net"> i <link rel="preconnect" href="https://shop-cdn.b-cdn.net" crossorigin> w sekcji <head> storefrontu: zysk od 50 do 200 ms na pierwszym żądaniu do CDN.

Cloudflare

Cloudflare w standardowym trybie proxy DNS nie wymaga przepisywania na CDN: Cloudflare cache’uje automatycznie na Twoim głównym hostname. Jeśli jednak używasz dedykowanego Custom Hostname Cloudflare dla zasobów (na przykład cdn.example.com), skonfiguruj go tutaj. Włącz też Cache Reserve albo Polish po stronie Cloudflare, aby dodatkowo skorzystać z optymalizacji Cloudflare na wierzchu Twojej własnej.

KeyCDN

Konfiguracja identyczna jak przy BunnyCDN: utwórz Pull Zone, pobierz adres typu shop-12345.kxcdn.com i skonfiguruj go w pluginie z prefiksem https://.

AWS CloudFront

Utwórz dystrybucję CloudFront ze swoim serwerem Shopware jako origin. Adres dystrybucji ma postać https://d1234abc.cloudfront.net albo Twojej własnej domeny, jeśli skonfigurowano alias. Ustaw minimalny TTL na 1 dzień, aby w pełni korzystać z cache.

Szczegółowy pipeline optymalizacji

Dla każdego obrazu (oryginału albo miniatury) do przetworzenia plugin wykonuje kolejno następujące kroki:

  1. Pobranie obrazu źródłowego z publicznego filesystemu Shopware do lokalnego pliku tymczasowego (/tmp/dfimgopt_xxx.jpg)
  2. Jeśli Kompresuj oryginał włączone: rekompresja w miejscu ze skonfigurowaną jakością, usunięcie metadanych, jeśli włączone. Jeśli wersja ponownie skompresowana jest mniejsza od oryginalnej, zastępuje plik źródłowy na filesystemie.
  3. Jeśli WebP włączone: konwersja do WebP, zapis bliźniaczego pliku foo.jpg.webp na publicznym filesystemie
  4. Jeśli AVIF włączone i szerokość ≤ maksymalna szerokość: konwersja do AVIF, zapis bliźniaczego pliku foo.jpg.avif
  5. Zapis w tabeli df_image_optimizer z licznikami i zaoszczędzonym rozmiarem
  6. Sprzątanie lokalnego pliku tymczasowego przez blok finally (także w razie błędu)

Imagick jest używany priorytetowo, gdy jest dostępny (wyższa jakość i jedyny silnik AVIF przez libheif na wielu serwerach). W przeciwnym razie przejmuje GD: obsługuje WebP od dawna, a AVIF od PHP 8.1.

Kompresja oryginalnego JPEG jest nieodwracalna. Gdy opcja Kompresuj oryginał jest zaznaczona, wersja skompresowana zastępuje oryginał na filesystemie. Jeśli potrzebujesz odzyskać surowe źródła do innych zastosowań (druk, retusz), wyłącz tę opcję: zyski z WebP i AVIF i tak zachowasz.

Zadanie cykliczne: nadrobienie istniejących obrazów

Aktywacja pluginu w sklepie, który ma już tysiące obrazów w bazie, nie uruchamia optymalizacji wstecznej. To celowe: konwersja 50 000 obrazów do AVIF naraz zapchałaby Twój serwer. Zamiast tego zadanie cykliczne df_image_optimizer.optimize_pending wykonuje się domyślnie co 15 minut:

  1. Zapytanie SQL z LEFT JOIN na df_image_optimizer w celu wskazania mediów jeszcze niezoptymalizowanych
  2. Przetworzenie partii 50 obrazów (rozmiar partii konfigurowalny)
  3. Zakończenie i zwolnienie workera na kolejne zadanie

W sklepie z 10 000 obrazów licz około 50 godzin na nadrobienie wszystkiego w tle. Aby przyspieszyć:

  • Zwiększ rozmiar partii w konfiguracji (spróbuj 100 albo 200)
  • Użyj przycisku Uruchom partię na pulpicie kilka razy pod rząd
  • Uruchom zadanie w pętli ręcznie przez 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 udostępniane motywom

Zarejestrowane są dwa helpery Twig, których możesz użyć w dowolnym szablonie motywu albo pluginu.

Filtr |df_cdn

Przepisuje adres URL na CDN, jeśli jest włączony, a w przeciwnym razie zwraca adres bez zmian. Przydatne przy zasobach, które dołączasz ręcznie.

<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>

Funkcja df_picture()

Renderuje kompletny znacznik <picture> ze źródłami AVIF, WebP i oryginalnym fallbackiem oraz wszystkimi skonfigurowanymi atrybutami (lazy, async, width/height).

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

Generuje:

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

Endpointy API administracji

Dostępne są trzy endpointy REST, uwierzytelniane standardowym tokenem Bearer administracji.

Metoda Trasa Opis
GET /api/_action/df-image-optimizer/stats Przegląd plus aktywność z 30 dni plus możliwości serwera
POST /api/_action/df-image-optimizer/run-batch Uruchamia partię. Opcjonalny parametr POST batchSize (domyślnie 50, maks. 500)
GET /api/_action/df-image-optimizer/capabilities Wykrywanie serwera (Imagick / GD / WebP / AVIF)

Przykład curl:

TOKEN=$(curl -s -X POST https://shop.example.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.example.com/api/_action/df-image-optimizer/run-batch 
    -H "Authorization: Bearer $TOKEN" 
    -H "Content-Type: application/json" 
    -d '{"batchSize":200}'

Tworzone tabele

df_image_optimizer

Jeden wiersz na zoptymalizowane medium. Unikalny klucz na media_id: nowa optymalizacja tego samego medium nadpisuje wiersz.

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       Original weight in bytes
bytes_saved       BIGINT       Cumulated savings (compression + WebP/AVIF delta)
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

Opcjonalny dziennik błędów. Tylko do odczytu na potrzeby debugowania, bez automatycznego czyszczenia.

Rozwiązywanie problemów

“Pulpit pokazuje AVIF: niedostępne”

Twój serwer nie ma wymaganego stosu AVIF. Opcje:

  • Jeśli tylko GD: sprawdź php -m | grep gd i php -i | grep AVIF. Potrzebne jest PHP 8.1+ oraz GD skompilowane z --with-avif. Na nowszych Debianach i Ubuntu jest to domyślne.
  • Jeśli Imagick dostępny: sprawdź php -r "print_r(Imagick::queryFormats('AVIF'));". Puste? Twój Imagick nie jest skompilowany z libheif: konieczna rekompilacja albo przejście na GD.
  • Akceptowalny fallback: zostaw AVIF wyłączone i skup się na WebP. Sam zysk z WebP jest już ogromny wobec natywnego JPEG w Shopware.

“Pliki .webp są generowane, ale storefront pokazuje JPEG”

Kompilator motywu nie uwzględnił override’u Twig. Rozwiązanie:

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

Następnie sprawdź w DevTools przeglądarki (Chrome albo Firefox): otwórz zakładkę Sieć, przeładuj stronę produktu i spójrz na typ MIME ładowanych obrazów. Powinieneś zobaczyć image/avif albo image/webp zamiast image/jpeg.

“Przesyłanie mediów zrobiło się wolne”

Zwłaszcza konwersja AVIF mocno obciąża CPU: licz od 1 do 3 sekund na obraz. Jeśli to przeszkadza, wyłącz autooptymalizację przy przesyłaniu (karta Ogólne) i zostaw przetwarzanie w tle wyłącznie zadaniu cyklicznemu. Przesyłanie znów staje się natychmiastowe, a obrazy są optymalizowane najpóźniej w ciągu 15 minut.

“Miniatury .webp nie są generowane”

Sprawdź, czy Przetwarzaj miniatury jest zaznaczone na karcie Ogólne. Następnie wygeneruj miniatury ręcznie, aby ponownie przeszły przez pipeline:

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

“Jak usunąć wszystkie wygenerowane pliki WebP/AVIF?”

Plugin nie usuwa ich automatycznie, nawet przy odinstalowaniu (aby chronić Twoje kopie zapasowe). Aby wyczyścić je ręcznie:

cd /path/to/shopware
find public/media -name "*.webp" -delete
find public/media -name "*.avif" -delete

“Adresy CDN nie są stosowane wszędzie”

Sprawdź skonfigurowany zakres. Jeśli widzisz adresy origin dla zasobów motywu (/theme/.../style.css), to normalne przy domyślnym zakresie Tylko media. Przejdź na Wszystkie zasoby statyczne, jeśli Twój CDN jest skonfigurowany do serwowania wszystkich zasobów.

Zwróć też uwagę, że przepisywane adresy dotyczą renderowania Twig po stronie serwera. Jeśli Twój frontend wywołuje Store-API i odtwarza adresy po stronie JS, przepisywanie trzeba zastosować osobno po stronie klienta.

Odinstalowanie

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

Przy odinstalowaniu Shopware pyta, czy chcesz zachować dane użytkownika:

  • Zachowaj (domyślnie): tabele df_image_optimizer i df_image_optimizer_log zostają w bazie. Ponowna instalacja pluginu podejmie historię.
  • Nie zachowuj: obie tabele są usuwane (DROP TABLE).

W obu przypadkach pliki .webp i .avif na filesystemie pozostają: użyj powyższych komend find, aby je w razie potrzeby wyczyścić.

Aby pójść dalej

  • Obserwuj swój wynik Core Web Vitals w Google Search Console: LCP powinien spaść w ciągu 2 do 4 tygodni od aktywacji
  • Przetestuj w PageSpeed Insights przed i po: typowy zysk od 20 do 40 punktów na mobile
  • Włącz też HTTP/2 albo HTTP/3 po stronie serwera, aby zwielokrotnić korzyść z CDN
  • Połącz to z pełnostronicowym cache Shopware, aby uzyskać statyczne czasy odpowiedzi
Czy ta strona była pomocna?

Nadal utknąłeś? Napisz do wsparcia