Saltar al contenido

La solución de Astro: HTML por defecto

Astro invierte la regla: HTML estático primero, cero JavaScript salvo en las islas que tú declaras. El enfoque content-first y a quién beneficia de verdad: blogs, docs, e-commerce y marketing.

HTML por defecto, cero JavaScript

Un componente .astro es plantilla HTML con un bloque de script delimitado por --- (la “valla frontmatter”). Ese bloque corre en el servidor, durante el build o en la petición, y jamás se envía al navegador. Lo que el usuario recibe es el HTML resultante, sin runtime, sin framework, sin bundle de hidratación.

Usas expresiones de JavaScript para construir la página, pero todo lo verde se queda en el servidor y al cliente solo baja la lista ya renderizada en HTML.

No te lo creas: compruébalo. Esto es el compilador real de Astro corriendo en tu navegador. Pulsa «compilar», edita el componente y mira en qué se convierte — desde ahí recompila solo con cada pausa al teclear.

Lo que ves en el panel izquierdo no es el bundle que baja al navegador, sino la función de render que corre en el servidor. Busca saludo: no está: se evaluó y quedó su resultado. Y el <style> no aparece en el JS: salió al panel de CSS con un hash de scope.

Las islas: JavaScript solo donde lo pides

¿Y cuando sí necesitas interactividad —un buscador, un carrusel, un botón con estado—? Astro te deja usar componentes de React, Vue, Svelte, Solid o Preact, y los convierte en islas: fragmentos interactivos embebidos en un océano de HTML estático. Cada isla se activa con una directiva client:* que decide cuándo se hidrata.

Sin la directiva, un componente de framework se renderiza a HTML y se queda inerte, igual que un .astro. Con ella, y solo entonces, Astro envía el JS mínimo para esa isla concreta. El resto de la página no paga nada.

Quita una directiva client:* y recompila: la chip de esa isla desaparece de la lista. Eso que ves es la metadata real —hydratedComponents— de la que sale cada astro-island del HTML final. Cuando no queda ninguna, el compilador te lo dice con todas las letras: cero JS de cliente.

Las directivas se diferencian por el momento en que hidratan, y elegir bien es la palanca de rendimiento principal:

  • client:load hidrata en cuanto carga la página. Para lo crítico e inmediato: un botón de compra visible al entrar.
  • client:idle espera a que el navegador esté ocioso. Para lo interactivo pero no urgente.
  • client:visible hidrata al entrar en el viewport. Ideal para islas que viven en el fold inferior.
  • client:media hidrata solo si se cumple una media query: un menú que solo existe en móvil.

La regla de oro es la parsimonia: cada directiva que añades es JavaScript que el usuario descargará. client:load es tentador porque “siempre funciona”, pero convierte cada isla en coste inmediato.

Content-first: el contenido es de primera clase

Astro no trata el contenido como un añadido: lo pone en el centro. Las content collections te dejan definir un esquema tipado para tu Markdown y MDX, validado con Zod, de modo que tu frontmatter tiene tipos y autocompletado como cualquier otra estructura de datos.

TypeScript
import { defineCollection, z } from 'astro:content';const blog = defineCollection({  schema: z.object({    title: z.string(),    fecha: z.date(),    destacado: z.boolean().default(false),  }),});export const collections = { blog };

MDX permite mezclar componentes dentro de la prosa —esta misma guía lo hace: el playground de arriba es un componente dentro del texto—. El flujo entero, desde el fichero de contenido hasta el HTML final, está pensado para escribir mucho y enviar poco.

A quién beneficia

El modelo brilla justo donde la SPA desperdicia: donde el contenido manda y la interactividad es puntual.

  • Blogs y publicaciones: texto e imágenes, el terreno natural del HTML. Cero JS por artículo.
  • Documentación: miles de páginas estáticas con la búsqueda como única isla. Starlight, el tema oficial de docs, vive de esto.
  • E-commerce: catálogo y fichas de producto estáticos; carrito y checkout como islas.
  • Marketing y landings: páginas que deben cargar en un parpadeo para no perder conversión.