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.
<Image /> y <Picture /> cubren el noventa por ciento de los casos, pero hay lugares donde una etiqueta no cabe: el background-image de una hoja de estilos, la og:image que va en una <meta>, un manifiesto, un correo. Para todos ellos existe getImage, la función que hace el trabajo de optimización y te entrega el resultado en crudo —una URL y unos atributos— para que lo coloques donde quieras. Y bajo esa función, y bajo los componentes, opera una pieza que casi nunca ves pero que decide cómo se transforma cada imagen: el servicio de imagen. Esta lección baja esos dos peldaños, del componente a la función y de la función al motor.
- Usar
getImagepara optimizar una imagen y obtener susrcy sus atributos. - Resolver casos sin etiqueta como un fondo CSS o una
og:imagesocial. - Distinguir los servicios de imagen: Sharp, el heredado Squoosh y las pasarelas.
- Elegir el servicio según el entorno de despliegue y sus capacidades.
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.
---
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.
---
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.
---
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} />
Tres detalles hacen que una tarjeta social funcione. Debe ser absoluta, porque quien la lee no es tu navegador sino un servidor remoto que no conoce tu ruta base. Conviene un tamaño canónico —1200 por 630 es el estándar— para que las plataformas no la recorten mal. Y su URL debe ser estable entre despliegues, para que las vistas previas ya cacheadas no se rompan. getImage con dimensiones fijas y Astro.site cubre los tres.
flowchart TD GI[getImage con src y opciones] --> RES[objeto con src attributes y srcSet] RES --> C[url para background-image en CSS] RES --> O[url absoluta para la og image social] RES --> M[atributos para un img compuesto a mano] style GI fill:#89b4fa,color:#11111b style RES fill:#f9e2af,color:#11111b style C fill:#a6e3a1,color:#11111b style O fill:#a6e3a1,color:#11111b style M fill:#a6e3a1,color:#11111b
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.
// astro.config.mjs
import { 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.
// astro.config.mjs
import { 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.
// astro.config.mjs
export default defineConfig({
image: {
service: {
entrypoint: 'mi-proveedor/servicio',
config: { calidadPorDefecto: 'auto' },
},
},
});
getImage devuelve datos
Optimiza como el componente pero entrega src, attributes y srcSet para colocarlos donde no cabe una etiqueta.
Fondos y og:image
Un fondo CSS toma su url de src; una og:image la vuelve absoluta con Astro.site para que la lea otro servidor.
Sharp por defecto
El motor nativo rápido y de calidad. Squoosh es la opción heredada en WebAssembly, hoy en desuso.
Pasarelas
Delegan la transformacion en un CDN o plataforma, o usan un servicio de paso donde Sharp no puede correr.
Estas dos piezas —getImage bajo el componente, el servicio bajo getImage— son la misma idea vista en dos capas, y esa idea es de las más fértiles que ofrece un buen diseño de software: separar la intención de la maquinaria que la cumple. Arriba del todo, <Image /> expresa una intención con la máxima comodidad posible: aquí hay una imagen, muéstrala bien. No dice cómo, ni con qué motor, ni en qué formato exacto; solo qué quieres. Un peldaño abajo, getImage desnuda esa comodidad y expone la operación como una función que devuelve datos, para cuando la etiqueta ergonómica no encaja en tu hueco —un fondo, una meta, un manifiesto— y necesitas la primitiva en lugar del envoltorio. Y un peldaño más abajo, el servicio de imagen encarna el cómo puro: el mecanismo concreto que mueve los píxeles, deliberadamente intercambiable, de modo que el mismo código de arriba se ejecute con Sharp en tu máquina, con una pasarela en el borde o con el optimizador de una plataforma, sin que una sola línea de tus páginas lo note. Esa estratificación no es casual; es el patrón que hace que un sistema envejezca bien. Cuando la intención está separada de la implementación, puedes cambiar la maquinaria sin reescribir a quien la usa, y puedes ofrecer una fachada cómoda sin renunciar a una salida de emergencia hacia el nivel de abajo. Los frameworks que perduran son casi siempre los que aciertan con esta doble oferta: una superficie de alto nivel que resuelve el caso común sin fricción, y una primitiva de bajo nivel, accesible cuando la haces falta, que no te abandona en cuanto tu caso se sale del molde. getImage es esa primitiva, el servicio es ese mecanismo enchufable, y el componente es la fachada amable que descansa sobre ambos. Aprende a ver esa escalera en cada herramienta que uses —dónde está la comodidad, dónde la primitiva, dónde el mecanismo sustituible— y sabrás siempre a qué altura bajar cuando el caso fácil deje de bastarte.
- Usa
getImagepara optimizar una imagen y píntala con un<img>a mano tomandosrcy las dimensiones de su objetoattributes. - Aplica una imagen optimizada como
background-imagede una sección leyendo susrc, y compara su peso con el del fichero original. - Genera una
og:imagede 1200 por 630 congetImage, conviértela en URL absoluta conAstro.sitey colócala en la<meta>; valida la tarjeta con un depurador social. - Cambia el servicio a
passthroughImageServiceen la config, reconstruye y observa que las imágenes ya no se transforman, razonando en qué entorno de despliegue esa elección tendría sentido.