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.
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
- Ustawienia → System → Rozszerzenia → Prześlij rozszerzenie
- Wybierz
DfImageOptimizer-1.0.0.zip - Kliknij Zainstaluj, a następnie Aktywuj
- 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
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.jpg→foo.jpg.webp - Bliźniaczy plik AVIF obok:
foo.jpg→foo.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. |
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)
- Utwórz Pull Zone na bunny.net ze swoim adresem origin, na przykład
https://shop.example.com - BunnyCDN daje Ci hostname typu
shop-cdn.b-cdn.net - W konfiguracji pluginu wpisz:
https://shop-cdn.b-cdn.net - Na start wybierz zakres Tylko media
- 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:
- Pobranie obrazu źródłowego z publicznego filesystemu Shopware do lokalnego pliku tymczasowego (
/tmp/dfimgopt_xxx.jpg) - 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.
- Jeśli WebP włączone: konwersja do WebP, zapis bliźniaczego pliku
foo.jpg.webpna publicznym filesystemie - Jeśli AVIF włączone i szerokość ≤ maksymalna szerokość: konwersja do AVIF, zapis bliźniaczego pliku
foo.jpg.avif - Zapis w tabeli
df_image_optimizerz licznikami i zaoszczędzonym rozmiarem - 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.
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:
- Zapytanie SQL z LEFT JOIN na
df_image_optimizerw celu wskazania mediów jeszcze niezoptymalizowanych - Przetworzenie partii 50 obrazów (rozmiar partii konfigurowalny)
- 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 gdiphp -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_optimizeridf_image_optimizer_logzostają 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