Depuración web moderna en Herramientas para desarrolladores de Chrome

Introducción

Hoy en día, los autores pueden usar muchas abstracciones para compilar sus aplicaciones web. En lugar de interactuar directamente con las APIs de bajo nivel que proporciona la plataforma web, muchos autores aprovechan frameworks, herramientas de compilación y compiladores para escribir sus aplicaciones desde una perspectiva de nivel superior.

Por ejemplo, los componentes creados sobre el framework de Angular se crean en TypeScript con plantillas HTML. En el fondo, la CLI de Angular y Webpack compilan todo en JavaScript y en un llamado paquete, que luego se envía al navegador.

Cuando depuras o generas perfiles de aplicaciones web en DevTools, actualmente puedes ver y depurar esta versión compilada de tu código en lugar del código que realmente escribiste. Sin embargo, como autor, esto no es lo que quieres:

  • No quieres depurar el código JavaScript reducido, sino el código JavaScript original.
  • Cuando usas TypeScript, no quieres depurar JavaScript, sino depurar tu código TypeScript original.
  • Cuando usas plantillas, como con Angular, Lit o JSX, no siempre quieres depurar el DOM resultante. Es posible que desees depurar los componentes.

En general, es probable que quieras depurar tu propio código tal como lo escribiste.

Si bien los mapas de origen ya cierran esta brecha en cierta medida, Chrome DevTools y el ecosistema pueden hacer más en esta área.

Veamos las diferencias.

Código creado en comparación con el código implementado

Actualmente, cuando navegas por el árbol de archivos en el panel Sources, puedes ver el contenido del paquete compilado y, a menudo, reducido. Estos son los archivos reales que descarga y ejecuta el navegador. DevTools lo llama Código implementado.

Captura de pantalla del árbol de archivos en las Herramientas para desarrolladores de Chrome que muestra el código implementado.

Esto no es muy práctico y, a menudo, es difícil de entender. Como autor, quieres ver y depurar el código que escribiste, no el código implementado.

Para compensarlo, ahora puedes hacer que el árbol muestre el código creado por el autor. Esto hace que el árbol se parezca más a los archivos fuente que ves en tu IDE, y estos archivos ahora están separados del código implementado.

Captura de pantalla del árbol de archivos en las Herramientas para desarrolladores de Chrome que muestra el código creado por el autor.

Para habilitar esta opción en DevTools de Chrome, ve a Configuración > Experimentos y marca Group sources into Authored and Deployed trees.

Captura de pantalla de la configuración de DevTools.

“Solo mi código”

Cuando usas dependencias o compilas sobre un framework, los archivos de terceros pueden interferir. La mayoría de las veces, solo quieres ver tu código, no el de alguna biblioteca de terceros escondida en la carpeta node_modules.

Para compensarlo, DevTools tiene un parámetro de configuración adicional habilitado de forma predeterminada: Agregar automáticamente secuencias de comandos de terceros conocidas a la lista de elementos ignorados. Puedes encontrarla en DevTools > Configuración > Lista de elementos ignorados.

Captura de pantalla de la configuración de DevTools.

Con este parámetro de configuración habilitado, DevTools oculta cualquier archivo o carpeta que un framework o una herramienta de compilación haya marcado como para ignorar.

A partir de la versión 14.1.0 de Angular, el contenido de las carpetas node_modules y webpack se marcó como tal. Por lo tanto, estas carpetas, los archivos que contienen y otros artefactos de terceros no aparecen en varios lugares de DevTools.

Como autor, no necesitas hacer nada para habilitar este nuevo comportamiento. Depende del framework implementar este cambio.

Código en la lista de elementos ignorados en los seguimientos de pila

Un lugar en el que ya no aparecen estos archivos de la lista de elementos ignorados es en los seguimientos de pila. Como autor, ahora puedes ver más seguimientos de pila relevantes.

Captura de pantalla de un seguimiento de pila en DevTools.

Si quieres ver todos los marcos de llamadas del seguimiento de pila, puedes hacer clic en el vínculo Mostrar más marcos.

Lo mismo se aplica a las pilas de llamadas que ves mientras depuras y recorres tu código. Cuando los frameworks o los empaquetadores informan a DevTools sobre secuencias de comandos de terceros, DevTools oculta automáticamente todos los marcos de llamadas irrelevantes y omite cualquier código de la lista de elementos ignorados durante la depuración paso a paso.

Captura de pantalla del depurador de fuentes de DevTools durante la depuración.

Código de la lista de elementos ignorados en el árbol de archivos

Para ocultar los archivos y las carpetas de la lista de elementos ignorados del árbol de archivos Código creado por el autor en el panel Sources, marca Hide ignore-listed code in sources tree view en Settings > Experiments en DevTools.

Captura de pantalla de la configuración de DevTools.

En el proyecto de Angular de ejemplo, las carpetas node_modules y webpack ahora están ocultas.

Captura de pantalla del árbol de archivos en las Herramientas para desarrolladores de Chrome que muestra el código creado por el autor, pero no node_modules.

Código de la lista de elementos ignorados en el menú “Abrir rápido”

El código de la lista de elementos omitidos no solo se oculta del árbol de archivos, sino también del menú "Abrir rápido" (Control + P (Linux/Windows) o Comando + P (Mac)).

Captura de pantalla de DevTools con el menú "Abrir rápido".

Más mejoras en los seguimientos de pila

Después de analizar los seguimientos de pila relevantes, las Herramientas para desarrolladores de Chrome presentan aún más mejoras en ellos.

Seguimientos de pila vinculados

Cuando algunas operaciones se programan para que se ejecuten de forma asíncrona, los seguimientos de pila en DevTools solo cuentan una parte de la historia.

Por ejemplo, este es un programador muy simple en un archivo framework.js hipotético:

function makeScheduler() {
  const tasks = [];

  return {
    schedule(f) {
      tasks.push({ f });
    },

    work() {
      while (tasks.length) {
        const { f } = tasks.shift();
        f();
      }
    },
  };
}

const scheduler = makeScheduler();

function loop() {
  scheduler.work();
  requestAnimationFrame(loop);
};

loop();

… y cómo un desarrollador podría usarla en su propio código en un archivo example.js:

function someTask() {
  console.trace("done!");
}

function businessLogic() {
  scheduler.schedule(someTask);
}

businessLogic();

Cuando agregas un punto de interrupción dentro del método someTask o cuando inspeccionas el seguimiento impreso en la consola, no ves ninguna mención de la llamada a businessLogic() que fue la “causa raíz” de esta operación.

En cambio, solo ves la lógica de programación del framework que llevó a la ejecución de la tarea y no hay migas de pan en el seguimiento de pila para ayudarte a descubrir los vínculos causales entre los eventos que llevan a esta tarea.

Un seguimiento de pila de algún código ejecutado de forma asíncrona sin información sobre cuándo se programó.

Gracias a una nueva función llamada "Etiquetado de pila asíncrona", es posible contar toda la historia vinculando ambas partes del código asíncrono.

La API de Async Stack Tagging presenta un nuevo método console llamado console.createTask(). La firma de la API es la siguiente:

interface Console {
  createTask(name: string): Task;
}

interface Task {
  run<T>(f: () => T): T;
}

La llamada console.createTask() muestra una instancia de Task que puedes usar más adelante para ejecutar el contenido f de la tarea.

// Task Creation
const task = console.createTask(name);

// Task Execution
task.run(f);

La tarea forma el vínculo entre el contexto en el que se creó y el contexto de la función asíncrona que se está ejecutando.

Si se aplica a la función makeScheduler anterior, el código se convierte en el siguiente:

function makeScheduler() {
  const tasks = [];

  return {
    schedule(f) {
      const task = console.createTask(f.name);
      tasks.push({ task, f });
    },

    work() {
      while (tasks.length) {
        const { task, f } = tasks.shift();
        task.run(f); // instead of f();
      }
    },
  };
}

Gracias a esto, las Herramientas para desarrolladores de Chrome ahora pueden mostrar un mejor seguimiento de pila.

Un seguimiento de pila de algún código ejecutado asíncrono con información sobre cuándo se programó.

Observa cómo businessLogic() ahora se incluye en el seguimiento de pila. No solo eso, sino que la tarea tiene un nombre familiar someTask en lugar del requestAnimationFrame genérico como antes.

Marcos de llamadas amigables

Los frameworks suelen generar código de todo tipo de lenguajes de plantillas cuando se compila un proyecto, como las plantillas de Angular o JSX que convierten el código con aspecto de HTML en JavaScript simple que, en última instancia, se ejecuta en el navegador. A veces, a este tipo de funciones generadas se les asignan nombres que no son muy amigables, ya sea nombres de una sola letra después de que se comprimen o algunos nombres oscuros o desconocidos, incluso cuando no lo son.

En el proyecto de ejemplo, un ejemplo de esto es AppComponent_Template_app_button_handleClick_1_listener, que se muestra en el seguimiento de pila.

Captura de pantalla del seguimiento de pila con un nombre de función generado automáticamente.

Para solucionar este problema, Chrome DevTools ahora admite cambiar el nombre de estas funciones a través de mapas de origen. Si un mapa de origen tiene una entrada de nombre para el inicio del alcance de una función, el marco de llamada debe mostrar ese nombre en el seguimiento de pila.

Como autor, no necesitas hacer nada para habilitar este nuevo comportamiento. Depende del framework implementar este cambio.

Con la mirada puesta en el futuro

Gracias a las incorporaciones que se describen en esta publicación, las Herramientas para desarrolladores de Chrome pueden ofrecerte una mejor experiencia de depuración. Hay más áreas que el equipo desea explorar. En particular, cómo mejorar la experiencia de generación de perfiles en DevTools.

El equipo de Chrome DevTools alienta a los autores de frameworks a adoptar estas nuevas funciones. El caso de éxito: Mejor depuración de Angular con DevTools ofrece orientación sobre cómo implementar esto.