Optimización de rendimiento con Claude Code: medición y Core Web Vitals
Mide y mejora LCP, INP, latencia de API, bundles y caché con Claude Code y ejemplos ejecutables.
Optimizar rendimiento no significa “hacer que la web parezca más rápida” de forma vaga. Significa medir cuánto espera el usuario, qué bloquea una interacción, qué mueve el layout durante la carga y qué recursos desperdicia el servidor. Después se reducen esos costes con cambios pequeños y verificables.
Claude Code ayuda mucho en este proceso porque puede leer el código, seguir posibles cuellos de botella, proponer parches y redactar pasos de verificación. La clave es no empezar por el parche. Primero se mide, luego se formula una hipótesis, se cambia una cosa y se vuelve a medir con la misma herramienta.
Usa como referencia oficial web.dev Core Web Vitals, Lighthouse docs y MDN Performance API.
Define Qué Es Rápido
El rendimiento web no cabe en un único número. LCP, Largest Contentful Paint, mide cuándo aparece el contenido principal. INP, Interaction to Next Paint, mide cuánto tarda la interfaz en responder después de una acción. CLS, Cumulative Layout Shift, mide movimientos inesperados del layout.
En una aplicación también importan la latencia p75 de API, el número de consultas a base de datos, el tamaño del bundle JavaScript, el peso de las imágenes y el trabajo síncrono en el hilo principal. El promedio puede ocultar usuarios lentos; p75 suele describir mejor la experiencia real de la mayoría.
flowchart LR
Measure["Medir"] --> Hypothesis["Crear hipótesis"]
Hypothesis --> Patch["Cambiar poco"]
Patch --> Verify["Volver a medir"]
Verify --> Keep["Conservar lo probado"]
| Métrica | Qué indica | Primer objetivo |
|---|---|---|
| LCP | Aparición del contenido principal | 2.5s o menos |
| INP | Respuesta a interacciones | 200ms o menos |
| CLS | Movimiento inesperado | 0.1 o menos |
| API p75 | Latencia que siente la mayoría | Depende de cada pantalla |
| JS transferido | JavaScript cargado al inicio | Comparar por ruta |
Dale Mejores Datos A Claude Code
Una buena petición incluye síntoma, reproducción, métricas actuales y límites.
La página /products de este repositorio es lenta.
El objetivo es reducir LCP móvil y p75 de /api/products.
Mediciones actuales:
- Lighthouse mobile Performance: 58
- LCP: 4.2s
- INP: 180ms
- CLS: 0.04
- /api/products p75: 920ms
Por favor:
1. Revisa imágenes, bundle, API y acceso a base de datos.
2. No cambies código solo por intuición; indica archivos y evidencia.
3. Prioriza cambios pequeños y medibles.
4. Incluye los comandos de verificación.
También son útiles la guía completa de depuración, desarrollo React con Claude Code y la guía de optimización de imágenes.
Script Ejecutable De Medición
Con Node.js 18 o superior puedes medir una página o API y obtener promedio y p75.
// measure-url.mjs
import { performance } from "node:perf_hooks";
const url = process.argv[2] ?? "https://example.com/";
const runs = Number(process.argv[3] ?? 5);
async function measureOnce() {
const start = performance.now();
const res = await fetch(url, { cache: "no-store" });
await res.arrayBuffer();
return {
status: res.status,
ms: performance.now() - start,
};
}
const samples = [];
for (let i = 0; i < runs; i += 1) {
samples.push(await measureOnce());
}
samples.sort((a, b) => a.ms - b.ms);
const avg = samples.reduce((sum, s) => sum + s.ms, 0) / samples.length;
const p75Index = Math.floor((samples.length - 1) * 0.75);
const p75 = samples[p75Index].ms;
console.table(
samples.map((sample, index) => ({
run: index + 1,
status: sample.status,
ms: sample.ms.toFixed(1),
}))
);
console.log(`avg=${avg.toFixed(1)}ms p75=${p75.toFixed(1)}ms`);
node measure-url.mjs http://localhost:3000/api/products 7
Comparte esta salida con Claude Code antes y después del cambio. Así el trabajo deja de ser una opinión y se convierte en una comparación repetible.
Casos De Uso Reales
| Caso | Causa común | Qué pedir a Claude Code |
|---|---|---|
| Dashboard SaaS lento | Todos los widgets cargan al inicio; librería de gráficos pesada | Diferir widgets secundarios y separar el código de gráficos |
| Listado ecommerce lento | Imágenes grandes y consultas N+1 de stock o reseñas | Revisar tamaños de imagen e include/select de DB |
| Artículo con mal LCP | Imagen principal tardía y scripts de anuncios tempranos | Priorizar la imagen principal y diferir terceros |
| Búsqueda admin bloqueada | Filtro síncrono sobre arrays grandes | Reducir complejidad, paginar o mover trabajo |
N+1 significa obtener una lista y luego ejecutar una consulta adicional por cada fila. Caché significa reutilizar un resultado durante poco tiempo, pero nunca debes compartir datos privados, permisos, precios sensibles o stock sin una clave y expiración correctas.
Ejemplo Ejecutable De Caché
Este ejemplo con Express compara un endpoint lento a propósito con otro cacheado. En producción usarías Redis o CDN, pero la memoria local basta para ver el efecto.
npm init -y
npm install express
node cached-api.mjs
// cached-api.mjs
import express from "express";
import { performance } from "node:perf_hooks";
const app = express();
const cache = new Map();
const ttlMs = 30_000;
async function loadProducts() {
await new Promise((resolve) => setTimeout(resolve, 800));
return [
{ id: 1, name: "Starter Plan", price: 1200 },
{ id: 2, name: "Pro Plan", price: 4800 },
];
}
async function cached(key, loader) {
const now = Date.now();
const hit = cache.get(key);
if (hit && hit.expiresAt > now) return { data: hit.data, cache: "hit" };
const data = await loader();
cache.set(key, { data, expiresAt: now + ttlMs });
return { data, cache: "miss" };
}
app.get("/api/products/raw", async (_req, res) => {
const start = performance.now();
const data = await loadProducts();
res.json({ cache: "none", ms: performance.now() - start, data });
});
app.get("/api/products/cached", async (_req, res) => {
const start = performance.now();
const result = await cached("products", loadProducts);
res.json({ ...result, ms: performance.now() - start });
});
app.listen(3000, () => {
console.log("Open http://localhost:3000/api/products/raw");
});
node measure-url.mjs http://localhost:3000/api/products/raw 3
node measure-url.mjs http://localhost:3000/api/products/cached 3
Cuando pidas caché, concreta el alcance: “cachea productos populares 30 segundos”, “no cachees stock” o “incluye userId en la clave”.
Ejemplo Ejecutable De Algoritmo
No todo cuello de botella está en la red. JavaScript síncrono pesado puede empeorar INP. Aquí se cambia una búsqueda repetida con includes por un Set.
// compare-lookup.mjs
import { performance } from "node:perf_hooks";
const a = Array.from({ length: 40_000 }, (_, i) => i);
const b = Array.from({ length: 40_000 }, (_, i) => i * 2);
function slowIntersection(left, right) {
return left.filter((item) => right.includes(item));
}
function fastIntersection(left, right) {
const rightSet = new Set(right);
return left.filter((item) => rightSet.has(item));
}
function time(label, fn) {
const start = performance.now();
const result = fn();
const ms = performance.now() - start;
console.log(`${label}: ${ms.toFixed(1)}ms (${result.length} hits)`);
}
time("slow", () => slowIntersection(a, b));
time("fast", () => fastIntersection(a, b));
node compare-lookup.mjs
Errores Frecuentes
No optimices solo para Lighthouse. Lighthouse es una medición de laboratorio; los usuarios reales tienen otros dispositivos, redes y estados de caché. Combínalo con Search Console, RUM y logs del servidor.
No añadas caché sin reglas de corrección. Precios, stock, permisos y datos personales necesitan clave, TTL e invalidación.
No pongas useMemo en todas partes. La memoización de React debe proteger rutas calientes medidas, no decorar todo el código.
No marques todas las imágenes como prioritarias. La imagen visible al inicio necesita tamaño estable y quizá prioridad; las imágenes inferiores suelen seguir siendo lazy.
No dividas bundles a ciegas. Usa análisis de bundle con Claude Code y code splitting con Claude Code para comparar impacto por ruta.
Reglas Para CLAUDE.md
## Performance rules
- Before optimizing, record the current metric and target metric.
- Prefer small, measurable changes over broad rewrites.
- Do not introduce shared cache for user-specific data.
- Avoid N+1 queries; use select/include or batching.
- Keep above-the-fold images sized and stable.
- After changes, report commands used for verification.
Estas reglas mantienen a Claude Code centrado en mejoras comprobables.
CTA De Consultoría
ClaudeCodeLab puede ayudarte a auditar una aplicación web con Claude Code, mejorar Core Web Vitals, aislar latencia de API/DB y crear un runbook práctico. Para una primera revisión útil, prepara URL, pantallas clave, resultado de Lighthouse, logs de APIs lentas y fecha objetivo.
Resultado Probado
Al ejecutar los ejemplos localmente, /api/products/raw se mantiene alrededor de 800ms porque tiene un retraso intencional, mientras que /api/products/cached baja a pocos milisegundos después de la primera petición. compare-lookup.mjs también muestra una mejora clara con Set. En proyectos reales los números no son tan limpios, pero el método sí: mide p75, cambia una cosa y vuelve a medir.
PDF gratis: cheatsheet de Claude Code
Introduce tu email y descarga una hoja con comandos, hábitos de revisión y flujos seguros.
Cuidamos tus datos y no enviamos spam.
Sobre el autor
Masa
Ingeniero enfocado en workflows prácticos con Claude Code.
Artículos relacionados
Permission receipt para Claude Code: alcance, prueba y rollback
Patrón de permission receipt para Claude Code: acciones permitidas, aprobación, pruebas, rollback y CTA de ingresos.
Agent Harness seguro para Claude Code y Codex: permisos, verificacion y rollback
Diseña un Agent Harness seguro para Claude Code y Codex con permisos, plan, verificaciones y rollback.
Subagentes de Claude Code: guía práctica para delegar trabajo de forma segura
Guía práctica de subagentes en Claude Code para dividir artículos y código: reglas, prompts, riesgos y checklist.