El panel de cobertura: qué se ejecutó y qué no
Cómo se graba una sesión de cobertura, qué significan exactamente sus dos modos de inicio, las columnas del resumen, y la visualización en el margen del código fuente.
El panel de cobertura instrumenta el navegador para registrar, byte a byte, qué partes de cada fichero de CSS y de JavaScript se han utilizado durante una sesión. El resultado es una tabla con porcentajes y una visualización en el margen del código que marca cada línea como usada o no usada. Es una de las herramientas más directamente accionables de las DevTools y también una de las que más decisiones equivocadas ha inspirado, por un malentendido sobre lo que significa la palabra “no usado”.
- Grabar una sesión de cobertura con el modo de inicio adecuado.
- Interpretar las columnas del resumen y la barra de proporción.
- Leer la visualización en el margen del código fuente.
- Exportar los datos para analizarlos fuera del panel.
Cómo se graba
El panel se abre por su nombre desde el menú de comandos y ofrece dos formas de empezar, que no son intercambiables.
Instrumentar y recargar. Activa el registro y recarga la página, capturando desde el primer byte. Es el modo correcto para auditar lo que se carga al arrancar, porque incluye todo el código ejecutado durante el arranque.
Instrumentar sin recargar. Empieza a registrar desde este instante, sobre la página tal como está. Es el modo correcto para responder una pregunta distinta: qué código adicional se ejecuta al hacer algo concreto. Empiezas a grabar, haces una interacción, y lo que aparezca como usado es lo que esa interacción necesitó.
Ese segundo modo se usa poco y es el más informativo de los dos, porque responde a “qué hace falta para esto” en lugar de a “cuánto sobra”.
Un uso que casi nadie hace y que resuelve una pregunta difícil: grabar sin recargar, navegar por todas las secciones de la aplicación, usar todas las funcionalidades que se te ocurran, y parar. Lo que quede sin usar después de ese recorrido exhaustivo sí es un candidato serio a código muerto, y no una simple cuestión de carga diferida. Es la única forma de acercarse a esa pregunta con esta herramienta.
El resumen
La tabla lista un fichero por fila con estas columnas.
URL. El recurso.
Tipo. CSS, JavaScript, o ambos cuando un documento HTML contiene los dos.
Bytes totales. El tamaño del fichero.
Bytes no usados. Cuántos no se ejecutaron ni se aplicaron.
Barra de proporción. La representación visual de la relación, que es lo que permite recorrer la lista rápido.
La ordenación por bytes no usados es la útil: pone arriba los ficheros donde hay más que ganar. Un fichero con el noventa por ciento sin usar pero que pesa dos kilobytes no importa; uno con el cuarenta por ciento sin usar y trescientos kilobytes de tamaño es donde está el trabajo.
El filtro de la parte superior permite quedarse solo con CSS o solo con JavaScript, y hay un campo de texto para filtrar por URL, que sirve para separar lo propio de lo de terceros.
La visualización en el margen
Al pulsar sobre una fila, el fichero se abre en el panel de fuentes con una barra de color en el margen izquierdo, junto a los números de línea. Cada línea lleva una marca según se haya usado o no.
Esa vista es donde el dato se vuelve accionable, porque permite ver qué no se usó, no solo cuánto. Y ahí aparecen patrones muy reconocibles.
Bloques enteros sin usar. Una función completa, una clase, una sección de estilos. Es el caso limpio: ese bloque es candidato a cargarse aparte o a desaparecer.
Líneas sueltas sin usar dentro de funciones usadas. Ramas condicionales que no se tomaron, manejo de errores que no se disparó, casos de un condicional múltiple que no se dieron. Esto no es código muerto y actuar sobre ello sería un error grave: es código que existe precisamente para los casos que no ocurrieron durante la sesión.
Un fichero entero sin ninguna marca de uso. Un módulo que se cargó y no se ejecutó nada de él. Es el hallazgo más valioso, y suele indicar una importación que quedó tras un cambio.
La distinción entre los tres patrones es la que decide si el dato es útil o peligroso, y por eso la lección de los límites es la más importante de este nivel.
Sacar los datos del panel
El panel permite exportar los datos de cobertura, y también se pueden obtener por código a través del protocolo. Para una comprobación rápida sin salir del navegador, hay una aproximación útil para CSS que no requiere el panel:
// Aproximacion a la cobertura de CSS: reglas cuyo selector no casa con nada ahora
(() => {
const resultados = [];
let totales = 0, sinCoincidencia = 0;
for (const hoja of document.styleSheets) {
let reglas;
try { reglas = hoja.cssRules; }
catch { resultados.push({ hoja: hoja.href, nota: 'inaccesible por origen cruzado' }); continue; }
const recorrer = (lista, contexto = '') => {
for (const r of lista) {
if (r.cssRules) { recorrer(r.cssRules, contexto + (r.conditionText || r.name || '') + ' '); continue; }
if (!r.selectorText) continue;
totales++;
let casa = false;
try { casa = document.querySelector(r.selectorText) !== null; }
catch { casa = true; } // selectores con pseudo-elementos no se pueden consultar
if (!casa) {
sinCoincidencia++;
resultados.push({
hoja: (hoja.href || 'en linea').split('/').pop(),
contexto: contexto.trim().slice(0, 30),
selector: r.selectorText.slice(0, 70),
declaraciones: r.style.length
});
}
}
};
recorrer(reglas);
}
console.log('Reglas examinadas:', totales, '| Sin coincidencia ahora mismo:', sinCoincidencia);
console.table(resultados.slice(0, 60));
console.warn('OJO: "sin coincidencia ahora" no es "no usada". Estados, otras rutas y');
console.warn('otros tamanos de ventana pueden hacer que casen. Esto es una pista, no un veredicto.');
})();
Ese fragmento tiene exactamente la misma limitación que el panel y la enuncia en voz alta: mide un instante. Su valor es que se puede ejecutar en varias rutas y estados, acumulando resultados, y la intersección de varias ejecuciones sí acota mucho más.
Toda la utilidad y todo el peligro de esta herramienta salen de la misma propiedad, así que conviene enunciarla con precisión desde el principio: la cobertura es un registro de ejecución, no un análisis del programa. No sabe qué hace tu código, no razona sobre qué caminos son alcanzables, no entiende condiciones. Solo anota qué bytes pasaron por el intérprete y qué reglas se aplicaron a algún elemento durante el rato que estuvo mirando. Eso hace que la palabra “no usado” que aparece en la interfaz signifique algo mucho más modesto de lo que sugiere: no significa “innecesario”, significa “no ejecutado en esta sesión concreta”. La diferencia entre las dos lecturas es la diferencia entre una herramienta de optimización y una máquina de romper cosas. El manejo de errores de una petición que no falló aparece como no usado, y borrarlo deja la aplicación sin red de seguridad. Los estilos de un estado de validación que no se alcanzó aparecen como no usados, y borrarlos rompe el formulario para quien se equivoque. El código de una funcionalidad de administración que tu cuenta de prueba no tiene aparece como no usado, y borrarlo se descubre cuando llama el cliente. Ninguno de esos tres es un fallo de la herramienta: los tres son exactamente lo que la herramienta dice, leído mal. La forma correcta de usarla es como generadora de hipótesis y nunca como fuente de decisiones. Un fichero con el noventa por ciento sin usar plantea la pregunta de por qué se carga entero al arrancar, y esa pregunta se responde leyendo el código, no borrándolo. Un módulo sin ninguna ejecución plantea la pregunta de quién lo importa, y esa se responde con una búsqueda. La regla que resume el nivel entero, y que conviene aplicar sin excepciones: la cobertura decide qué mirar; solo la comprensión del código decide qué cambiar.