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 API de nivel inferior que proporciona la plataforma web, muchos autores aprovechan los frameworks, las herramientas de compilación y los compiladores para escribir sus aplicaciones desde una perspectiva de mayor nivel.

Por ejemplo, los componentes compilados sobre el framework de Angular se crean en TypeScript con plantillas HTML. De forma interna, la CLI y el paquete web de Angular compilan todo en JavaScript y en un llamado paquete, que luego se envía al navegador.

Cuando depuras o creas perfiles de aplicaciones web en Herramientas para desarrolladores, puedes ver y depurar esta versión compilada de tu código en lugar del código que escribiste. Sin embargo, como autor, esto no es lo que deseas:

  • No deseas depurar código de JavaScript reducido, sino tu código original de JavaScript.
  • Si usas TypeScript, no quieres depurar JavaScript; debes depurar tu código original de TypeScript.
  • Cuando usas plantillas, como Angular, Lit o JSX, no siempre querrás depurar el DOM resultante. Es posible que desees depurar los componentes por sí mismos.

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

Si bien los mapas de fuentes ya cierran esta brecha hasta cierto punto, las Herramientas para desarrolladores de Chrome y el ecosistema pueden hacer mucho 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 Fuentes, puedes ver el contenido del paquete compilado y, a menudo, reducido. Son los archivos reales que el navegador descarga y ejecuta. Herramientas para desarrolladores 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.

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

Para compensarlo, puedes hacer que el árbol muestre authored Code en su lugar. De esta manera, el árbol se parece más a los archivos de origen 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.

Para habilitar esta opción en las Herramientas para desarrolladores de Chrome, ve a Configuración > Experimentos y marca la opción Agrupar fuentes en árboles implementados e creados.

Captura de pantalla de la configuración de Herramientas para desarrolladores.

“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 solo tu código y no el de alguna biblioteca de terceros escondida en la carpeta node_modules.

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

Captura de pantalla de la configuración de Herramientas para desarrolladores.

Cuando se habilita este parámetro de configuración, Herramientas para desarrolladores oculta cualquier archivo o carpeta que un framework o una herramienta de compilación haya marcado como ignorar.

A partir de Angular v14.1.0, 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 similares no aparecen en varios lugares de Herramientas para desarrolladores.

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

Código que aparece en la lista de ignorados en seguimientos de pila

Un lugar en el que estos archivos de la lista de elementos ignorados ya no aparecen 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 Herramientas para desarrolladores.

Si deseas ver todos los marcos de llamada del seguimiento de pila, puedes hacer clic en el vínculo Show more frames en cualquier momento.

Lo mismo se aplica a las pilas de llamadas que ves durante la depuración y el recorrido por tu código. Cuando los frameworks o los agrupadores informan a las Herramientas para desarrolladores sobre las secuencias de comandos de terceros, las Herramientas para desarrolladores ocultan automáticamente todos los marcos de llamada irrelevantes y salta cualquier código que se haya ignorado durante la depuración de pasos.

Captura de pantalla de Sources Debugger de Herramientas para desarrolladores durante la depuración.

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

Para ocultar los archivos y las carpetas en la lista de elementos ignorados del árbol de archivos Authored Code en el panel Sources, marca Hide-list-list code in sources view tree view en Settings > Experiments en Herramientas para desarrolladores.

Captura de pantalla de la configuración de Herramientas para desarrolladores.

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

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

Código en la lista de elementos ignorados en el menú "Quick Open"

El código que se omite en la lista no solo se oculta del árbol de archivos, sino que también está oculto en el menú "Quick Open" (Control + P (Linux y Windows) o Comando + P (Mac).

Captura de pantalla de Herramientas para desarrolladores con el menú “Apertura rápida”.

Se implementaron más mejoras en los seguimientos de pila

Como ya se trataron los seguimientos de pila relevantes, las Herramientas para desarrolladores de Chrome presentan aún más mejoras para los seguimientos de pila.

Seguimientos de pila vinculados

Cuando algunas operaciones están programadas para ejecutarse de forma asíncrona, los seguimientos de pila en Herramientas para desarrolladores actualmente solo cuentan una parte de la historia.

Por ejemplo, aquí hay 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 era la "causa raíz" de esta operación.

En cambio, solo ves la lógica de programación del framework que condujo a la ejecución de la tarea y no hay rutas de navegación en el seguimiento de pila que te ayuden a descubrir los vínculos causales entre los eventos que conducen a esta tarea.

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

Gracias a la nueva función de etiquetado de pila asíncrona, es posible contar la historia completa si vinculas ambas partes del código asíncrono.

La API de etiquetado de pila asíncrona 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 f del contenido 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 ejecuta.

Cuando 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.

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. Además de eso, la tarea tiene un nombre conocido someTask en lugar del requestAnimationFrame genérico como antes.

Marcos de llamada amigables

Los frameworks suelen generar código a partir de todo tipo de lenguajes de plantillas cuando se compila un proyecto, como las plantillas de Angular o JSX que convierten el código HTML en JavaScript simple que, finalmente, se ejecutará en el navegador. A veces, este tipo de funciones generadas tienen nombres que no son muy amigables, ya sea nombres con una sola letra después de reducirse o algunos nombres desconocidos o desconocidos, incluso cuando no lo son.

En el proyecto de muestra, un ejemplo de esto es AppComponent_Template_app_button_handleClick_1_listener, que se ve 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, las Herramientas para desarrolladores de Chrome ahora permiten cambiar el nombre de estas funciones por medio 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 tienes que 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, la forma de mejorar la experiencia de generación de perfiles en Herramientas para desarrolladores.

El equipo de Herramientas para desarrolladores de Chrome alienta a los autores de marcos de trabajo a adoptar estas nuevas capacidades. El Caso de éxito: Better Angular Debugging with Herramientas para desarrolladores ofrece orientación para implementar esta función.