Astro 7.3: el candado que bloqueaba tus tests E2E en preview
Actualizas Astro. Lanzas la suite de Playwright. Un servidor de preview arranca bien y los demás se caen con un error que no habla de tus tests: habla de un lockfile.
Tú no habías puesto ningún lockfile. Y el commit de esa noche no tocaba nada de testing.
Ese error tiene una historia detrás, y la historia no va de ti. Va de los agentes de IA.
Astro 7.3.0 se publicó el 3 de septiembre de 2026 con tres cambios pequeños: el flag --ignore-lock llega a astro preview, el logger de runtime de Astro se pasa a los image services y cache providers custom, y @astrojs/cloudflare 14.3.0 incorpora un helper finalize() para worker entrypoints propios. No hay breaking changes. Ninguno de los tres cambia lo que puedes construir con Astro; los tres cambian cuánto tiempo pierdes cuando algo se rompe.
Todo lo que cuento aquí sale de las notas oficiales de la release de Astro 7.3, del changelog de astro 7.3.0, del changelog de @astrojs/cloudflare y de la referencia de CLI de Astro.
Vamos con el primero, que es el que más gente va a notar hoy mismo.
--ignore-lock llega a astro preview: el arreglo que se nota en el CI
astro preview levanta un servidor sobre tu build de producción. Es contra ese servidor contra el que corren tus tests E2E, porque probar contra astro dev es probar otra cosa: otro pipeline, otros assets, otro comportamiento.
Desde Astro 7.2, ese comando escribe un lockfile en .astro/preview.json — el mismo mecanismo que astro dev usa en .astro/dev.json desde Astro 7.0. Un servidor de preview por proyecto y punto: si intentas levantar el segundo, no arranca.
Astro 7.3 devuelve la escotilla:
npx astro preview --port 4322 --ignore-lock
El flag se salta la comprobación del lockfile y te deja arrancar tantos servidores de preview como quieras sobre el mismo proyecto, cada uno en su puerto. En Playwright, que es el caso de uso que el propio equipo de Astro menciona en las notas, se traduce en esto:
// playwright.config.ts
import { defineConfig } from 39;@playwright/test39;;
export default defineConfig({
webServer: [
{
command: 39;npx astro preview --port 4321 --ignore-lock39;,
url: 39;http://localhost:4321',
reuseExistingServer: !process.env.CI,
},
{
command: 39;npx astro preview --port 4322 --ignore-lock39;,
url: 39;http://localhost:4322',
reuseExistingServer: !process.env.CI,
},
],
});
Hay un detalle que conviene leer dos veces. Las notas oficiales avisan de que estas instancias corren de forma independiente, así que están pensadas para servidores rápidos y de usar y tirar, no para los que gestionas con astro preview stop o astro preview status. Traducido: si los arrancas a mano, los matas a mano. Dentro de Playwright da igual, porque el teardown del webServer se encarga.
Y un aviso que no está en el anuncio de la release pero sí en la referencia del CLI: --ignore-lock no se puede combinar con --background ni con --force, porque los dos dependen del lockfile. Si los juntas, Astro lanza un error.
Lo que convierte eso en un problema real: Astro activa el modo background por su cuenta cuando detecta que quien ejecuta el comando es un agente de IA. Traducido: si lanzas la suite desde dentro de una sesión de Claude Code o de Cursor, tu --ignore-lock puede petar sin que hayas escrito --background en ninguna parte.
La salida está documentada y es una variable de entorno:
ASTRO_PREVIEW_BACKGROUND=0 npx astro preview --port 4322 --ignore-lock
Si lanzas Playwright desde tu terminal, esto no te afecta. Si lo lanza un agente por ti, ponla en el webServer y te ahorras el segundo día de depuración.
Y hay un segundo escenario, menos obvio y más frecuente de lo que parece: no necesitas dos suites en paralelo para chocar con el candado. Basta con que algo ya lo tenga cogido. Un preview huérfano de la ejecución anterior. O tu agente de IA, que dejó uno levantado en segundo plano mientras trabajaba.
Esto último no es hipotético, y aquí es donde la release se pone interesante.
El candado no lo pusieron por ti
Astro 7 introdujo el lockfile en astro dev con un motivo explícito, y lo dicen ellos con todas las letras en su blog: para que los agentes de IA no levantaran servidores de desarrollo duplicados del mismo proyecto sin darse cuenta. Un problema que hace tres años no existía.
La secuencia completa es esta:
| Versión | Qué pasó |
|---|---|
| Astro 7.0 | Llega el lockfile a astro dev para frenar servidores duplicados de agentes de IA |
| Astro 7.1 | Se añade --ignore-lock a astro dev para quien sí quiere varios a propósito |
| Astro 7.2 | El lockfile se extiende a astro preview, pero sin escotilla |
| Astro 7.3 | --ignore-lock llega también a astro preview |
Si te interesa el contexto de dónde salió todo esto, lo conté cuando salió la major en el repaso de novedades de Astro v7.
Aquí está la lección, y va mucho más allá de Astro.
Tus herramientas están empezando a poner defaults pensados para un agente, no para ti. El lockfile es una decisión sensata cuando quien ejecuta el comando es un modelo que no recuerda si ya levantó el servidor hace diez minutos. Es una decisión molesta cuando quien lo ejecuta eres tú, con un playwright.config.ts delante y muy claro lo que quieres.
Astro lo ha resuelto bien: default seguro para el agente, flag explícito para el humano. Pero el patrón se va a repetir en todo tu stack, y la próxima vez a lo mejor no te dan el flag el mismo trimestre.
Por eso insisto tanto en esto cuando trabajo con agentes en el curso de Construye con IA: tienes que saber qué procesos deja vivos tu agente. No porque vaya a romper nada grave, sino porque el día que tu CI falle por un lockfile vas a perder dos horas buscando el bug en tu código.
Y ya que estamos en testing: el E2E es la capa cara. Casi todo lo que quieres verificar debería estar cubierto más abajo, donde una prueba cuesta milisegundos — lo desarrollé en pruebas unitarias ultrarrápidas con Vitest.
El logger de runtime llega a los image services y a los cache providers
Segundo cambio. Menos vistoso, y sin embargo es el que arregla un problema de higiene real.
Si mantienes un image service custom —el típico wrapper sobre Cloudinary, imgproxy o tu propio CDN— hasta ahora tu única forma de avisar de algo era console.warn(). Con la consecuencia obvia: ese warning se escupía siempre. Ignoraba el nivel de log del proyecto, ignoraba --silent y ensuciaba la salida del build igual en local que en CI.
En Astro 7.3, los image services reciben el logger de Astro como argumento adicional en transform():
import type { LocalImageService } from 39;astro39;;
const service: LocalImageService = {
// ...
async transform(inputBuffer, transform, imageConfig, logger) {
logger.warn(`No se pudo optimizar "${transform.src}". Se devuelve sin tocar.`);
return { data: inputBuffer, format: 39;png39; };
},
};
Y los cache providers lo reciben dentro del contexto que se pasa a onRequest():
import type { CacheProvider } from 39;astro39;;
const provider: CacheProvider = {
name: 39;my-cache39;,
async onRequest({ request, url, logger }, next) {
logger.warn(`Caché omitida en ${url.pathname}: la respuesta define una cookie.`);
return next();
},
// ...
};
El servicio Sharp integrado y el provider memoryCache() ya están migrados. Sharp lo usa para avisar de formatos de origen raros o no soportados; memoryCache(), para avisar de respuestas que se salta y de fallos en la revalidación en segundo plano.
La ganancia no es que ahora "haya logs". Es que tus warnings viajan por el mismo canal que los de Astro y respetan la configuración del proyecto. Si mantienes una integración propia, es un cambio de dos líneas.
Y sí, esto entra de lleno en la conversación de rendimiento: el image service es una de las piezas que decide el peso real de tus páginas, igual que las Server Islands que analicé en sitios web ultrarrápidos con Astro.
finalize() en @astrojs/cloudflare: el bug silencioso de las cookies
Tercer cambio, el más de nicho y el más peligroso de los tres si te toca.
Va para quien despliega en Cloudflare con un worker entrypoint propio en lugar del que genera el adapter. Ese pipeline manual funciona, pero se salta un paso: aplicar las cookies y los defaults de caché del CDN de Cloudflare a la respuesta que devuelve astro/fetch.
Un bug de esos que no rompe el build. Simplemente un día descubres que las cookies de sesión no llegan.
@astrojs/cloudflare 14.3.0, publicada el 3 de septiembre de 2026 —el mismo día que Astro 7.3—, añade finalize() para cerrar ese hueco. Recibe el FetchState y la respuesta del pipeline, y devuelve la respuesta ya con las cookies y la caché aplicadas:
// src/worker.ts
import { astro, FetchState } from 39;astro/fetch39;;
import { cf, finalize } from 39;@astrojs/cloudflare/fetch39;;
export default {
async fetch(request: Request, env: Env, context: ExecutionContext) {
const state = new FetchState(request);
const asset = await cf(state, env, context);
if (asset) return asset;
return finalize(state, await astro(state));
},
};
Si usas Hono, no tienes que hacer nada: el middleware @astrojs/cloudflare/hono aplica esas cabeceras por su cuenta.
El resto de la release te ahorra tiempo. Esta te ahorra un incidente.
¿Te toca actualizar a Astro 7.3?
No hay breaking changes, así que la pregunta no es si puedes, es si ganas algo.
| Tu situación | Qué hacer | Por qué |
|---|---|---|
Tienes E2E con Playwright sobre astro preview |
Actualiza hoy | Es la diferencia entre una suite que arranca y una que muere en el webServer |
| Trabajas a diario con un agente de IA en el proyecto | Actualiza hoy | Dejas de pelearte con él por el mismo lockfile |
| Mantienes un image service o cache provider custom | Actualiza y cambia dos líneas | Tus warnings pasan a respetar el nivel de log y --silent |
| Despliegas en Cloudflare con worker entrypoint propio | Sube @astrojs/cloudflare a 14.3.0 |
finalize() te quita el bug silencioso de las cookies |
| Sitio estático, sin E2E, sin adapter | Actualiza sin prisa | No hay riesgo, pero tampoco premio |
Si vienes de la rama 6.x, el salto que de verdad cambió cómo se construye con Astro no es este: fue el de Server Islands y Actions en 6.2. Astro 7.3 es mantenimiento fino sobre esa base.
Lo que yo haría esta semana
Abre tu playwright.config.ts y mira si el command del webServer llama a astro preview. Si es que sí, añade --ignore-lock y actualiza. Son treinta segundos y te ahorras el día en que el CI falle por un lockfile que tú no pusiste.
El resto puede esperar al próximo sprint.
Pero quédate con la idea de fondo, porque vale más que los tres cambios juntos: tu tooling ha empezado a asumir que quien escribe los comandos es un agente. Los defaults se están moviendo hacia ahí. Cuando algo se rompa de forma rara en tu pipeline, esa es la primera hipótesis que deberías poner sobre la mesa, y ya no la última.
De esto discutimos bastante en Dominicode Labs, porque casi todos los que estamos metiendo agentes en el flujo diario nos hemos comido alguna versión de este mismo problema.
Preguntas frecuentes
¿Qué hace exactamente –ignore-lock en astro preview?
Se salta la comprobación del lockfile que Astro 7.2 añadió a astro preview, de modo que puedes tener varios servidores de preview del mismo proyecto corriendo a la vez en puertos distintos. El flag ya existía en astro dev desde Astro 7.1; la 7.3 lo lleva también a preview.
¿Por qué astro preview –ignore-lock me da error?
Porque --ignore-lock no se puede combinar con --background ni con --force: las dos opciones dependen del lockfile, así que Astro lanza un error. Y cuando Astro detecta que el comando lo ejecuta un agente de IA, activa el modo background automáticamente, aunque tú no hayas pasado --background. Si te ocurre, desactiva ese automatismo con la variable de entorno ASTRO_PREVIEW_BACKGROUND=0 delante del comando.
¿Por qué existe ese lockfile si nadie lo pidió?
Porque Astro 7 lo introdujo para que los agentes de IA no levantaran servidores duplicados del mismo proyecto sin darse cuenta. Es un default pensado para un ejecutor que no recuerda si ya arrancó el servidor hace diez minutos, y por eso convive mal con flujos donde tú quieres varios servidores a propósito.
¿Los servidores lanzados con –ignore-lock se gestionan con astro preview stop?
No. Las notas oficiales avisan de que esas instancias corren de forma independiente y están pensadas para servidores rápidos y de usar y tirar, no para los que administras con astro preview stop o astro preview status. Si los arrancas a mano, los cierras a mano; dentro de Playwright se encarga el teardown del webServer.
¿Tengo que tocar mi image service custom para aprovechar el logger?
Solo si quieres. El cambio es aditivo: el logger llega como argumento adicional en transform() y dentro del contexto de onRequest() en los cache providers, así que tu código actual sigue funcionando. Cambiar console.warn() por logger.warn() es lo que hace que tus avisos respeten el nivel de log configurado y el flag --silent.
¿Necesito llamar a finalize() si uso Hono en Cloudflare?
No. El middleware @astrojs/cloudflare/hono aplica esas cabeceras automáticamente. finalize() está pensado para quien monta un worker entrypoint propio sobre astro/fetch y necesita aplicar a mano las cookies y los defaults de caché del CDN de Cloudflare.
¿En qué versión de @astrojs/cloudflare está finalize()?
En @astrojs/cloudflare 14.3.0, publicada el 3 de septiembre de 2026 junto a Astro 7.3. El adapter se versiona aparte de astro: subir astro a 7.3 no actualiza el adapter, tienes que subir los dos paquetes.
¿Hay breaking changes al actualizar a Astro 7.3?
No. Es una release menor de mantenimiento sobre la 7.2: un flag nuevo, un logger que se propaga a APIs de extensión y un helper añadido en @astrojs/cloudflare 14.3. La actualización del adapter de Cloudflare va aparte de la de astro, así que revisa que subes las dos si estás en ese escenario.
Si prefieres ver este tipo de análisis en vídeo, con el proyecto delante, lo publico en el canal de YouTube de Dominicode.
Por Bezael Pérez — Developer senior con más de 15 años de experiencia y fundador de Dominicode.
¿Te resultó útil este artículo?
Compártelo con tu comunidad y ayuda a otros desarrolladores.
