Expresiones en vivo y preservar el registro
El panel de expresiones que se reevalúan solas, su coste real, y las dos opciones de conservación del log que cambian qué puedes depurar.
Vigilar cómo cambia un valor mientras interactúas con la página tiene dos soluciones malas y una buena. Las malas son llenar el código de trazas —que ensucia la consola y exige recargar— y evaluar la expresión a mano cada vez, que interrumpe la interacción. La buena son las expresiones en vivo: un panel fijo en la parte superior de la consola con expresiones que se reevalúan solas varias veces por segundo y que no escriben nada en el registro.
- Crear y gestionar expresiones en vivo y elegir qué merece vigilarse así.
- Reconocer el coste de una expresión en vivo y evitar las que tienen efectos.
- Configurar la conservación del registro de consola y de red con criterio.
- Depurar flujos que atraviesan una navegación sin perder la información.
Cómo funcionan
En la barra de la consola hay un botón con forma de ojo. Al pulsarlo aparece un campo donde escribir una expresión, y al confirmarla queda fijada en una franja sobre el registro, con su valor actualizándose continuamente.
Se pueden tener varias a la vez. Sobreviven a la recarga de la página y a cerrar y abrir las DevTools, lo cual las convierte en una especie de panel de instrumentos persistente para el proyecto en el que estés trabajando.
Se evalúan en el contexto seleccionado, así que una expresión que dependa de una variable del iframe requiere tener ese contexto activo.
Los valores que más rinden vigilados así.
document.activeElement.tagName + '#' + document.activeElement.id
Ese, en particular, es un instrumento de accesibilidad excelente: te dice dónde está el foco en todo momento mientras navegas con el tabulador, incluido cuando el foco se pierde y aterriza en el cuerpo, que es exactamente el bug que estás buscando.
$$('[aria-hidden="true"]').length
performance.memory ? Math.round(performance.memory.usedJSHeapSize / 1048576) + ' MB' : 'n/d'
document.querySelectorAll('*').length
location.hash
navigator.onLine
El del número de nodos del documento es un detector de fugas de DOM sorprendentemente bueno: si sube monótonamente mientras usas la aplicación y no baja al cerrar cosas, tienes nodos acumulándose.
performance.memory es una extensión no estándar disponible en Chromium, con valores redondeados por motivos de seguridad. Sirve como indicador de tendencia y no como medida; para números serios, el panel de memoria.
El coste y los efectos
Dos advertencias importantes.
Se evalúan constantemente, varias veces por segundo, y ese trabajo se hace en el hilo principal de la página. Una expresión que recorra todo el DOM con $$('*') en una página con veinte mil nodos es un lastre medible, y si estás intentando diagnosticar un problema de rendimiento, tu propia instrumentación lo está agravando. La regla: quítalas antes de grabar un perfil.
Se evalúan de verdad, con sus efectos laterales. Una expresión con array.pop() vacía el array a razón de varias veces por segundo. Una que llame a un getter con lógica ejecuta esa lógica continuamente. Una que haga una petición hace muchísimas peticiones. La disciplina es que una expresión en vivo debe ser una lectura pura, y si no estás seguro de que lo sea, no la pongas.
Conservar el registro
Dos ajustes independientes con el mismo nombre y el mismo efecto conceptual: por defecto, tanto la consola como el panel de red se vacían en cada navegación, y ambos tienen una casilla para impedirlo.
Sin conservación, hay una familia entera de bugs que es imposible investigar, porque toda la información se destruye en el momento en que ocurre lo interesante.
El error justo antes de una redirección. Una página que redirige por un fallo de autenticación borra el error que explicaba el fallo.
El envío de formulario tradicional. Si el formulario navega, todo lo que ocurrió antes desaparece.
Los flujos de autenticación con varios saltos. Un inicio de sesión con proveedor externo pasa por tres o cuatro documentos, y sin conservación solo ves el último.
La cadena de redirecciones. El panel de red conservado muestra los tres o cuatro saltos con sus códigos de estado y sus cabeceras de destino, que es exactamente lo que necesitas cuando una redirección acaba en el sitio equivocado.
Con la conservación activada, los mensajes de cada documento quedan separados por una línea divisoria que indica la navegación, así que la secuencia se lee en orden.
El coste es la memoria y la velocidad: una consola con decenas de miles de líneas retenidas, cada una con sus objetos vivos, ralentiza el frontend de forma perceptible. Por eso la recomendación es activarla para investigar y desactivarla después, no dejarla puesta.
El caso del beforeunload
Hay un matiz técnico que merece conocerse. Cuando una página está a punto de descargarse, el navegador tiene poco tiempo y no garantiza que todo lo que emita llegue a la consola. Un console.log dentro de un manejador de beforeunload o de unload puede perderse.
La forma robusta de instrumentar ese momento es doble: usar el evento pagehide en lugar de unload, que es el recomendado y el que se dispara también cuando la página va a la caché de retroceso; y si el dato tiene que salir de la máquina, usar navigator.sendBeacon, que está diseñado precisamente para sobrevivir a la descarga del documento.
addEventListener('pagehide', e => {
console.warn('pagehide, persisted =', e.persisted);
});
El campo persisted de ese evento dice si la página se está guardando en la caché de retroceso en lugar de destruirse, lo que responde a una de las preguntas más difíciles de diagnosticar de todo el ciclo de vida.
Hay un patrón que combina las expresiones en vivo con la observación del DOM y que resuelve, en treinta segundos y sin tocar ni una línea del código, una categoría de bugs que la gente suele atacar con trazas durante media hora: vigilar el número de elementos que casan con una condición mientras interactúas. El razonamiento es que casi todos los bugs de estado en una interfaz se manifiestan como un desajuste de conteo. Si al abrir un modal aparecen dos overlays, la expresión $$('.overlay').length te lo dice en el momento exacto en que ocurre y sin ningún log. Si al cerrar una lista quedan listeners registrados, el conteo de un elemento característico no vuelve a cero. Si un componente se monta dos veces, el número salta de uno a dos y no baja. Si una fuga de nodos está en marcha, el conteo total sube monótonamente. Lo potente no es cada caso: es que el conteo cambia en el instante exacto de la interacción, y tú lo estás viendo mientras interactúas, lo cual establece una correlación temporal directa entre tu acción y el efecto, que es precisamente lo que las trazas no dan porque las lees después. Y hay una razón más profunda por la que este patrón funciona tan bien: te obliga a formular la invariante antes de mirar. Escribir la expresión exige decidir qué número debería mantenerse constante o cómo debería evolucionar, y eso es una hipótesis falsable escrita en una línea. Cuando el número hace algo distinto de lo que predijiste, ya no tienes un síntoma vago: tienes un momento concreto y una magnitud concreta, que es el punto donde poner un breakpoint de modificación del DOM y cerrar el caso.