# DataFirefly Image Optimizer — Documentación Shopware 6

> DataFirefly Image Optimizer transforma automáticamente cada imagen de medios Shopware en variantes WebP y AVIF, recomprime los JPEG y PNG originales, y reescribe las URL hacia su CDN — sin…

- Página: <https://www.datafirefly.com/es/documentation/dfimageoptimizer/>
- Idioma: es
- Actualizado el: 2026-06-29
- Otros idiomas: [fr](https://www.datafirefly.com/documentation/dfimageoptimizer/index.md), [en](https://www.datafirefly.com/en/documentation/dfimageoptimizer/index.md), [de](https://www.datafirefly.com/de/documentation/dfimageoptimizer/index.md), [it](https://www.datafirefly.com/it/documentation/dfimageoptimizer/index.md), [pl](https://www.datafirefly.com/pl/documentation/dfimageoptimizer/index.md), [nl](https://www.datafirefly.com/nl/documentation/dfimageoptimizer/index.md), [pt](https://www.datafirefly.com/pt/documentation/dfimageoptimizer/index.md)
- Índice: <https://www.datafirefly.com/es/documentation/llms.txt>

DataFirefly Image Optimizer transforma automáticamente cada imagen de medios Shopware en variantes WebP y AVIF, recomprime los JPEG y PNG originales, y reescribe las URL hacia su CDN — sin modificar el tema. Esta documentación cubre la instalación, la configuración completa, la API Twig expuesta a los temas, y la resolución de problemas.

## Instalación

El plugin se entrega como ZIP. Dos métodos de instalación, funcionalmente equivalentes.

### Vía la administración Shopware

1. Ajustes → Sistema → Extensiones → Subir extensión
2. Seleccione `DfImageOptimizer-1.0.0.zip`
3. Haga clic en Instalar y luego Activar
4. Limpiar caché: Ajustes → Sistema → Caché e Índices → Limpiar

### Vía CLI (recomendado)

```
cd /ruta/a/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
```

**Consejo.** `theme:compile` es obligatorio tras la instalación para que el override Twig del componente thumbnail esté activo en el storefront. Sin esta etapa, las etiquetas `` no se generarán aunque WebP y AVIF se produzcan.

### Verificación post-instalación

Vaya al menú admin **Catálogos → Image Optimizer**. El panel debe mostrarse con una tarjeta _Capacidades del servidor_ indicando en tiempo real:

- Versión PHP detectada (8.2 mínimo)
- Presencia de Imagick (recomendado)
- Presencia de GD (obligatorio)
- Soporte efectivo WebP — debe ser ✓
- Soporte efectivo AVIF — puede ser ✗ según el servidor, no bloqueante
- Motor recomendado: Imagick o GD

## Arquitectura en dos palabras

Cuando se sube una imagen, el plugin escucha el evento entity `media.written`, carga la imagen en un archivo temporal local, y luego produce en paralelo:

- El original recomprimido (reemplaza el archivo si _Comprimir original_ está marcado)
- Un hermano WebP al lado con extensión acumulada: `foo.jpg` → `foo.jpg.webp`
- Un hermano AVIF al lado: `foo.jpg` → `foo.jpg.avif`

Las miniaturas Shopware generadas por el `ThumbnailService` nativo se procesan de la misma manera. En el storefront, el override Twig de `storefront/component/image/thumbnail.html.twig` envuelve la etiqueta `` en un `` con fuentes AVIF, WebP y fallback original — el navegador elige automáticamente el formato más ligero que soporta.

## Configuración

Acceso: **Ajustes → Sistema → Extensiones → DfImageOptimizer → Configurar**. Siete tarjetas agrupan las opciones.

### Tarjeta «General»

| Opción | Defecto | Efecto |
| --- | --- | --- |
| Auto-optimizar al subir | Activado | Activa el pipeline inmediatamente en cada subida. Desactive si prefiere procesar todo en segundo plano vía cron. |
| Procesar miniaturas | Activado | Genera WebP/AVIF también para las miniaturas Shopware (típicamente 4-6 tamaños por imagen origen). |

### Tarjeta «WebP»

| Opción | Defecto | Recomendación |
| --- | --- | --- |
| Activar WebP | Activado | Mantener activado salvo caso muy específico. WebP es compatible con el 96% de navegadores. |
| Calidad WebP (1-100) | 82 | 75-85 para buen equilibrio. 90+ para fotografía de alta gama, 70 para catálogo voluminoso. |
| Lossless para PNG | Desactivado | Active solo si sus PNG contienen texto o gráficos nítidos (logos, iconos). Si no, el modo lossy da mejores ganancias. |

### Tarjeta «AVIF»

| Opción | Defecto | Recomendación |
| --- | --- | --- |
| Activar AVIF | Desactivado | Active si el panel indica que su servidor soporta AVIF. Ganancia típica del 50% vs JPEG, pero codificación más lenta que WebP. |
| Calidad AVIF (1-100) | 55 | 45-65 para excelente renderizado. AVIF tolera calidades más bajas que JPEG/WebP gracias a su códec moderno. |
| Anchura máxima para AVIF (px) | 2400 | Salvaguarda CPU. Imágenes mayores se omiten para AVIF pero conservan su WebP. Aumente si tiene un servidor potente. |

**Sobre AVIF.** La codificación AVIF requiere PHP 8.1+ con el flag `IMG_AVIF` compilado, o Imagick con libheif. El panel _Capacidades del servidor_ indica exactamente qué está disponible. Si AVIF no es compatible, la opción queda inoperante aunque esté marcada — sin error, simplemente no hay generación AVIF.

### Tarjeta «Compresión»

| Opción | Defecto | Recomendación |
| --- | --- | --- |
| Comprimir JPG/PNG originales | Activado | Reemplaza el original por su versión recomprimida. Acción **irreversible** — desactive si quiere conservar las fuentes brutas. |
| Calidad JPEG (1-100) | 85 | 85 es el estándar foto web. Bajar a 80 para ganancia adicional si la calidad sigue aceptable. |
| Nivel compresión PNG (0-9) | 7 | 9 = compresión máxima pero 3-4× más lenta. 7 es el equilibrio estándar. |
| Eliminar metadatos EXIF/ICC | Activado | Ganancia típica 5 a 30 KB por foto de cámara. Conserve si gestiona contenido con perfiles cromáticos. |

### Tarjeta «CDN»

| Opción | Defecto | Explicación |
| --- | --- | --- |
| Activar reescritura CDN | Desactivado | Si desactivado, las URL apuntan a su origen. Active tras configurar su CDN. |
| URL base del CDN | — | Formato: `https://cdn.ejemplo.com` sin slash final. |
| Alcance de reescritura | Solo medios | Vea detalle abajo. |
| Conservar query strings | Activado | Preserva parámetros cache-busting (`?v=1234`) en la reescritura. |

**Los tres alcances en detalle:**

- **Solo medios** — reescribe únicamente URLs comenzando por `/media/`. Es el más seguro y cubre el 95% de los casos de uso típicos.
- **Medios + miniaturas** — añade `/thumbnail/`. Útil si su storefront sirve muchas miniaturas generadas dinámicamente.
- **Todos los recursos estáticos** — añade `/theme/`, `/bundles/` y `/assets/`. Solo elija esta opción si su CDN está bien configurado.

### Tarjeta «Renderizado frontend»

| Opción | Defecto | Efecto |
| --- | --- | --- |
| Salida como `` | Activado | Envuelve los `` del storefront en un `` con fuentes AVIF/WebP. |
| Añadir `loading="lazy"` | Activado | Lazy-loading nativo navegador. Mantener salvo solución propia. |
| Añadir `decoding="async"` | Activado | Permite al navegador decodificar en paralelo del parsing HTML. |
| Forzar `width`/`height` | Activado | Anti-CLS (Cumulative Layout Shift). El navegador reserva el espacio. |

### Tarjeta «Procesamiento por lotes»

| Opción | Defecto | Recomendación |
| --- | --- | --- |
| Tamaño de lote para tarea cron | 50 | 50 es buen equilibrio. Suba a 100-200 si necesita recuperar un gran catálogo rápidamente. |
| Intervalo cron (minutos) | 15 | Información solo — el intervalo real lo define `OptimizeImagesTask::getDefaultInterval()`. |

## Configurar un CDN — ejemplos concretos

### BunnyCDN (recomendado)

1. Cree una _Pull Zone_ en bunny.net con su URL de origen, por ejemplo `https://shop.ejemplo.com`
2. BunnyCDN le da un hostname del tipo `shop-cdn.b-cdn.net`
3. En la config del plugin, ponga: `https://shop-cdn.b-cdn.net`
4. Elija el alcance _Solo medios_ para empezar
5. Active la reescritura CDN

El plugin inyecta automáticamente `` y `` en el `` del storefront — ahorro de 50 a 200 ms en la primera petición CDN.

### Cloudflare

Cloudflare en modo proxy DNS estándar no necesita reescritura CDN — Cloudflare cachea automáticamente en su hostname principal. Pero si usa un _Custom Hostname_ Cloudflare dedicado para assets (por ejemplo `cdn.ejemplo.com`), configúrelo aquí. Active también _Cache Reserve_ o _Polish_ de Cloudflare.

### KeyCDN

Configuración idéntica a BunnyCDN: cree una Pull Zone, recupere la URL del tipo `shop-12345.kxcdn.com`, configúrela en el plugin con el prefijo `https://`.

### AWS CloudFront

Cree una distribución CloudFront con su servidor Shopware como origen. La URL de distribución es del tipo `https://d1234abc.cloudfront.net`. Configure el TTL mínimo a 1 día.

## Pipeline de optimización detallado

Para cada imagen a procesar, el plugin ejecuta estos pasos en orden:

1. Descarga de la imagen origen desde el filesystem público Shopware a archivo temporal local (`/tmp/dfimgopt_xxx.jpg`)
2. **Si Comprimir original activado**: recompresión in-place con calidad configurada, eliminación metadatos si activada.
3. **Si WebP activado**: conversión a WebP, escritura del hermano `foo.jpg.webp`
4. **Si AVIF activado y anchura ≤ anchura máxima**: conversión a AVIF, escritura del hermano `foo.jpg.avif`
5. Registro en tabla `df_image_optimizer`
6. Limpieza del archivo temporal vía bloque `finally`

Imagick se usa por prioridad cuando está disponible. GD toma el relevo si no — soporta WebP desde hace tiempo y AVIF desde PHP 8.1.

**Compresión JPEG original — irreversible.** Cuando la opción _Comprimir original_ está marcada, la versión comprimida reemplaza la original en el filesystem. Si necesita las fuentes brutas para otros usos, desactive esta opción.

## Tarea programada — recuperación de imágenes existentes

Activar el plugin en una tienda con ya miles de imágenes no dispara la optimización retroactiva. La tarea programada `df_image_optimizer.optimize_pending` se ejecuta cada 15 minutos por defecto:

1. Consulta SQL vía LEFT JOIN sobre `df_image_optimizer` para identificar medios no optimizados
2. Procesa un lote de 50 imágenes (configurable)
3. Termina y libera el worker

En una tienda con 10.000 imágenes, cuente unas 50 horas para recuperación total. Para acelerar:

- Aumente el tamaño de lote (pruebe 100 o 200)
- Use el botón **Ejecutar lote** del panel varias veces
- Ejecute la tarea en bucle vía 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 expuesta a los temas

Dos helpers Twig registrados, usables en cualquier template de tema o plugin.

### Filtro `|df_cdn`

Reescribe una URL hacia el CDN si activado, sino retorna la URL sin cambios.

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

### Función `df_picture()`

Renderiza una etiqueta `` completa con fuentes AVIF, WebP y fallback original.

```
{{ df_picture(
    media,
    alt='Descripción accesible',
    classes='product-image card-img',
    sizes='(max-width: 768px) 100vw, 50vw'
) }}
```

Genera:

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

## Endpoints API admin

| Método | Ruta | Descripción |
| --- | --- | --- |
| GET | `/api/_action/df-image-optimizer/stats` | Vista general + actividad 30d + capacidades servidor |
| POST | `/api/_action/df-image-optimizer/run-batch` | Lanza un lote. Parámetro POST opcional `batchSize` |
| GET | `/api/_action/df-image-optimizer/capabilities` | Detección servidor |

**Ejemplo curl:**

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

## Tablas creadas

### `df_image_optimizer`

```
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 en bytes
bytes_saved       BIGINT       Cumulativo ahorros
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`

Diario opcional de errores. Solo lectura para depuración — sin purga automática.

## Resolución de problemas

### «El panel muestra AVIF: No disponible»

- **Si GD-only**: verifique `php -m | grep gd` y `php -i | grep AVIF`. Se necesita PHP 8.1+ _y_ GD compilado con `--with-avif`.
- **Si Imagick disponible**: verifique `php -r "print_r(Imagick::queryFormats('AVIF'));"`. ¿Vacío? Su Imagick no está compilado con libheif.
- **Fallback aceptable**: deje AVIF desactivado y concéntrese en WebP.

### «Las imágenes `.webp` se generan pero el storefront muestra JPEG»

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

Verifique con DevTools del navegador: abra la pestaña Red, recargue una página producto, inspeccione el tipo MIME — debería ver `image/avif` o `image/webp`.

### «La subida de medios se ha vuelto lenta»

La conversión AVIF es CPU-intensiva. Desactive auto-optimización al subir y deje la tarea programada procesar en segundo plano.

### «Las miniaturas `.webp` no se generan»

Verifique _Procesar miniaturas_ en tarjeta General. Luego:

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

### «¿Cómo vaciar todos los archivos WebP/AVIF generados?»

```
cd /ruta/a/shopware
find public/media -name "*.webp" -delete
find public/media -name "*.avif" -delete
```

### «Las URLs CDN no se aplican en todas partes»

Verifique el alcance configurado. URLs de origen para assets tema con alcance por defecto _Solo medios_ son normales. Pase a _Todos los recursos estáticos_ si su CDN está bien configurado.

## Desinstalación

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

En la desinstalación, Shopware pregunta si conservar los datos de usuario:

- **Conservar** (defecto): las tablas se mantienen en base.
- **No conservar**: las dos tablas se eliminan (DROP TABLE).

En ambos casos, los archivos `.webp` y `.avif` en el filesystem permanecen.

## Para ir más lejos

- Monitorice su puntuación Core Web Vitals en Google Search Console
- Pruebe con PageSpeed Insights antes/después — ganancia típica 20-40 puntos en móvil
- Active también HTTP/2 o HTTP/3 lado servidor
- Combine con caché página completa Shopware
