Optimización de imágenes

Deja una imagen a tamaño completo en src/ o public/, apunta un <img> hacia ella, y sitelo la redimensiona, la convierte a un formato moderno y reescribe la etiqueta con un srcset. Nada que importar, ningún componente que aprender.

Activarlo

export default {
  images: true,
}

La codificación la hace sharp, una dependencia peer opcional: instálala junto a sitelo cuando actives las imágenes:

npm install -D sharp

Los sitios que no optimizan imágenes no necesitan instalarla nunca.

Escribe un <img> normal

import { html, body, img } from 'javascript-to-html'

export default () =>
  html({ lang: 'es' },
    body(
      img({ src: '/images/hero.png', alt: 'Amanecer sobre el puerto' }),
    ),
  )

Una imagen original de 3000×2000 sale así por el otro lado:

<img src="/assets/img/hero.a1b2c3d4-1200.webp"
     alt="Amanecer sobre el puerto"
     sizes="(max-width: 1200px) 100vw, 1200px"
     width="1200" height="800"
     loading="lazy" decoding="async"
     srcset="/assets/img/hero.9f8e7d6c-400.webp 400w,
             /assets/img/hero.5b4a3c2d-800.webp 800w,
             /assets/img/hero.a1b2c3d4-1200.webp 1200w">

Qué obtienes

La reescritura se ejecuta sobre el HTML ya compilado, así que cubre por igual las imágenes de src/ y de public/.

Opciones

export default {
  images: {
    widths: [400, 800, 1200],
    formats: ['avif', 'webp'],
    quality: { avif: 55, webp: 78, jpeg: 82 },
    exclude: ['**/og/**'],
  },
}

Dos formatos te dan

AVIF es más pequeño pero más reciente que WebP, así que listar ambos deja que el navegador elija y mantiene una alternativa para los antiguos:

<picture>
  <source type="image/avif" srcset="/assets/img/hero.*-400.avif 400w, ..." sizes="...">
  <source type="image/webp" srcset="/assets/img/hero.*-400.webp 400w, ..." sizes="...">
  <img src="/assets/img/hero.*-1200.png" alt="..." srcset="..." width="1200" height="800">
</picture>

Cómo excluir imágenes

Las etiquetas que ya tienen un srcset, que están dentro de un <picture>, o que apuntan a un SVG, un GIF animado o una URL remota se dejan intactas. Para cualquier otra, dilo explícitamente:

<img src="/images/exact.png" alt="Pixel art" data-no-optimize>

Las imágenes de tarjetas sociales y favicons viven en <meta> y <link>, que esto nunca reescribe: conservan su URL fija.

Imágenes remotas

El contenido importado de un CMS suele apuntar al servidor de otra persona. Activa remote y esas imágenes se descargan, se optimizan y se sirven desde tu propio dominio:

export default {
  images: {
    remote: true,
    prune: true,
  },
}

Una descarga que falla deja la etiqueta exactamente como estaba, con un aviso: un origen inestable nunca hace fallar tu compilación. Después, prune elimina los originales locales que ya no referencia nadie.