SW Shopware 6 Intermédio

DataFirefly Image Optimizer: documentação Shopware 6

Instalação, configuração WebP/AVIF, integração de CDN, API Twig e resolução de problemas da extensão Image Optimizer para Shopware 6.6 e 6.7.

Atualizado Versão do módulo 1.0.0

O DataFirefly Image Optimizer transforma automaticamente cada imagem de média do Shopware em variantes WebP e AVIF, recomprime os JPEG e PNG de origem, e reescreve os URLs para o seu CDN, sem alterar o tema. Esta documentação cobre a instalação, a configuração completa, a API Twig exposta aos temas e a resolução de problemas.

Instalação

A extensão é entregue em ZIP. Dois métodos de instalação, funcionalmente equivalentes.

Pela administração do Shopware

  1. Definições → Sistema → Extensões → Carregar uma extensão
  2. Selecione DfImageOptimizer-1.0.0.zip
  3. Clique em Instalar e depois em Ativar
  4. Limpe a cache: Definições → Sistema → Cache e Índice → Limpar

Por CLI (recomendado)

cd /caminho/para/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
Dica. O theme:compile é obrigatório depois da instalação para que a sobreposição Twig do componente de miniatura fique ativa no storefront. Sem esse passo, as etiquetas <picture> não serão geradas, mesmo que o WebP e o AVIF sejam produzidos.

Verificação após a instalação

Vá ao menu de administração Catálogos → Image Optimizer. O painel tem de aparecer com um cartão Compatibilidade do servidor a indicar em tempo real:

  • Versão do PHP detetada (8.2 no mínimo)
  • Presença do Imagick (recomendado)
  • Presença do GD (obrigatório)
  • Suporte efetivo a WebP: tem de estar ✓
  • Suporte efetivo a AVIF: pode estar ✗ consoante o servidor, não é bloqueante
  • Motor recomendado: Imagick ou GD

Arquitetura em duas palavras

Quando uma imagem é carregada, a extensão escuta o evento de entidade media.written, carrega a imagem para um ficheiro temporário local, e produz em paralelo:

  • O original recomprimido (substitui o ficheiro de origem se Comprimir original estiver marcado)
  • Um irmão WebP ao lado, com extensão acumulada: foo.jpgfoo.jpg.webp
  • Um irmão AVIF ao lado: foo.jpgfoo.jpg.avif

As miniaturas do Shopware geradas pelo ThumbnailService nativo são tratadas da mesma forma. Do lado do storefront, a sobreposição Twig de storefront/component/image/thumbnail.html.twig envolve a etiqueta <img> num <picture> com fontes AVIF, WebP e alternativa original: o navegador escolhe automaticamente o formato mais leve que suporta.

Configuração

Acesso: Definições → Sistema → Extensões → DfImageOptimizer → Configurar. Sete cartões agrupam as opções.

Cartão «Geral»

Opção Predefinição Efeito
Otimização automática no carregamento Ativa Aciona o pipeline de imediato a cada carregamento. Desative se preferir fazer tudo em segundo plano através do cron.
Tratar as miniaturas Ativa Gera WebP/AVIF também para as miniaturas do Shopware (tipicamente 4 a 6 tamanhos por imagem de origem).

Cartão «WebP»

Opção Predefinição Recomendação
Ativar WebP Ativo A manter ativo salvo caso muito específico. O WebP é suportado por 96 % dos navegadores.
Qualidade WebP (1-100) 82 75 a 85 para um bom compromisso. 90+ para fotografia de topo, 70 para catálogos volumosos.
Lossless para PNG Desativado Ative apenas se os seus PNG contiverem texto ou gráficos nítidos (logótipos, ícones). Caso contrário, o modo lossy dá melhores ganhos.

Cartão «AVIF»

Opção Predefinição Recomendação
Ativar AVIF Desativado Ative se o painel indicar que o seu servidor suporta AVIF. Ganho típico de 50 % face ao JPEG, mas codificação mais lenta que o WebP.
Qualidade AVIF (1-100) 55 45 a 65 para uma excelente renderização. O AVIF tolera qualidades mais baixas do que o JPEG e o WebP graças ao seu codec moderno.
Largura máxima para AVIF (px) 2400 Salvaguarda de CPU. As imagens acima disso são saltadas para AVIF mas mantêm o seu WebP. Aumente se tiver um servidor potente e precisar de AVIF em imagens grandes.
Sobre o AVIF. A codificação AVIF exige PHP 8.1+ com o sinalizador IMG_AVIF compilado, ou Imagick com libheif. O painel Compatibilidade do servidor indica-lhe exatamente o que está disponível. Se o AVIF não for suportado, a opção fica inoperante mesmo que marcada: sem erro, apenas sem geração de AVIF.

Cartão «Compressão»

Opção Predefinição Recomendação
Comprimir os JPG/PNG originais Ativo Substitui o original pela sua versão recomprimida. Ação irreversível: desative se quiser conservar as fontes em bruto para futuras edições.
Qualidade JPEG (1-100) 85 85 é a norma da fotografia web. Descer a 80 dá ganho adicional se a qualidade continuar visualmente aceitável.
Nível de compressão PNG (0-9) 7 9 = compressão máxima mas 3 a 4× mais lenta. 7 é o equilíbrio normal.
Eliminar os metadados EXIF/ICC Ativo Ganho típico de 5 a 30 KB por fotografia vinda de câmara. Conserve se gerir conteúdo que exija perfis de cor precisos.

Cartão «CDN»

Opção Predefinição Explicação
Ativar a reescrita para CDN Desativada Se estiver desativada, os URLs apontam para a sua origem. Ative depois de configurar o seu CDN.
URL de base do CDN Formato: https://cdn.exemplo.com sem barra final. Ex.: https://shop-cdn.b-cdn.net para BunnyCDN.
Âmbito da reescrita Apenas médias Ver detalhe abaixo.
Conservar as query strings Ativo Preserva os parâmetros de cache-busting (?v=1234) na reescrita.

Detalhe dos três âmbitos:

  • Apenas médias: reescreve apenas os URLs que começam por /media/. É o mais seguro e cobre 95 % dos casos de uso típicos.
  • Médias e miniaturas: acrescenta /thumbnail/. Útil se o seu storefront servir muitas miniaturas geradas dinamicamente.
  • Todos os recursos estáticos: acrescenta /theme/, /bundles/ e /assets/. Só escolha esta opção se o seu CDN estiver corretamente configurado para pull-cache de todos os recursos e se tiver testado em staging.

Cartão «Renderização no frontend»

Opção Predefinição Efeito
Saída em etiqueta <picture> Ativa Envolve as <img> do storefront num <picture> com fontes AVIF/WebP.
Acrescentar loading="lazy" Ativo Lazy-loading nativo do navegador. A manter, salvo se tiver a sua própria solução.
Acrescentar decoding="async" Ativo Permite ao navegador descodificar em paralelo com o parsing do HTML.
Forçar width/height Ativo Anti-CLS (Cumulative Layout Shift). O navegador reserva o espaço do visual antes do carregamento.

Cartão «Processamento em lote»

Opção Predefinição Recomendação
Tamanho do lote da tarefa cron 50 50 é um bom equilíbrio. Suba para 100 a 200 se precisar de recuperar um catálogo grande depressa e o seu servidor aguentar.
Intervalo do cron (minutos) 15 Informação apenas: o intervalo real é definido pela classe OptimizeImagesTask::getDefaultInterval(). Para o alterar de facto, mude o valor na tabela scheduled_task ou reinstale a extensão depois da alteração.

Configurar um CDN: exemplos concretos

BunnyCDN (recomendado)

  1. Crie uma Pull Zone em bunny.net com o seu URL de origem, por exemplo https://loja.exemplo.com
  2. O BunnyCDN dá-lhe um hostname do tipo shop-cdn.b-cdn.net
  3. Na configuração da extensão, coloque: https://shop-cdn.b-cdn.net
  4. Escolha o âmbito Apenas médias para começar
  5. Ative a reescrita para CDN

A extensão injeta automaticamente <link rel="dns-prefetch" href="https://shop-cdn.b-cdn.net"> e <link rel="preconnect" href="https://shop-cdn.b-cdn.net" crossorigin> no <head> do storefront: ganho de 50 a 200 ms no primeiro pedido ao CDN.

Cloudflare

A Cloudflare em modo proxy DNS normal não exige reescrita de CDN: coloca automaticamente em cache no seu hostname principal. Mas se usar um Custom Hostname Cloudflare dedicado aos recursos (por exemplo cdn.exemplo.com), configure-o aqui. Ative também o Cache Reserve ou o Polish do lado da Cloudflare para beneficiar da otimização da Cloudflare por cima da sua.

KeyCDN

Configuração idêntica à do BunnyCDN: crie uma Pull Zone, obtenha o URL do tipo shop-12345.kxcdn.com, e configure-o na extensão com o prefixo https://.

AWS CloudFront

Crie uma distribuição CloudFront com o seu servidor Shopware como origem. O URL de distribuição é do tipo https://d1234abc.cloudfront.net, ou o seu domínio personalizado se tiver configurado um alias. Configure o TTL mínimo para 1 dia para aproveitar plenamente a cache.

Pipeline de otimização em detalhe

Para cada imagem (original ou miniatura) a tratar, a extensão executa os seguintes passos por ordem:

  1. Transferência da imagem de origem do filesystem público do Shopware para um ficheiro temporário local (/tmp/dfimgopt_xxx.jpg)
  2. Se Comprimir original estiver ativo: recompressão in-place com a qualidade configurada, eliminação dos metadados se estiver ativa. Se a versão recomprimida for menor do que a original, substitui o ficheiro de origem no filesystem.
  3. Se o WebP estiver ativo: conversão para WebP, escrita do irmão foo.jpg.webp no filesystem público
  4. Se o AVIF estiver ativo e a largura for ≤ largura máxima: conversão para AVIF, escrita do irmão foo.jpg.avif
  5. Registo na tabela df_image_optimizer com contadores e tamanho poupado
  6. Limpeza do ficheiro temporário local através de um bloco finally (mesmo em caso de erro)

O Imagick é usado em prioridade quando está disponível (qualidade superior e único motor AVIF através de libheif em muitos servidores). O GD assume caso contrário: suporta WebP há muito tempo e AVIF desde o PHP 8.1.

Compressão do JPEG original: irreversível. Quando a opção Comprimir original está marcada, a versão comprimida substitui a original no filesystem. Se precisar de recuperar as fontes em bruto para outros usos (impressão, edições), desative esta opção: continuará a ter os ganhos através do WebP e do AVIF.

Tarefa agendada: recuperar as imagens existentes

Ativar a extensão numa loja que já tem milhares de imagens na base de dados não desencadeia a otimização retroativa. É intencional: converter 50 000 imagens em AVIF de uma vez saturaria o seu servidor. Em vez disso, a tarefa agendada df_image_optimizer.optimize_pending corre a cada 15 minutos por predefinição:

  1. Consulta SQL com LEFT JOIN em df_image_optimizer para identificar os médias ainda não otimizados
  2. Trata um lote de 50 imagens (tamanho de lote configurável)
  3. Termina e liberta o worker para a tarefa seguinte

Numa loja de 10 000 imagens, conte cerca de 50 horas para recuperar tudo em segundo plano. Para acelerar:

  • Aumente o tamanho do lote na configuração (experimente 100 ou 200)
  • Use o botão Lançar um lote do painel várias vezes seguidas
  • Execute a tarefa em ciclo manualmente por 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 exposta aos temas

Estão registados dois helpers Twig, utilizáveis em qualquer template de tema ou de extensão.

Filtro |df_cdn

Reescreve um URL para o CDN se estiver ativo, e devolve o URL inalterado caso contrário. Útil para os recursos que inclui manualmente.

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

Função df_picture()

Renderiza uma etiqueta <picture> completa com fontes AVIF, WebP e alternativa original, mais todos os atributos configurados (lazy, async, width/height).

{{ df_picture(
    media,
    alt='Descrição acessível',
    classes='product-image card-img',
    sizes='(max-width: 768px) 100vw, 50vw'
) }}

Gera:

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

Endpoints da API de administração

Estão disponíveis três endpoints REST, autenticados com o Bearer token normal da administração.

Método Rota Descrição
GET /api/_action/df-image-optimizer/stats Visão geral, atividade de 30 dias e capacidades do servidor
POST /api/_action/df-image-optimizer/run-batch Lança um lote. Parâmetro POST opcional batchSize (predefinição 50, máximo 500)
GET /api/_action/df-image-optimizer/capabilities Deteção do servidor (Imagick / GD / WebP / AVIF)

Exemplo com curl:

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

Tabelas criadas

df_image_optimizer

Uma linha por média otimizado. Chave única em media_id: uma nova otimização do mesmo média substitui a linha.

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       Peso original em bytes
bytes_saved       BIGINT       Acumulado de poupanças (compressão + 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

Registo opcional dos erros. Só de leitura, para depuração: sem limpeza automática.

Resolução de problemas

«O painel mostra AVIF: Indisponível»

O seu servidor não tem a stack AVIF necessária. Opções:

  • Se só tiver GD: verifique php -m | grep gd e php -i | grep AVIF. É preciso PHP 8.1+ e GD compilado com --with-avif. Em Debian/Ubuntu recentes, vem por predefinição.
  • Se o Imagick estiver disponível: verifique php -r "print_r(Imagick::queryFormats('AVIF'));". Vazio? O seu Imagick não está compilado com libheif: é necessária recompilação ou passagem para GD.
  • Alternativa aceitável: deixe o AVIF desativado e concentre-se no WebP. O ganho só com WebP já é enorme face ao JPEG nativo do Shopware.

«As imagens .webp são bem geradas mas o storefront mostra JPEG»

O compilador de tema não teve em conta a sobreposição Twig. Solução:

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

Verifique depois com as DevTools do navegador (Chrome ou Firefox): abra o separador Rede, recarregue uma página de produto, e veja o tipo MIME das imagens carregadas. Deverá ver image/avif ou image/webp em vez de image/jpeg.

«O carregamento dos médias ficou lento»

A conversão AVIF em particular é intensiva em CPU: conte 1 a 3 segundos por imagem. Se for incómodo, desative a otimização automática no carregamento (cartão Geral) e deixe apenas a tarefa agendada tratar em segundo plano. Os carregamentos voltam a ser instantâneos e as imagens são otimizadas em 15 minutos no máximo.

«As miniaturas .webp não são geradas»

Verifique que Tratar as miniaturas está marcado no cartão Geral. Regenere depois manualmente as miniaturas para que voltem a passar pelo pipeline:

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

«Como eliminar todos os ficheiros WebP/AVIF gerados?»

A extensão não os elimina automaticamente, nem sequer na desinstalação (para preservar as suas cópias de segurança). Para os limpar manualmente:

cd /caminho/para/shopware
find public/media -name "*.webp" -delete
find public/media -name "*.avif" -delete

«Os URLs do CDN não são aplicados em todo o lado»

Verifique o âmbito configurado. Se vir URLs de origem para recursos de tema (/theme/.../style.css), é normal com o âmbito predefinido Apenas médias. Passe para Todos os recursos estáticos se o seu CDN estiver configurado para servir todos os recursos.

Note também que os URLs reescritos dizem respeito à renderização Twig no servidor. Se o seu frontend chamar a Store API e reconstruir os URLs do lado do JS, terá de aplicar a reescrita do lado do cliente em separado.

Desinstalação

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

Na desinstalação, o Shopware pergunta se quer conservar os dados do utilizador:

  • Conservar (predefinição): as tabelas df_image_optimizer e df_image_optimizer_log ficam na base de dados. Reinstalar a extensão retoma o histórico.
  • Não conservar: as duas tabelas são eliminadas (DROP TABLE).

Nos dois casos, os ficheiros .webp e .avif no filesystem mantêm-se: use os comandos find acima para os limpar se for necessário.

Para ir mais longe

  • Vigie a sua pontuação de Core Web Vitals na Google Search Console: o LCP deve descer nas 2 a 4 semanas seguintes à ativação
  • Teste com o PageSpeed Insights antes e depois: ganho típico de 20 a 40 pontos em telemóvel
  • Ative também HTTP/2 ou HTTP/3 do lado do servidor para multiplicar o benefício do CDN
  • Combine com uma cache de página completa do Shopware para tempos de resposta estáticos
Esta página foi útil?

Ainda com dúvidas? Contacte o suporte