Prompts para Analizar y Testear Rendimiento Web con IA
10 prompts para testear rendimiento con IA: Lighthouse, Core Web Vitals, bundle size y detección de cuellos de botella antes de que lleguen a producción.
Tabla de contenidos
Lighthouse te dice que tienes un 62 en Performance. Bajas el informe, le das la mitad de las recomendaciones al modelo y te devuelve un par de párrafos genéricos sobre “optimizar imágenes” y “minificar JavaScript”. Aplicas dos cosas. La barra sube a 68. Te sientes útil durante veinte minutos.
A la semana siguiente, el jefe sigue diciendo que la web va lenta. Porque Lighthouse es un laboratorio: mide una máquina virtual con la red limitadas a 1,6 Mbps y la CPU a 4x de slowdown, en un móvil Moto G con pantalla de 412×823. Tus usuarios reales están en un iPhone 15 con fibra de 500 Mbps. El laboratorio y la realidad apuntan en direcciones distintas casi siempre.
El problema nunca es que falten herramientas. Tienes Lighthouse, WebPageTest, CrUX, Chrome DevTools, un profiler de bundle y 400 llamadas de observabilidad. El problema es que cada una te devuelve 800 líneas de datos que nadie sabe priorizar. Eso es justo lo que la IA hace bien: leer un JSON de 400 KB, entenderlo y decirte qué tres líneas importan.
Antes de pegar nada: qué datos tienes
Esto es lo primero que tienes que saber. El prompt se escribe en función del dato, no al revés.
| Dato | Cómo se obtiene | Para qué sirve |
|---|---|---|
| JSON de Lighthouse (lab) | npx lighthouse <url> --output=json --output-path=lh.json | Ver exactamente qué recurso bloquea el LCP y por qué |
| Core Web Vitals de campo | CrUX API o el panel de Search Console | Lo que realmente experimentan tus usuarios |
| Waterfall de red | Pestaña Network de DevTools, “Preserve log” | La secuencia de peticiones y los stalls |
| Stats del bundle | Salida de next build, vite build --mode analyze o un visualizador | Qué dependencias se están enviando |
| TTFB por ruta | Cabecera Server-Timing, APM (Datadog, Sentry) | Si el problema está en tu servidor o en el cliente |
| Long tasks | Performance panel, bloque “Long Animation Frames” | JS que bloquea el hilo principal y destruye el INP |
Si solo tienes el JSON de Lighthouse, trabaja con eso. Si tienes los dos, mucho mejor: le pides que compare laboratorio contra campo y que te diga qué discrepancia explica. Esa comparación es la parte que ningún dashboard te da hecha.
Reglas de oro antes de copiar
- Una métrica por prompt. Si le preguntas por LCP, TTFB, bundle y CLS en el mismo mensaje, te devuelve cuatro párrafos de Prioridad Media y no te dice qué arreglar primero. Separa.
- Obliga a citar la ruta del dato. Añade siempre “cita el campo exacto del JSON del que sacas cada conclusión”. Es lo que separa una respuesta verificable de una que te suena plausible.
- Prohíbe las recomendaciones genéricas. Nada de “optimiza tus imágenes” sin decir cuál, de cuánto a cuánto y con qué gain esperado. Si la respuesta es genérica, es que el modelo no ha leído el dato.
- Pide siempre el impacto estimado. “Cada cambio que propongas debe incluir el delta esperado sobre la métrica y en qué viñeta del informe se apoya”.
- Mide después de aplicar. El prompt es la mitad del trabajo. La otra mitad es reejecutar Lighthouse y comparar. Un prompt sin medición posterior es una opinión.
1. Convertir un JSON de Lighthouse en un plan de acción
Este es el prompt base. El resto son especializaciones.
Actúa como ingeniero de performance web. Voy a darte el JSON de Lighthouse de una URL.
Reglas:
- Cita el path exacto del JSON del que sacas cada conclusión (ej: audits["largest-contentful-paint-element"].details.items)
- No me des recomendaciones genéricas. Si no puedes señalar el recurso o la función concreta, no lo menciones
- Ordena por impacto real sobre las Core Web Vitals, no por el score de la auditoría
Devuélveme:
1. Una tabla con: métrica | valor medido | valor umbral | gap | auditoría Lighthouse asociada | recurso responsable
2. Los 3 cambios con mayor impacto, y para cada uno: qué editar, por qué mejora la métrica, y qué parte del informe lo confirma
3. Los cambios que NO deberías hacer todavía y por qué
Contexto de la app:
- Framework: [Next.js App Router / Astro / React + Vite / ...]
- Hosting: [Vercel / Netlify / VPS propio detrás de nginx]
- Datos: [SQLite local / Postgres en el mismo servidor / API externa a 800ms]
- Qué nos duele: [la home tarda 4s en móvil / el INP sube a 600ms / el LCP salta]
JSON:
```json
[pega aquí el contenido de lh.json]
**Por qué funciona**: el "cita el path exacto" es lo que fuerza al modelo a no inventar. Sin esa instrucción, la respuesta mezcla datos reales del JSON con conocimiento genérico de optimización web, y no distingues unos de otros.
**Ejemplo real** de lo que devuelve con un informe mediocre:
| Métrica | Medido | Umbral | Gap | Auditoría | Recurso responsable |
|---------|--------|--------|-----|-----------|---------------------|
| LCP | 4,12 s | 2,5 s | +1,62 s | `largest-contentful-paint-element` | `/assets/hero-desktop.jpg` (2,4 MB, sin `srcset`) |
| TTFB | 890 ms | 800 ms | +90 ms | `server-response-time` | Route handler `/api/posts` |
| CLS | 0,24 | 0,1 | +0,14 | `layout-shift-elements` | `<img>` sin `width`/`height` + fuente sin `font-display: optional` |
| TBT | 890 ms | 200 ms | +690 ms | `mainthread-work-breakdown` | `moment.js` (287 KB) en el bundle cliente |
### 2. Auditar Core Web Vitals con datos de campo
Si tienes CrUX, esto vale más que Lighthouse. CrUX te dice qué experimentan tus usuarios de verdad.
Tengo datos de CrUX (Chrome UX Report) de los últimos 28 días para mi web. Estos son los percentiles p75 por URL:
[p75_lcp]: [valor] ms [p75_inp]: [valor] ms [p75_cls]: [valor] ms Número de orígenes con datos suficientes: [n] Distribución de dispositivos: [mobile X%, desktop Y%]
Compara con los umbrales oficiales (LCP 2500ms, INP 200ms, CLS 0.1).
Quiero que:
- Me digas si estamos en “necesita mejora” o “pobre” en cada métrica
- Expliques por qué un LCP de laboratorio puede ser bueno y el de campo malo (o al revés)
- Me digas qué variables de tráfico explicarían esa discrepancia: % de móvil, red 4G vs 3G, caché de CDN, % en Android gama baja
- Dame la métrica que priorizaría primero y por qué el retorno por hora trabajada es mayor
Contexto adicional: [nuestro tráfico es 70% móvil, mayormente Android gama media, procedemos de campañas de Meta Ads]
**Por qué funciona**: separa explícitamente el dato de laboratorio del de campo. La mayoría de equipos optimiza contra el primero y se sorprende cuando el segundo no se mueve.
### 3. Leer una waterfall y encontrar el recurso que mata el LCP
La waterfall es donde vive la verdad del LCP. Si el elemento LCP es una imagen, casi siempre hay una de estas tres causas: se descarga demasiado tarde, bloquea el HTML, o tiene una prioridad equivocada.
Voy a pegarte el listado de network requests de una carga completa (pestaña Network de Chrome, “Preserve log”, waterfall) y el elemento LCP identificado.
Requests (en orden): [pega las filas: nombre | initiator | tipo | tamaño | prioridad | start | end | protocol]
Elemento LCP: [pega el nodo del DOM que marca Lighthouse como LCP]
Analiza la secuencia y dime:
- ¿En qué milisegundo empieza la petición del recurso LCP? (debería empezar MUCHO antes de cuando se necesita)
- ¿Hay requests secuenciales donde podrían ser paralelos? Señala las cadenas de 3+ pasos
- ¿Qué recurso es el “critical path” y cuál es el último en bloquear el render?
- ¿Qué recursos NO son necesarios para el primer render y deberían tener lazy loading?
- Si el LCP es una imagen: ¿está en un preload? ¿tiene fetchpriority=“high”? ¿es AVIF/WebP?
Dame el HTML/JSX exacto que debería tener ese recurso, no la descripción de lo que debería tener.
**Por qué funciona**: convertir la pregunta "¿por qué es lento?" en "¿qué hay en la tabla?" es lo que evita el divago. El modelo lee tiempos concretos y razona sobre ellos.
**Ejemplo real** de respuesta:
> La imagen `/assets/hero.jpg` empieza a las 1.840 ms. Llega a las 4.050 ms. El HTML finishes a los 1.120 ms, así que técnicamente podría haber empezado a descargarse antes. No hay `<link rel="preload">` para ella. Pesa 2,4 MB y está servida como JPEG. Con `fetchpriority="high"` y AVIF a 190 KB, el LCP baja a ~1,9 s.
```html
<link rel="preload" as="image" href="/assets/hero.avif" type="image/avif" fetchpriority="high" />
<img
src="/assets/hero.avif"
alt="..."
width="1200" height="630"
fetchpriority="high"
decoding="async"
/>
4. Analizar el bundle y encontrar la dependencia más pesada
El bundle es donde se va la mitad de tu presupuesto. La pregunta nunca es “qué framework uso” sino “qué se está yendo a la basura por la puerta”.
Voy a pegarte el desglose del bundle de mi aplicación y quiero saber qué se ha bloated en el bundle.
Framework: [Next.js 15 App Router / Vite 8 / Astro 5]
Presupuesto de JS para la ruta principal: [180] KB gzip
Desglose:
[pega la salida de `npx next build`, de rollup-plugin-visualizer, o el resultado de
`npx source-map-explorer dist/assets/*.js`]
Haz esto:
1. Lista los 10 módulos más pesados, con su peso gzip y el % del total
2. Marca cuáles son "candidatos a eliminación" (se pueden quitar sin rehacer la app),
cuáles son "candidatos a sustituir" (existe un equivalente más ligero)
y cuáles son "inevitable" (el core del framework)
3. Para cada candidato a sustitución, dame la alternativa concreta con su peso estimado
y si el cambio rompe algo (API incompatible, necesita migración)
4. Detecta patrones antipatrón: import * from, barrels que arrastran todo el módulo,
polyfills incluidos sin necesidad, librerías de fechas/dimensiones/MD duplicadas
5. Dame el código de la config que corregiría el tree-shaking roto
Contexto: [usamos lodash en 30 ficheros, dayjs y date-fns están los dos instalados,
tenemos 4 librerías de utilidades distintas (underscore, ramda, lodash, helpers propios)]
Por qué funciona: el modelo sabe qué alternativas pesan menos y conoce los casos donde un “sustitución” rompe la API. Lo que no sabe es qué usas tú — por eso el bloque de contexto es obligatorio.
Ejemplo real:
| Módulo | Gzip | Acción | Sustituto |
|---|---|---|---|
moment (+ locales) | 287 KB | Eliminar | Intl.DateTimeFormat nativo, 0 KB |
lodash (import * from) | 71 KB | Susituir | Imports granulares: 12 KB |
date-fns | 24 KB | Eliminar | Ya tienes Intl para formateo |
chart.js | 118 KB | Lazy | next/dynamic → solo carga en la ruta de charts |
@mui/icons-material | 210 KB | Susituar | SVG inline, 8 KB |
Eso son 710 KB gzip menos. No lo arregla un prompt: lo arregla saber exactamente qué mirar.
5. Diagnosticar TTFB y el tiempo de respuesta del servidor
Si el servidor tarda 2 segundos en responder, ningún frontend te salva. Y aquí la IA es especialmente útil porque suele haber cinco causas distintas con sintomas parecidos.
TTFB de mi aplicación en producción: [2.400] ms (p75).
El TTFB en staging con la misma carga: [180] ms.
Cabeceras de respuesta:
[pega el bloque de response headers, incluyendo Server-Timing si existe]
Base de datos y servicios:
- La ruta hace [N] consultas a Postgres, incluyendo [describe la más pesada]
- Llama a [servicio externo] que tarda [X] ms
- Está en [Vercel Edge / un contenedor en Coolify con 1 vCPU / nginx + PM2]
Quiero que:
1. Descompongas los 2.400 ms en fases (DNS + TCP + TLS + tiempo de procesamiento servidor + espera I/O)
2. Me digas si el caso es "la app tarda" o "la red tarda hasta tu servidor" y cómo lo distingo con un
`curl -w` de 4 líneas que me voy a copiar tal cual
3. Me los 3 cuellos de botella más probables ordenados por impacto, NO por facilidad de implementación
4. Para cada uno: el cambio concreto en código o infra, y cómo lo verifico que funcionó
5. Me señales si debería mirar cache, conexiones persistentes, o paralelizar queries
No me propongas "optimizar las consultas" sin decir cuál y cómo.
Por qué funciona: darle el contraste staging/producción es lo que permite a la IA descartar de golpe toda la capa de red y CDN. Es el detalle que más tiempo ahorra en la conversación.
6. Revisar imágenes, formatos modernos y responsive
Las imágenes siguen siendo, en 2026, la causa número uno de un LCP malo. Y el_arranque de la auditoría casi nunca mira lo importante.
Audita el tratamiento de imágenes de esta ruta de mi web: [URL o ruta]
Código actual de la imagen principal:
[pega el HTML/JSX/Astro del elemento LCP y de 2-3 imágenes más]
Contexto:
- Sirvo con [nginx / Vercel / Cloudflare / Coolify]
- Pipeline de imágenes: [next/image / <Image> de Astro / @unpic/astro / Cloudinary / HTML pelado]
- Viewports a soportar: [360, 768, 1024, 1440]
- Densidad de píxel típica: [2x móvil, 1x escritorio]
- Presupuesto de peso por imagen: [120] KB
Quiero:
1. El marcado final completo, listo para pegar, con srcset, sizes, width, height, loading,
fetchpriority y decoding donde aplique
2. La tabla de formatos y pesos esperados por breakpoint (AVIF vs WebP vs JPEG)
3. Dónde y cómo generar los derivados: build-time con un plugin, o runtime con una CDN
4. Qué hago con las imágenes debajo del fold (lazy loading no es la respuesta automática,
dime cuándo SÍ y cuándo NO)
5. El presupuesto en bytes y cómo lo fuerzo en CI para que no se rompa
Por qué funciona: el error típico es pedir “optimiza imágenes” y recibir “usa WebP”. Con el presupuesto en bytes y los breakpoints, recibes markup concreto.
Ejemplo real:
<picture>
<source type="image/avif" srcset="/img/hero-640.avif 640w, /img/hero-1280.avif 1280w" sizes="(max-width: 768px) 100vw, 50vw" />
<source type="image/webp" srcset="/img/hero-640.webp 640w, /img/hero-1280.webp 1280w" sizes="(max-width: 768px) 100vw, 50vw" />
<img src="/img/hero-1280.jpg" width="1280" height="720" alt="Dashboard de métricas en tiempo real" fetchpriority="high" decoding="async" />
</picture>
7. Auditar code splitting y lazy loading
Aquí el patrón de error es bastante claro: hacer dynamic import de todo hasta romper la navegación. El prompt tiene que entender eso.
Tengo una app [Next.js 15 App Router / Astro 5 / React Router 7] con estas rutas:
[lista de rutas con su peso de bundle]
Y este es el mapa de qué se importa en el entrypoint principal:
[pega el desglose o describe qué está en el bundle raíz]
Audita el code splitting:
1. ¿Qué rutas comparten más código del que deberían? Busca barrels, contexts globales y
providers que Live en el layout raíz
2. ¿Qué componentes pesados (gráficos, editores, mapas, rich text) NO deberían estar en el
bundle raíz? Lista los candidatos a lazy
3. ¿Qué se está importando con `import * from` o imports de barrel que rompen el tree-shaking?
4. ¿El dynamic import está definido a nivel de módulo o dentro del render? (diferencia enorme)
5. ¿Estoy precargando chunks que casi nadie visita?
Quiero el código del before y el after, y el efecto esperado en el JS de la ruta inicial.
También quiero saber qué NO conviene lazy: nada que esté en el camino crítico del primer render.
Por qué funciona: el modelo sabe distinguir dynamic() a nivel de módulo (solo parte el chunk) de un dynamic() dentro del componente (se resuelve en cada render). Es una diferencia que cuesta money en muchos tutoriales.
8. Auditar fuentes web y layout shift
El CLS casi siempre son fuentes o imágenes sin dimensiones. Es el hallazgo rápido que más satisfaction da.
Revisa este componente para problemas de CLS y de carga de fuentes:
[pega el componente completo: HTML/CSS/JSX]
Fuente usada: [Inter], cargada así:
[pega el @font-face o el <link> a Google Fonts / el import de next/font]
Dime:
1. Cuántos elementos pueden saltar al cargar la fuente y por qué
2. El código corregido con font-display, preload de la fuente crítica, y size-adjust / ascent-override
para que el fallback tenga métricas parecidas y el swap no provoque salto
3. Qué elementos necesitan width/height o aspect-ratio para reservar espacio
4. Si conviene subset de la fuente y qué caracteres son realmente necesarios
5. Cómo medir el CLS en local con el Performance panel y qué línea mirar
Ejemplo real de la corrección de una fuente:
@font-face {
font-family: 'Inter Fallback';
src: local('Arial');
/* Estas métricas hacen que el fallback ocupe casi lo mismo que Inter */
size-adjust: 107%;
ascent-override: 90%;
descent-override: 22%;
line-gap-override: 0%;
}
html {
font-family: 'Inter', 'Inter Fallback', system-ui, sans-serif;
font-display: swap;
}
Añadir aspect-ratio: 16 / 9 a la imagen hero quita el segundo salto. Dos líneas, medio punto de CLS.
9. Elegir estrategia de renderizado en Next.js
Aquí la IA es especialmente buena, porque los criterios son objetivos y muchos equipos eligen mal por inercia.
Mi app es [descripción]: Next.js 15 App Router, [contenido dinámico / mayormente estático /
mixto]. Base de datos: [Postgres]. Coste actual: [X] €/mes en [Vercel Pro / VPS].
Rutas actuales y cómo se renderizan hoy:
[describe cada una: estática, dynamic, ISR, SSR]
Analiza:
1. Para cada ruta, ¿qué estrategia de renderizado es la correcta y por qué? Justifica con
frecuencia de cambio de los datos, coste de la query y exigencia de personalización
2. ¿Cuántas de estas rutas deberían ser SSG o ISR en lugar de SSR? Estima el ahorro en
TTFB y en coste de invocaciones
3. ¿Qué pasa con `use cache` y las directivas de caché en Next.js 15? ¿Qué debería cachearse
a nivel de dato, de fetch y de componente?
4. ¿Los Server Components me están resolviendo algo real o solo estoy moviendo el JS de sitio?
Sé crítico: si todo acaba siendo `use client`, el RSC no aporta
5. El plan de migración en pasos, cada uno con su propio before/after y su métrica de éxito
Por qué funciona: si le das el coste actual y la frecuencia de cambio de datos, puede recomendar ISR con segundos de revalidación en lugar del “ponlo todo en estático” que dirían otros.
10. Revisar las tres capas de caché
Casi todo el mundo piensa en la caché del navegador. Casi nadie audita las otras dos. Y las tres fallan de forma distinta.
Audita la estrategia de caché de esta aplicación en sus tres capas.
Capa 1 — HTTP/CDN:
- Headers actuales de Cache-Control en: [rutas HTML / estáticos / API]
- CDN: [Cloudflare / Vercel Edge / nginx] con reglas actuales: [...]
Capa 2 — datos:
- [Prisma / Drizzle / SQL plano] contra [Postgres]
- Queries que se ejecutan en cada request: [...]
Capa 3 — aplicación:
- Redis?: [sí/no] con TTL actual: [...]
- Cache en memoria (LRU)?: [...]
- revalidateTag / unstable_cache: [...]
Para cada capa quiero:
1. Qué se cachea, con qué clave, y durante cuánto tiempo
2. El problema concreto de invalidación en cada una (stale data, cache stampede, thundering herd)
3. La cabecera o la llamada correcta en 2026 (Cache-Control: s-maxage + stale-while-revalidate,
revalidateTag, cacheTag...)
4. Cómo manejas la invalidación sin tumbar la cache entera en cada escritura
Y una pregunta difícil: ¿qué NO debería cachearse NUNCA en esta app y qué pasa si alguien lo cachea?
Por qué funciona: separa las tres capas y pide explícitamente la invalidación. La invalidación es donde los equipos se atascan, y es donde el modelo puede darte las APIs concretas (revalidateTag, revalidatePath).
Ejemplo real:
// app/api/posts/route.ts
export async function GET() {
const posts = await db.post.findMany({ orderBy: { createdAt: 'desc' } });
return Response.json(posts, {
headers: {
'Cache-Control': 'public, s-maxage=60, stale-while-revalidate=300',
},
});
}
// app/api/posts/route.ts (POST)
import { revalidateTag } from 'next/cache';
export async function POST(request: Request) {
await db.post.create({ data: await request.json() });
revalidateTag('posts'); // solo_posts, no toda la web
return Response.json({ ok: true }, { status: 201 });
}
11. Priorizar: Lighthouse (lab) contra Core Web Vitals (campo)
Este es el prompt que más impacto tiene a medio plazo, porque evita meses de optimizar la métrica equivocada.
Tengo estos dos conjuntos de datos de la MISMA web. Dime por qué difieren y cuál manda.
LAB (Lighthouse, móvil emulado, red 1.6 Mbps, CPU 4x slowdown):
- LCP: [1.850] ms INP simulado (TBT): [420] ms CLS: [0,05]
CAMPO (CrUX, p75, 28 días, usuarios reales):
- LCP p75: [3.900] ms INP p75: [310] ms CLS p75: [0,19]
Perfil de tráfico: [68% móvil Android gama media, 31% iOS, 1% desktop,
mayoritariamente acceso con 4G de latencia alta]
Preguntas:
1. ¿Qué explica que el LCP de campo sea [más del doble] que el de laboratorio?
Dame 3 hipótesis ordenadas por probabilidad y el test exacto para confirmar cada una
2. ¿Qué explica que el CLS de campo sea 4x el de laboratorio? Sospecha de dispositivos reales
vs emulador, pero dime qué más mirar
3. ¿El INP de campo indica interacción lenta aunque el laboratorio no lo marque? ¿Qué hacer?
4. Si solo tengo presupuesto para arreglar DOS cosas antes del próximo sprint, ¿cuáles y por qué
esas dos? El resto lo planifico para más adelante
Por qué funciona: convertir “el laboratorio y el campo no coinciden” en una lista de hipótesis con test de confirmación es exactamente lo que hace un ingeniero de performance senior.
Anti-patrones
1. Preguntar por todo en el mismo mensaje
❌ "Analiza este JSON de Lighthouse y dime cómo mejorar LCP, INP, CLS,
el bundle, las imágenes, las fuentes y la estrategia de renderizado"
Resultado: siete párrafos de Prioridad Media, cero prioridades, ninguna ruta de fichero citada. Tu tiempo de lectura sube y no cambias ni una línea.
✅ "En este JSON, el LCP falla (4,1s vs umbral 2,5s). Cita el path del audit que lo
identifica, dime qué recurso concreto es el LCP y cuál es su peso y su tiempo
de inicio. Nada más: solo LCP."
2. Aceptar la primera respuesta sin verificar el dato
❌ "Estos son los hallazgos del JSON: el LCP es una imagen de 2,4 MB y el CLS viene de
una fuente sin font-display. Aplica los cambios."
Aplicaste dos cambios y el LCP bajó a 3,2 s. El resto del CLS venía de un banner que insertas con un script de terceros.
✅ "Antes de aplicar nada, cita el path exacto de cada afirmación y dame la métrica
que debería mejorar y en cuánto. Si no puedes citar el path, di 'no lo sé'."
3. Usar solo Lighthouse como fuente de verdad
❌ Ejecutar lighthouse, obtener 98 en Performance, cerrar el ticket.
El 98 es en un móvil emulado con red cortada. Tus usuarios reales no usan esa red.
✅ lighthouse en local → candidatos. CrUX en producción → realidad.
Si divergen por encima del 40%, el CrUX manda.
4. Optimizar sin medir después
❌ Prompt → 6 cambios de una vez → "debería improving mucho"
Seis cambios simultáneos y un solo número final. Si no mejoró, no sabes cuál lo empeoró.
✅ Un prompt → un cambio → Lighthouse otra vez → anotar el delta → siguiente prompt.
Apunta los deltas en un fichero, en serio: ese histórico vale más que cualquier score.
5. Ignorar el peso de la respuesta de la IA
Cada respuesta de análisis de rendimiento con JSON dentro son 2.000-4.000 tokens. Con doce auditorías vas hacia las 40.000 solo en datos, sin una línea de tu código. Aprende a recortar el JSON: los audits que fallan, el network-requests de las 15 peticiones más pesadas y nada más. Lo cuento mejor en cómo aprovechar la ventana de contexto.
Errores frecuentes que verás con estos prompts
“El modelo dice que el bundle son 850 KB pero tu build dice 240 KB.” Pasa porque le pasaste el tamaño sin comprimir. Dile siempre “sin comprimir / con gzip” o pásale el output real del build, que ya viene en gzip.
“Me sugiere cosas que no existen en mi versión.” Los frameworks cambian rápido. Abre el prompt con la versión exacta: “Next.js 15.3 con React 19 y App Router” o “Vite 8 + Tailwind 3.4”. Sin eso te propose next/dynamic en un proyecto que usa Astro.
“El INP sale siempre en rojo y no lo consigo bajar.” El INP se mide por interacción, no por carga. El laboratorio lo estima a partir del TBT, que no es lo mismo. Si el TBT está bien y el INP no, el problema casi siempre es un handler largo o un re-render masivo al hacer clic. Pide el análisis del Long Animation Frames panel, no del bundle.
“Todas las recomendaciones son sobre imágenes.” Casi siempre es cierto y casi siempre es lo correcto arreglar primero. Pero si el TTFB está por encima de 1 segundo, estás optimizando la foto de un cuadro que tarda en llegar.
“El JSON tiene datos que no cuadran con lo que veo.” Los Lighthouse de localhost miden en local. Los campos network-server-latency y network-rtt se pueden forzar con --throttling-method=devtools para simular. Si quieres datos reales de red, mide desde el móvil con DevTools remoto.
El flujo completo
┌────────────────────────────────────────────────────────────┐
│ 1. MEDIR │
│ lighthouse --output=json + CrUX (p75 real) │
│ Save lh.json · Save en sheet: fecha + 3 métricas │
└───────────────────────┬────────────────────────────────────┘
▼
┌────────────────────────────────────────────────────────────┐
│ 2. RECORTAR EL JSON │
│ Solo audits fallidos + network-requests top 15 │
│ (≈800 tokens en vez de 4000) │
└───────────────────────┬────────────────────────────────────┘
▼
┌────────────────────────────────────────────────────────────┐
│ 3. UN PROMPT, UNA MÉTRICA │
│ "solo LCP, cita el path, impacto estimado" │
└───────────────────────┬────────────────────────────────────┘
▼
┌────────────────────────────────────────────────────────────┐
│ 4. VALIDAR EL DATO QUE HA DEVUELTO │
│ ¿El path del JSON existe? ¿El peso es gzip? │
│ No → pedir corrección antes de tocar código │
└───────────────────────┬────────────────────────────────────┘
▼
┌────────────────────────────────────────────────────────────┐
│ 5. UN CAMBIO. MEDIR OTRA VEZ. ANOTAR EL DELTA. │
│ lcp: 4.12s → 2.90s (+1.22s) ✅ mantener │
└───────────────────────┬────────────────────────────────────┘
▼
┌────────────────────────────────────────────────────────────┐
│ 6. FORZAR EN CI │
│ budgets de Lighthouse → bloquea el deploy si falla │
└────────────────────────────────────────────────────────────┘
Ese paso 6 es el que convierte todo lo demás en algo permanente. Un presupuesto de rendimiento en CI vale más que cualquier prompt.
Conclusión
La IA no mide el rendimiento de tu web. Lo que hace es convertir 400 KB de JSON en tres líneas accionables, y eso ya te ahorra una hora por auditoría. Pero el criterio sigue siendo tuyo: si la respuesta no cita el path exacto del dato, no la aceptes.
Tres cosas que me llevo de este proceso. Primero, siempre una métrica por prompt, porque mezclar LCP con bundle produce relleno. Segundo, medir después de cada cambio, porque seis cambios a la vez no te dan información. Tercero, y la más importante, el laboratorio y el campo son dos campos distintos: si divergen, gana el CrUX.
Si quieres el paso previo —tener tests que detecten regresiones de rendimiento antes de que se mergen— está en prompts para detectar regresiones con IA. Y si ya sabes que la app aguanta y lo que te preocupa es que se caiga con 500 usuarios simultáneos, mira prompts para load testing con k6.
Para construir los prompts en sí tienes la herramienta interactiva de prompts y la guía de los mejores prompts para programar con IA. Y si te interesa el caso real de una migración que pasó de React a Astro por rendimiento, está aquí: migrar React a Astro y qué pasó con Lighthouse.
Los tests de carga del servidor nunca se mezclan con los del navegador. Eso lo desarrollo en el artículo de k6.