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 bas niveau fournies par la plate-forme Web, de nombreux auteurs utilisent des frameworks, des outils de compilation et des compilateurs pour écrire leurs applications à un niveau plus élevé.

Par exemple, les composants créés sur le framework Angular sont créés en TypeScript avec des modèles HTML. Sous le capot, la CLI Angular et 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 souhaitez pas déboguer le 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 des modèles, comme avec Angular, Lit ou JSX, vous n'avez pas toujours envie de déboguer le DOM qui en résulte. Vous pouvez déboguer les composants eux-mêmes.

Dans l'ensemble, vous souhaitez probablement déboguer votre propre code tel que vous l'avez écrit.

Bien que les maquettes sources comblent déjà cette lacune dans une certaine mesure, les outils pour les développeurs Chrome et l'écosystème peuvent faire plus dans ce domaine.

Penchons-nous là-dessus.

Code créé par l'auteur et code déployé

Actuellement, lorsque vous parcourez l'arborescence des fichiers dans le panneau Sources, vous pouvez voir le contenu du bundle compilé (et souvent minifié). Il s'agit des fichiers réels que le navigateur télécharge et exécute. DevTools l'appelle Code déployé.

Capture d'écran de l'arborescence des fichiers dans Chrome DevTools 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 compenser cela, vous pouvez désormais afficher le code créé à la place. L'arborescence ressemble ainsi davantage aux fichiers sources que vous pouvez voir dans votre IDE. Ces fichiers sont désormais séparés du code déployé.

Capture d'écran de l'arborescence des fichiers dans Chrome DevTools montrant le code créé par l'auteur.

Pour activer cette option dans Chrome DevTools, accédez à Settings (Paramètres) > Experiments (Tests) et cochez Group sources into Authored and Deployed trees (Regrouper les sources dans des arborescences "Authored" (Créé) et "Deployed" (Déployé)).

Capture d'écran des paramètres de DevTools.

"Just my code" (Mon code uniquement)

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

Pour compenser cela, un paramètre supplémentaire est activé par défaut dans les outils de développement: Ajouter automatiquement des scripts tiers connus à la liste d'éléments à ignorer. Vous pouvez y accéder dans DevTools > Settings > Ignore List (DevTools > Paramètres > Liste d'ignorer).

Capture d'écran des paramètres de DevTools.

Lorsque ce paramètre est activé, DevTools masque tous les fichiers ou dossiers qu'un framework ou un outil de compilation a marqués comme à ignorer.

Depuis la version Angular v14.1.0, le contenu des dossiers node_modules et webpack a été 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 DevTools.

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

Code de la liste des éléments à ignorer dans les traces de pile

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

Capture d'écran d'une trace de pile dans DevTools.

Si vous souhaitez afficher tous les cadres d'appels 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 exécutez votre code. Lorsque des frameworks ou des outils de compilation informent DevTools de scripts tiers, DevTools masque automatiquement tous les cadres d'appels non pertinents et ignore tout code figurant sur la liste d'ignorement lors du débogage par étapes.

Capture d'écran du débogueur des sources DevTools lors du débogage.

Code figurant sur la liste d'éléments à ignorer dans l'arborescence des fichiers

Pour masquer les fichiers et les dossiers de la liste d'ignorement dans l'arborescence de fichiers Code créé du panneau Sources, cochez Masquer le code de la liste d'ignorement dans l'arborescence des sources dans Settings > Experiments (Paramètres > Tests) dans DevTools.

Capture d'écran des paramètres de DevTools.

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 de DevTools avec le menu "Ouvrir rapidement".

Nouvelles améliorations apportées aux traces de pile

Les outils pour les développeurs Chrome ayant déjà couvert les traces de pile pertinentes, ils apportent encore plus d'améliorations à ce type de traces.

Traces de pile associées

Lorsque certaines opérations sont planifiées pour se produire de manière asynchrone, les traces de la pile dans DevTools ne donnent actuellement qu'un aperçu 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 lorsque vous inspectez la trace imprimée dans la console, aucune mention de l'appel businessLogic() qui était la "cause racine" de cette opération ne s'affiche.

À 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é de manière asynchrone, sans aucune information sur le moment où il a été planifié.

Grâce à une nouvelle fonctionnalité appelée "Taggage de pile asynchrone", il est possible de raconter toute l'histoire en associant les deux parties du code asynchrone.

L'API Async Stack Tagging introduit une nouvelle méthode console appelé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 pourrez 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é de manière asynchrone, avec des informations sur le moment où il a été planifié.

Notez que businessLogic() est maintenant 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 auparavant.

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 ressemblant à du code HTML en code JavaScript pur qui s'exécute finalement 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 de ce type, que vous pouvez 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 une carte source comporte une entrée de nom pour le début d'un champ d'application de fonction, le bloc 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. C'est au framework d'implémenter ce changement.

Perspectives

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 souhaite explorer d'autres domaines. En particulier, comment améliorer l'expérience de profilage dans DevTools.

L'équipe des outils pour les développeurs Chrome encourage les auteurs de frameworks à adopter ces nouvelles fonctionnalités. L'étude de cas: Mieux déboguer Angular avec DevTools vous explique comment procéder.