Saltar al contenido

getImage y los servicios de imagen

La función que hay debajo del componente: getImage optimiza una imagen y te devuelve su src y sus atributos para los casos donde no cabe una etiqueta, como un fondo CSS o la og:image de las tarjetas sociales. Y por debajo de todo, el servicio de imagen que hace el trabajo real: Sharp como motor por defecto, Squoosh como opción heredada, y las pasarelas que delegan la transformación en un CDN o plataforma.

getImage: el motor sin el componente

<Image /> no hace magia propia: por dentro llama a getImage, calcula el resultado y lo pinta como una etiqueta. Si te saltas el componente y llamas tú a esa función, obtienes lo mismo que él usa, pero como datos manipulables en lugar de HTML ya cerrado. Es una función asíncrona: recibe las mismas opciones que las props del componente —src, width, format, quality— y devuelve un objeto con la URL optimizada en src, un attributes con los atributos calculados y un srcSet si procede.

ASTRO
---import { getImage } from 'astro:assets';import hero from '../assets/hero.png';const optimizada = await getImage({ src: hero, width: 800, format: 'webp' });---<img src={optimizada.src} width={optimizada.attributes.width} alt="Puerto" />

Ese optimizada.src es la ruta al fichero ya transformado que Astro emitirá; el resto del objeto son los metadatos con los que armar la etiqueta que necesites. Con getImage recuperas el control fino a cambio de escribir a mano lo que el componente te daba hecho.

Dónde brilla: fondos CSS y og:image

El primer caso claro es un fondo. No puedes poner un <Image /> dentro de background-image, pero sí puedes pedirle a getImage la URL optimizada y volcarla en el estilo. Así una imagen decorativa de fondo se beneficia del mismo reencode y redimensionado que cualquier otra.

ASTRO
---import { getImage } from 'astro:assets';import fondo from '../assets/fondo.jpg';const bg = await getImage({ src: fondo, width: 1920, format: 'webp' });---<section style={`background-image: url(${bg.src})`}>  <h1>Portada</h1></section>

El segundo caso es la imagen de las tarjetas sociales. Al compartir un enlace, las redes leen la <meta property="og:image">, y esa etiqueta exige una URL absoluta: el rastreador vive fuera de tu dominio y una ruta relativa no le sirve de nada. getImage te da la ruta optimizada, y combinándola con Astro.site —la URL de producción declarada en la config— la conviertes en absoluta.

ASTRO
---import { getImage } from 'astro:assets';import portada from '../assets/og.png';const og = await getImage({ src: portada, width: 1200, height: 630, format: 'png' });const ogUrl = new URL(og.src, Astro.site);---<meta property="og:image" content={ogUrl.href} />

El servicio de imagen: quién hace el trabajo

Ni el componente ni getImage transforman los píxeles por sí mismos: delegan en un servicio de imagen, un módulo intercambiable que sabe redimensionar y reencodear. Astro trae uno por defecto y te deja cambiarlo, y esa elección importa cuando el sitio sale del portátil y aterriza en un entorno de despliegue concreto.

El motor por defecto es Sharp, una biblioteca nativa rápida y de gran calidad que resuelve casi cualquier necesidad sin que la toques. Squoosh fue el servicio anterior, escrito en WebAssembly puro y por ello muy portable pero más lento; hoy es una opción heredada, en desuso y retirada de las versiones actuales, que conviene conocer solo para entender configuraciones antiguas. Y en el otro extremo están las pasarelas: servicios que no transforman la imagen en tu build ni en tu servidor, sino que delegan el trabajo en una plataforma o un CDN —Vercel, Netlify, Cloudflare, Cloudinary— que la optimiza bajo demanda en su propia infraestructura. Cambiar de servicio es cambiar una línea.

TypeScript
// astro.config.mjsimport { defineConfig, sharpImageService } from 'astro/config';export default defineConfig({  image: {    service: sharpImageService(),  },});

Hay un caso en que la pasarela o el servicio de paso dejan de ser un lujo y se vuelven necesarios: los entornos donde una biblioteca nativa como Sharp no puede instalarse o ejecutarse, ciertos runtimes de borde o funciones serverless muy restringidas. Allí se usa un servicio de paso que no transforma —confiando la optimización a la plataforma— o directamente el servicio de imágenes que esa plataforma ofrece. La misma llamada a <Image /> de tu código sigue igual; lo que cambia por debajo es quién ejecuta la transformación.

TypeScript
// astro.config.mjsimport { defineConfig, passthroughImageService } from 'astro/config';export default defineConfig({  image: {    service: passthroughImageService(),  },});

Un servicio de pasarela de terceros se enchufa igual, apuntando image.service a su punto de entrada y pasándole su configuración. Tu código de plantilla no se entera: sigue escribiendo <Image /> y getImage, y es la plataforma quien recibe las peticiones de transformación y devuelve las imágenes ya optimizadas desde su propia red. Esa indiferencia del código ante el motor es justo lo que hace el sistema portable entre despliegues.

TypeScript
// astro.config.mjsexport default defineConfig({  image: {    service: {      entrypoint: 'mi-proveedor/servicio',      config: { calidadPorDefecto: 'auto' },    },  },});