Débogage Web moderne dans les outils pour les développeurs Chrome

Introduction

Aujourd'hui, les auteurs peuvent utiliser de nombreuses abstractions pour créer leurs applications Web. Au lieu d'interagir directement avec les API de niveau inférieur fournies par la plate-forme Web, de nombreux auteurs exploitent des frameworks, des outils de développement et des compilateurs pour écrire leurs applications dans une perspective plus générale.

Par exemple, les composants basés sur le framework Angular sont créés en TypeScript avec des modèles HTML. Sous le capot, la CLI Angular et le webpack compilent tout en JavaScript et dans un bundle, qui est ensuite envoyé au navigateur.

Lorsque vous déboguez ou profilez des applications Web dans les outils de développement, vous pouvez actuellement voir et déboguer cette version compilée de votre code au lieu de celui que vous avez réellement écrit. Cependant, en tant qu'auteur, vous ne voulez pas:

  • Vous ne voulez pas déboguer votre code JavaScript réduit, mais votre code JavaScript d'origine.
  • Lorsque vous utilisez TypeScript, vous ne souhaitez pas déboguer JavaScript, mais votre code TypeScript d'origine.
  • Lorsque vous utilisez les modèles, comme avec Angular, Lit ou JSX, vous ne voulez pas toujours déboguer le DOM obtenu. Vous voudrez peut-être déboguer les composants eux-mêmes.

Dans l'ensemble, vous souhaiterez probablement déboguer votre propre code au fur et à mesure que vous l'avez écrit.

Si les cartes sources permettent déjà, dans une certaine mesure, de combler ces lacunes, les outils pour les développeurs Chrome et l'écosystème peuvent faire bien plus dans ce domaine.

Penchons-nous là-dessus.

Code créé et code déployé

Actuellement, lorsque vous parcourez l'arborescence de fichiers dans le panneau Sources, vous pouvez voir le contenu du bundle compilé, et souvent réduit. Il s'agit des fichiers que le navigateur télécharge et exécute. Les outils de développement l'appellent le code déployé.

Capture d'écran de l'arborescence de fichiers dans les outils pour les développeurs Chrome montrant le code déployé.

Ce n'est pas très pratique et souvent difficile à comprendre. En tant qu'auteur, vous souhaitez voir et déboguer le code que vous avez écrit, et non le code déployé.

Pour vous rattraper, vous pouvez désormais faire en sorte que l'arborescence affiche le code créé à la place. L'arborescence ressemble ainsi davantage aux fichiers sources que vous voyez dans votre IDE, et ces fichiers sont désormais séparés du code déployé.

Capture d'écran de l'arborescence de fichiers dans les outils pour les développeurs Chrome montrant le code créé.

Pour activer cette option dans les outils pour les développeurs Chrome, accédez à Paramètres > Tests et cochez Grouper les sources dans les arbres créés et déployés.

Capture d'écran des paramètres des outils de développement

"Seulement mon code"

Lorsque vous utilisez des dépendances ou créez un framework sur un framework, les fichiers tiers peuvent vous gêner. La plupart du temps, vous ne souhaitez voir que votre code, et non celui d'une bibliothèque tierce cachée dans le dossier node_modules.

En compensation, les outils de développement disposent d'un paramètre supplémentaire activé par défaut: Ajouter automatiquement les scripts tiers connus à la liste des éléments à ignorer. Vous pouvez y accéder dans DevTools > Paramètres > Liste des éléments à ignorer.

Capture d'écran des paramètres des outils de développement

Lorsque ce paramètre est activé, les outils de développement masquent les fichiers ou dossiers qu'un framework ou un outil de compilation a marqués comme à ignorer.

Depuis Angular v14.1.0, le contenu de ses dossiers node_modules et webpack est marqué comme tel. Par conséquent, ces dossiers, les fichiers qu'ils contiennent et d'autres artefacts tiers de ce type ne s'affichent pas à différents endroits dans les outils de développement.

En tant qu'auteur, vous n'avez rien à faire pour activer ce nouveau comportement. Il appartient au cadre de mettre en œuvre ce changement.

Ignorer le code figurant dans les traces de la pile

Ces fichiers ne s'affichent plus dans les traces de la pile. En tant qu'auteur, vous pouvez désormais voir des traces de pile plus pertinentes.

Capture d'écran d'une trace de la pile dans les outils de développement

Si vous souhaitez afficher tous les cadres d'appel de la trace de la pile, vous pouvez toujours cliquer sur le lien Afficher plus de cadres.

Il en va de même pour les piles d'appels que vous voyez lorsque vous déboguez et parcourez votre code. Lorsque les frameworks ou les bundles des outils de développement informent les outils de développement de scripts tiers, ils masquent automatiquement tous les frames d'appel non pertinents et sautent par-dessus tout code figurant sur la liste des éléments à ignorer lors du débogage par étapes.

Capture d'écran du débogueur de sources des outils de développement lors du débogage.

Code à ignorer dans l'arborescence de fichiers

Pour masquer les fichiers et les dossiers figurant sur la liste des éléments à ignorer dans l'arborescence de fichiers Code créé dans le panneau Sources, cochez la case Masquer le code figurant sur la liste des éléments à ignorer dans l'arborescence des sources dans Paramètres > Tests dans les outils de développement.

Capture d'écran des paramètres des outils de développement

Dans l'exemple de projet Angular, les dossiers node_modules et webpack sont désormais masqués.

Capture d'écran de l'arborescence de fichiers dans les outils pour les développeurs Chrome montrant le code créé, mais pas les node_modules.

Code à ignorer dans le menu "Quick Open" (Ouverture rapide)

Le code de la liste des éléments ignorés n'est pas seulement masqué dans l'arborescence de fichiers, mais il est également masqué dans le menu "Ouverture rapide" (Ctrl+P (Linux/Windows) ou Commande+P (Mac)).

Capture d'écran des outils de développement avec le menu "Quick Open".

Autres améliorations apportées aux traces de la pile

Les outils pour les développeurs Chrome ont déjà abordé les traces de la pile pertinentes et apportent encore plus d'améliorations à celles-ci.

Traces de pile associées

Lorsque certaines opérations sont planifiées de manière asynchrone, les traces de la pile dans les outils de développement ne vous racontent actuellement qu'une partie de l'histoire.

Par exemple, voici un planificateur très simple dans un fichier framework.js fictif:

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();

... et comment un développeur peut l'utiliser dans son propre code, dans un fichier example.js:

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

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

businessLogic();

Lorsque vous ajoutez un point d'arrêt dans la méthode someTask ou que vous inspectez la trace imprimée dans la console, vous ne voyez aucune mention de l'appel businessLogic() qui était la "cause racine" de cette opération.

À la place, vous ne voyez que la logique de planification du framework qui a conduit à l'exécution de la tâche, et aucun fil d'Ariane dans la trace de la pile pour vous aider à identifier les liens de causalité entre les événements menant à cette tâche.

Trace de la pile d'un code exécuté asynchrone sans aucune information sur la date de planification.

Grâce à une nouvelle fonctionnalité appelée "Async Stack Tagging" (Balisage de pile asynchrone), il est possible de raconter toute l'histoire en liant les deux parties du code asynchrone.

L'API Async Stack Tagging intègre une nouvelle méthode console nommée console.createTask(). La signature de l'API est la suivante:

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

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

L'appel console.createTask() renvoie une instance Task que vous pouvez utiliser ultérieurement pour exécuter le contenu f de la tâche.

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

// Task Execution
task.run(f);

La tâche constitue le lien entre le contexte dans lequel elle a été créée et le contexte de la fonction asynchrone en cours d'exécution.

Appliqué à la fonction makeScheduler ci-dessus, le code devient le suivant:

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();
      }
    },
  };
}

Grâce à cela, les outils pour les développeurs Chrome peuvent désormais afficher une meilleure trace de la pile.

Trace de la pile d&#39;un code exécuté asynchrone avec des informations sur sa date de planification.

Notez que businessLogic() est désormais inclus dans la trace de la pile. De plus, la tâche porte un nom familier someTask au lieu du nom générique requestAnimationFrame comme précédemment.

Cadres d'appel conviviaux

Les frameworks génèrent souvent du code à partir de toutes sortes de langages de création de modèles lors de la création d'un projet, tels que des modèles Angular ou JSX qui transforment du code HTML en JavaScript simple qui s'exécute à terme dans le navigateur. Parfois, ces types de fonctions générées reçoivent des noms peu conviviaux : soit des noms à une seule lettre après minimisation, soit des noms obscurs ou inconnus, même s'ils ne le sont pas.

Dans l'exemple de projet, AppComponent_Template_app_button_handleClick_1_listener est un exemple. Vous pouvez le voir dans la trace de la pile.

Capture d&#39;écran de la trace de la pile avec un nom de fonction généré automatiquement.

Pour résoudre ce problème, les outils pour les développeurs Chrome permettent désormais de renommer ces fonctions via des mappages sources. Si un mappage source comporte une entrée de nom pour le début d'un champ d'application de fonction, le cadre d'appel doit afficher ce nom dans la trace de la pile.

En tant qu'auteur, vous n'avez rien à faire pour activer ce nouveau comportement. Il appartient au cadre de mettre en œuvre ce changement.

Perspectives d'avenir

Grâce aux ajouts décrits dans cet article, les outils pour les développeurs Chrome peuvent vous offrir une meilleure expérience de débogage. L'équipe aimerait explorer d'autres domaines. en particulier la manière d'améliorer l'expérience de profilage dans les outils de développement.

L'équipe des outils pour les développeurs Chrome encourage les auteurs de frameworks à adopter ces nouvelles fonctionnalités. L'article Étude de cas: Améliorer le débogage Angular avec les outils de développement fournit des conseils sur la mise en œuvre de cette fonctionnalité.