wandres.dev
DEPLOY · a producción

Anatomía del build: astro build, dist y preview

Qué produce exactamente astro build: la fábrica que congela el proyecto en artefactos terminados. La salida estática de dist frente a la salida de servidor client mas server cuando hay un adapter, cómo leer el resumen que imprime el build y por qué astro preview ensaya producción en local sin desplegar nada.

⏱ 15 min

Desarrollar es un diálogo: editas, guardas, el navegador responde. Desplegar es lo contrario, un monólogo congelado —el proyecto se cuece una vez y a partir de ahí solo se sirve—. astro build es el instante exacto de esa congelación: toma tu carpeta de fuentes, resuelve el contenido, compila los componentes, empaqueta el JavaScript de las islas y deja en dist/ un conjunto de artefactos terminados. Según tengas o no un adapter, esa carpeta significa dos cosas muy distintas: ficheros planos que cualquier CDN sirve sin pensar, o un manojo de assets junto a un manejador de servidor listo para ejecutarse. Entender qué hay dentro de dist/ es entender qué vas a desplegar.

🎯 Al terminar esta lección sabrás
  • Comprender qué hace astro build paso a paso, de la fuente al artefacto.
  • Distinguir la salida estática de dist/ de la salida client mas server con adapter.
  • Leer el resumen que imprime el build y saber qué páginas se prerenderizan.
  • Usar astro preview para ensayar la build de producción en tu máquina.

astro build: la fábrica que congela el proyecto

Un solo comando desencadena una cadena de trabajos que rara vez ves con detalle. astro build no es un paso atómico, sino una tubería con etapas bien definidas, y conocerlas te da un mapa mental para cuando algo falla.

astro build
# 1. carga astro.config.mjs y resuelve integraciones y adapter
# 2. ejecuta los loaders de contenido y valida los schemas
# 3. compila cada .astro con el compilador en Rust
# 4. Rolldown empaqueta el JavaScript de las islas
# 5. renderiza cada ruta prerenderizable a HTML
# 6. escribe todo en dist y emite un resumen

El orden importa. El contenido se resuelve antes de renderizar, porque una página no puede pintarse sin sus datos; las islas se empaquetan aparte del HTML, porque viajan por canales distintos —el marcado va horneado, el script se hidrata en el cliente—. Cuando el build se rompe, el mensaje casi siempre delata en qué etapa: un schema de Zod que no valida detiene la fase de contenido; un import roto detiene el empaquetado; un Astro.glob sin resultados aparece al renderizar.

Al terminar, Astro imprime un resumen que no es decorativo: es la radiografía del despliegue que estás a punto de hacer. Leerlo con atención dice más que abrir la carpeta a ciegas.

  • Cuántas páginas se prerenderizaron a HTML y cuántas quedaron como rutas bajo demanda.
  • El peso del JavaScript de cada isla, la métrica que de verdad gobierna el rendimiento percibido.
  • El tiempo total, repartido entre resolver contenido, compilar los .astro y empaquetar.
  • Avisos de assets pesados o imágenes sin optimizar que conviene atender antes de publicar.
ℹ️
El build es determinista, el dev server es tolerante

En desarrollo Astro es indulgente: recompila al vuelo, tolera estados a medias y solo procesa lo que visitas. El build es lo opuesto —recorre todas las rutas de una vez y no perdona—. Por eso un proyecto puede funcionar en dev y romperse en build: el build fuerza a resolver cada página, cada import y cada dato del sitio entero. Ejecutarlo a menudo en local es la forma más barata de descubrir esos fallos antes que tu servidor de despliegue.

dist como sitio estático

Sin adapter, el output es static y dist/ es literalmente el sitio: una jerarquía de ficheros terminados, sin una sola línea de tu código pendiente de ejecutar. Abrirlos revela la anatomía de una web horneada.

dist/
  index.html          # cada ruta, ya renderizada a HTML
  blog/
    primer-post/
      index.html
  _astro/             # JS de islas y CSS con hash de contenido
    hoisted.a1b2c3.js
    index.d4e5f6.css
  favicon.svg         # copiado tal cual desde public

Todo lo que ves aquí es inerte: bytes que ya existían antes de la primera visita. El HTML está completo, el CSS lleva un hash en el nombre para cachearse para siempre, y la carpeta _astro guarda solo el JavaScript de las islas que declararon una directiva client:. Servir esto no requiere cómputo: un CDN devuelve el fichero y termina. Esa es la razón de que el estático sea tan barato y tan rápido —no hay servidor que mantener ni proceso que pueda caerse—.

Conviene distinguir las tres clases de fichero que conviven en la carpeta, porque cada una se cachea de forma distinta:

  • El HTML de cada ruta, terminado y sin hash: su nombre no cambia aunque su contenido sí, así que debe revalidarse a menudo.
  • Los assets con hash en _astro: el nombre deriva del contenido, de modo que pueden cachearse para siempre sin riesgo de servir algo viejo.
  • Lo copiado de public tal cual: favicons, robots.txt y ficheros que quieres servir sin que Vite los reescriba.

Salida de servidor: client y server

En cuanto instalas un adapter y alguna ruta se renderiza bajo demanda, el build parte dist/ en dos mitades con roles opuestos. Ya no es un sitio terminado, sino un sitio a medio hornear que necesita un runtime para completarse.

📦

dist/client

Los assets terminados: HTML prerenderizado, CSS y el JavaScript de las islas. Lo sirve un CDN sin ejecutar nada.

⚙️

dist/server

El manejador que ejecuta las rutas bajo demanda. Es el código que el adapter conecta al runtime de destino.

🧭

El manifiesto

Un mapa que dice qué ruta está horneada y cuál va al handler. El adapter lo usa para repartir cada petición.

🔀

La mezcla es la norma

Portada estática, carrito dinámico. Un mismo build combina ambas salidas sin obligarte a elegir un extremo.

dist/
  client/   # servible por un CDN, igual que el estatico
  server/
    entry.mjs   # el punto de entrada que arranca el runtime

La lección clave es que dist/server no es un sitio: es un programa. Nadie lo sirve como ficheros; alguien lo ejecuta. Confundir las dos mitades es el error más común al desplegar SSR —subir dist/server a un CDN estático no produce nada, porque un CDN no arranca procesos—. El adapter existe justo para que cada mitad aterrice donde le corresponde.

💡
El resumen te dice qué se horneó y qué no

Tras un build con adapter, el resumen distingue las rutas prerenderizadas de las que quedaron bajo demanda, y esa lista es tu inventario: te dice con exactitud qué se sirve como fichero y qué ejecutará el runtime en cada visita. Si una ruta que creías estática aparece como dinámica —o al revés—, es la señal de que un prerender está mal puesto. Descubrirlo en el resumen del build es gratis; descubrirlo en la factura de cómputo de tu plataforma, no.

astro preview: el ensayo general

Entre construir y desplegar hay un abismo peligroso: nunca has visto correr eso que acabas de generar. astro preview cierra esa brecha levantando un servidor local que sirve dist/ tal cual, sin el andamiaje del dev server.

astro build && astro preview
# levanta dist en http://localhost:4321 como en produccion

La diferencia con astro dev es sustancial y por eso preview atrapa fallos que dev esconde. El dev server compila al vuelo, aplica HMR y no pasa por Rolldown en producción; preview no compila nada, sirve el artefacto real. Aquí afloran los problemas que solo existen tras el build: una ruta de asset que se rompió al empaquetar, un base mal configurado, una imagen que no se optimizó, una isla que se hidrata distinto sobre el bundle final.

Hay una regla de higiene que ahorra incidentes: nunca despliegues algo que no hayas servido al menos una vez con astro preview. El coste es de segundos y la recompensa es desproporcionada —cada fallo que preview atrapa en tu máquina es un fallo que no verá tu plataforma ni, peor, tu visitante—. Es el último control de calidad que está enteramente en tus manos antes de ceder el sitio a la red.

📝
preview no reemplaza a tu plataforma

astro preview sirve la salida con un servidor mínimo pensado para inspección local, no para producción. Con un adapter, preview puede necesitar el soporte del propio adapter para emular el runtime, y aun así no reproduce el edge real, sus límites de CPU ni sus variables de entorno. Trátalo como un ensayo general en el teatro vacío: comprueba que el decorado se sostiene, pero el estreno con público es el despliegue de verdad.

flowchart TD
SRC[src pages y contenido] --> COMP[compilador en Rust]
COMP --> BUND[Rolldown empaqueta las islas]
BUND --> OUT[carpeta dist]
OUT --> EST[modo estatico HTML y assets]
OUT --> SSR[modo servidor client mas server]
EST --> PREV[astro preview lo ensaya en local]
SSR --> PREV
style COMP fill:#89b4fa,color:#11111b
style OUT fill:#a6e3a1,color:#11111b
El build es la frontera donde el desarrollo se vuelve producto

Todo lo que has escrito hasta ahora vivía en un mundo mutable y perdonador: el dev server recompilaba al instante, toleraba errores parciales y solo miraba lo que tú mirabas. astro build es el rito de paso que convierte ese borrador vivo en un artefacto inmutable, y esa transición cambia las reglas de golpe. Lo que antes era un proceso que respondía a tus ediciones se congela en bytes que nadie volverá a tocar hasta el próximo build; lo que antes se resolvía perezosamente, ruta a ruta según la visitabas, ahora se resuelve entero y de una vez, sin excusas. Por eso el build es el primer lugar honesto de tu proyecto: es donde el sitio deja de ser una promesa que funciona en tu máquina y se convierte en una cosa terminada que puede fallar en la de otro. Y la anatomía de dist/ cuenta una verdad de arquitectura que trasciende Astro: la separación entre lo que se puede hornear y lo que hay que ejecutar es la línea que divide todo despliegue. Un CDN sirve ficheros; un runtime ejecuta código; confundir las dos mitades es el origen de la mayoría de los despliegues rotos. Aprender a leer esa carpeta —qué está terminado, qué está a medias, qué necesita un proceso vivo— es aprender a ver tu sitio como lo verá la plataforma que lo aloje, en lugar de como lo veías tú al escribirlo. El build no es un botón: es el momento en que tu código deja de ser tuyo y empieza a ser de la red.

⚔️ Disecciona tu propia salida de build
  1. Ejecuta astro build en un proyecto estático y explora dist/: identifica un HTML horneado, un CSS con hash y el contenido de _astro.
  2. Instala un adapter, marca una ruta con export const prerender = false, vuelve a construir y localiza las carpetas client y server.
  3. Lanza astro preview y compara la web servida con la que veías en astro dev: busca alguna diferencia de rutas o assets.
  4. Rompe a propósito un schema de contenido y observa en qué etapa exacta del build se detiene el proceso.