wandres.dev
PERFORMANCE II · Las métricas en vivo

Las métricas en vivo: medir mientras usas la página

La vista que muestra LCP, CLS e INP actualizándose en tiempo real, cómo se compara con los datos de campo del mismo origen, y para qué sirve de verdad.

⏱ 16 min

Antes de existir esta vista, comprobar el efecto de un cambio sobre una métrica exigía grabar un perfil, esperar a que se procesara y leer un número enterrado. Ahora la pantalla de entrada del panel de rendimiento muestra las tres métricas principales actualizándose mientras usas la página, con el elemento responsable y el registro de interacciones al lado. Eso convierte un ciclo de dos minutos en uno de dos segundos, y un ciclo de dos segundos cambia por completo cómo se trabaja.

🎯 Al terminar esta lección sabrás
  • Leer las métricas locales en vivo y saber cuándo cada una queda fijada.
  • Comparar el valor local con el dato de campo del mismo origen y explicar las discrepancias.
  • Usar el registro de interacciones para encontrar la peor y reproducirla.
  • Reproducir la misma medición desde el código con la API de rendimiento.

Qué muestra y cuándo se fija cada valor

Al abrir el panel de rendimiento sin grabar nada, la vista muestra tres tarjetas con los valores de esta pestaña, ahora mismo.

La pintura de contenido mayor aparece pronto y puede cambiar varias veces durante la carga: cada vez que se pinta un elemento mayor que el anterior candidato, el valor se actualiza. Queda fijado en la primera interacción del usuario, porque a partir de ahí lo que se pinta ya no es carga sino respuesta. Esa regla explica un comportamiento desconcertante: si haces clic mientras la página carga, congelas la métrica en un valor artificialmente bueno.

El desplazamiento acumulado de disposición crece durante toda la vida de la página. No se fija nunca. Un valor bajo tras dos segundos no dice nada sobre lo que pasará cuando el usuario haga scroll y se carguen imágenes perezosas.

La interacción con la siguiente pintura no existe hasta que interactúas. Después muestra el valor de la peor interacción registrada, no de la última, porque lo que interesa es el peor caso que sufrió el usuario.

La vista incluye además un registro con todas las interacciones y su duración, ordenables. Esa lista es más útil que el número agregado, porque permite encontrar la interacción concreta que fue mal y repetirla con el panel grabando.

💡
Tip

La misma pantalla permite fijar la ralentización de CPU y de red y desactivar la caché sin ir a otro panel, y esos ajustes se aplican a las métricas en vivo. Es la forma más rápida de responder a la pregunta “y en un móvil de gama media, ¿cuánto sería esto?”: cambias el preajuste, recargas, y el número se actualiza.

Local frente a campo

Cuando hay datos disponibles para el origen que estás visitando, la vista los muestra al lado de los locales. Son dos cosas distintas y la comparación es informativa precisamente por eso.

El valor local es una medición de tu navegador, en tu máquina, con tu red, con tu perfil, con la página en el estado en que la has dejado. Muestra concreta, tamaño uno.

El valor de campo es un percentil agregado de usuarios reales del mismo origen durante un periodo largo. No es tu página necesariamente: dependiendo de la granularidad disponible, puede ser el origen entero, con todas sus rutas mezcladas.

Cuando los dos números discrepan mucho, la discrepancia es el dato. Un valor local excelente y uno de campo malo significa que tu entorno no representa al de tus usuarios, lo cual es prácticamente siempre cierto y a veces por márgenes enormes. Un valor local malo y uno de campo bueno suele significar que estás midiendo una ruta poco visitada, o que tu extensión favorita está haciendo daño.

La regla operativa que se deriva: el campo decide qué hay que arreglar, el laboratorio decide cómo. Si el campo dice que la métrica de respuesta es mala y tú no consigues reproducirlo, el problema no es que el campo se equivoque: es que te falta el dispositivo, el volumen de datos o la ruta correcta.

La misma medición desde el código

Todo lo que muestra esa vista sale de APIs estándar, y tenerlas a mano en un snippet permite medir sin abrir ningún panel y, sobre todo, instrumentar producción.

// Vigilante de las tres metricas principales, con el elemento responsable
(() => {
  const estado = { lcp: null, cls: 0, inp: 0, interacciones: [] };

  new PerformanceObserver(l => {
    const e = l.getEntries().at(-1);
    estado.lcp = {
      ms: Math.round(e.startTime),
      elemento: e.element,
      url: e.url || '(nodo de texto)',
      tamano: e.size
    };
  }).observe({ type: 'largest-contentful-paint', buffered: true });

  new PerformanceObserver(l => {
    for (const e of l.getEntries()) {
      if (e.hadRecentInput) continue;
      estado.cls += e.value;
      if (e.value > 0.01) {
        console.warn('Salto de', e.value.toFixed(4), 'afectando a',
          e.sources.map(s => s.node));
      }
    }
  }).observe({ type: 'layout-shift', buffered: true });

  new PerformanceObserver(l => {
    for (const e of l.getEntries()) {
      if (!e.interactionId) continue;
      const d = Math.round(e.duration);
      estado.interacciones.push({ tipo: e.name, ms: d, destino: e.target });
      if (d > estado.inp) estado.inp = d;
    }
  }).observe({ type: 'event', buffered: true, durationThreshold: 16 });

  window.metricas = () => {
    console.log('LCP:', estado.lcp?.ms, 'ms sobre', estado.lcp?.elemento);
    console.log('CLS acumulado:', estado.cls.toFixed(4));
    console.log('Peor interaccion:', estado.inp, 'ms');
    console.table(estado.interacciones.sort((a, b) => b.ms - a.ms).slice(0, 12));
    return estado;
  };

  console.log('Midiendo. Usa la pagina y ejecuta metricas()');
})();

Dos matices sobre este código que explican por qué sus números no coinciden exactamente con los del panel. El primero es que el umbral de duración del observador de eventos descarta las interacciones cortas, cosa que hay que hacer por rendimiento pero que sesga la lista. El segundo es que la métrica de respuesta real no es simplemente el máximo de las duraciones: con muchas interacciones se usa un percentil alto en lugar del máximo, para que una anomalía aislada no defina la experiencia entera. Para una sesión de depuración el máximo es lo que interesa; para una métrica de campo, no.

Para qué sirve de verdad

Hay tres usos donde esta vista es claramente la herramienta correcta, y uno donde no lo es.

Iteración rápida. Cambias algo, recargas, miras el número. Sin grabar, sin procesar, sin leer. Para una sesión de optimización donde vas a probar quince cosas, esto multiplica por diez la cadencia.

Encontrar el elemento culpable. La tarjeta de la pintura mayor identifica el nodo concreto, y el registro de saltos identifica los nodos que se movieron. Esa información es la que convierte una métrica en una tarea.

Vigilancia pasiva mientras trabajas. Dejar el panel abierto en esta vista mientras desarrollas hace que una regresión se note en el momento en que se introduce y no tres semanas después.

Y el uso equivocado: como fuente de un número para reportar. Una medición local es una muestra de tamaño uno en un entorno atípico. Sirve para comparar contigo mismo hace un minuto, no para afirmar cuánto tarda la página.

Medir constantemente cambia lo que construyes, y ese es el verdadero valor de esta vista

El efecto más importante de tener estas métricas siempre a la vista no es diagnóstico sino conductual, y merece la pena decirlo explícitamente porque no es obvio. Cuando medir cuesta dos minutos, se mide al final: se construye la funcionalidad entera, se pasa a control de calidad, y si alguien se acuerda, se perfila antes de la salida. En ese punto, cualquier hallazgo llega demasiado tarde para cambiar una decisión de arquitectura, así que se convierte en una lista de micro-optimizaciones que arañan un diez por ciento sobre una estructura que ya está decidida. Cuando medir cuesta dos segundos, se mide durante, y entonces el rendimiento deja de ser una fase y pasa a ser una restricción de diseño. La diferencia se ve en el tipo de decisiones que se toman: alguien que ve el número mientras escribe descubre en el momento que esa librería de fechas añade cuatrocientos milisegundos al arranque, y todavía está a tiempo de no usarla; alguien que lo descubre tres meses después se encuentra con doscientos usos repartidos por el código y escribe un ticket de deuda técnica que nadie hará. Esto tiene una implicación práctica sobre cómo montar el entorno de trabajo, y es que conviene bajar el coste de medir hasta hacerlo despreciable: dejar el panel en esta vista mientras se desarrolla, tener la ralentización de CPU puesta por defecto en el perfil de desarrollo en lugar de activarla ocasionalmente, y tener el observador de métricas cargado en el arranque de la aplicación en modo desarrollo para que la consola avise sola. Ninguna de esas tres cosas cuesta nada una vez montada, y las tres convierten el rendimiento en algo que se nota mientras se escribe el código en vez de en algo que se descubre cuando ya no se puede cambiar. La regla general, que vale mucho más allá de este panel: el coste de medir determina la frecuencia con la que se mide, y la frecuencia con la que se mide determina el diseño del sistema.