Modernes Web-Debugging in den Chrome-Entwicklertools

Einführung

Autoren können heute viele Abstraktionen verwenden, um ihre Webanwendungen zu erstellen. Anstatt direkt mit den untergeordneten APIs der Webplattform verbunden zu sein, nutzen viele Autoren Frameworks, Build-Tools und Compiler, um ihre Anwendungen aus einer übergeordneten Perspektive zu schreiben.

Beispielsweise werden Komponenten, die auf dem Angular-Framework aufbauen, in TypeScript mit HTML-Vorlagen erstellt. Im Hintergrund kompilieren die Angular-Befehlszeile und das Webpack alles in JavaScript und in einem sogenannten Bundle, das dann an den Browser gesendet wird.

Beim Debuggen oder Erstellen von Profilen für Webanwendungen in Entwicklertools können Sie derzeit diese kompilierte Version Ihres Codes anstelle des tatsächlich geschriebenen Codes sehen und debuggen. Als Autor möchten Sie das jedoch nicht:

  • Sie möchten keine Fehler im komprimierten JavaScript-Code, sondern im ursprünglichen JavaScript-Code beheben.
  • Wenn Sie TypeScript verwenden, möchten Sie nicht JavaScript-Fehler beheben, sondern Ihren ursprünglichen TypeScript-Code debuggen.
  • Wenn Sie Vorlagen wie Angular, Lit oder JSX verwenden, sollten Sie das resultierende DOM nicht immer debuggen. Vielleicht möchten Sie die Fehler in den Komponenten selbst beheben.

Insgesamt möchten Sie wahrscheinlich Ihren eigenen Code debuggen, wie Sie ihn geschrieben haben.

Obwohl Quellkarten diese Lücke bereits in gewissem Umfang schließen, gibt es in diesem Bereich noch mehr, was die Chrome-Entwicklertools und die Plattform bieten.

Sehen wir uns das genauer an!

Erstellter und bereitgestellter Code im Vergleich

Wenn Sie derzeit im Bereich Quellen in der Dateistruktur den Inhalt des kompilierten – und oft minimierten – Bundles sehen, Dies sind die tatsächlichen Dateien, die der Browser herunterlädt und ausführt. In den Entwicklertools wird dies Bereitgestellter Code genannt.

Screenshot des Dateibaums in den Chrome-Entwicklertools mit dem bereitgestellten Code

Dies ist nicht sehr praktisch und oft schwer zu verstehen. Als Autor möchten Sie den von Ihnen geschriebenen Code sehen und debuggen, nicht den bereitgestellten Code.

Als Ausgleich können Sie nun festlegen, dass die Baumstruktur stattdessen den autorisierten Code anzeigt. Dadurch ähnelt die Baumstruktur eher den Quelldateien, die Sie in Ihrer IDE sehen. Diese Dateien sind jetzt vom bereitgestellten Code getrennt.

Screenshot des Dateibaums in den Chrome-Entwicklertools mit dem erstellten Code

Sie können diese Option in den Chrome-Entwicklertools unter Einstellungen > Experimente und aktivieren Sie die Option Quellen in Baumstrukturen für erstellte und bereitgestellte Strukturen gruppieren.

Screenshot der Einstellungen in den Entwicklertools.

„Nur mein Code“

Wenn Sie Abhängigkeiten verwenden oder auf einem Framework aufbauen, können die Drittanbieterdateien im Weg stehen. Meistens möchten Sie nur Ihren Code sehen und nicht den Code einer Bibliothek eines Drittanbieters im Ordner node_modules.

Als Ausgleich ist in den Entwicklertools standardmäßig eine zusätzliche Einstellung aktiviert: Bekannte Drittanbieter-Skripts automatisch zur Ignorieren-Liste hinzufügen. Sie finden sie in den DevTools > Einstellungen > Liste zu ignorierender Nutzer:

Screenshot der Einstellungen in den Entwicklertools.

Wenn diese Einstellung aktiviert ist, blendet Entwicklertools alle Dateien oder Ordner aus, die von einem Framework oder Build-Tool als zu ignorieren markiert wurden.

Ab Angular-Version 14.1.0 wurden die Inhalte der Ordner node_modules und webpack entsprechend gekennzeichnet. Daher werden diese Ordner, die darin enthaltenen Dateien und andere Artefakte von Drittanbietern an verschiedenen Stellen in den Entwicklertools nicht angezeigt.

Als Autor müssen Sie nichts unternehmen, um dieses neue Verhalten zu ermöglichen. Es liegt an den Rahmenbedingungen, diese Änderung umzusetzen.

Ignorierter Code in Stacktraces

Dateien, die auf der Ignorieren-Liste nicht mehr angezeigt werden, befinden sich in Stacktraces. Als Autor sehen Sie jetzt relevantere Stacktraces.

Screenshot eines Stacktrace in den Entwicklertools.

Wenn Sie alle Aufruf-Frames des Stacktrace ansehen möchten, können Sie jederzeit auf den Link Mehr Frames anzeigen klicken.

Dasselbe gilt für die Aufrufstacks, die Sie beim Fehlersuche und Durchlaufen Ihres Codes sehen. Wenn Frameworks oder Bundler die Entwicklertools über Drittanbieterskripts informieren, blendet Entwicklertools automatisch alle irrelevanten Aufrufframes aus und springt beim Debuggen von Schritten über Code, der ignoriert werden soll.

Screenshot des Quellen-Debuggers der Entwicklertools während der Fehlerbehebung.

Ignoriercode in der Dateistruktur

Um die Dateien und Ordner, die auf der Ignorieren-Liste aufgeführt sind, aus der Dateistruktur Authored Code im Steuerfeld Quellen auszublenden, aktivieren Sie unter Einstellungen die Option Code auf Ignorieren-Liste in der Quellstruktur ausblenden. Tests in den Entwicklertools

Screenshot der Einstellungen in den Entwicklertools.

Im Angular-Beispielprojekt sind die Ordner node_modules und webpack jetzt ausgeblendet.

Screenshot des Dateibaums in den Chrome-Entwicklertools mit dem erstellten Code, aber ohne „node_modules“.

Code, der im Schnellzugriff-Menü zu ignorieren ist

Ignorierter Code wird nicht nur in der Dateistruktur ausgeblendet, sondern auch über das Menü „Schnell öffnen“ (Strg + P (Linux/Windows) oder Befehlstaste + P (Mac))) ausgeblendet.

Screenshot der Entwicklertools mit dem Menü „Schnellzugriff“.

Weitere Verbesserungen an Stacktraces

Nachdem bereits die relevanten Stacktraces behandelt wurden, wurden in den Chrome-Entwicklertools weitere Verbesserungen eingeführt.

Verknüpfte Stacktraces

Wenn einige Vorgänge asynchron ausgeführt werden, erzählen die Stacktraces in den Entwicklertools derzeit nur einen Teil der Geschichte.

Hier sehen Sie als Beispiel einen sehr einfachen Planer in einer hypothetischen framework.js-Datei:

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

...und wie ein Entwickler dies in seinem eigenen Code in einer example.js-Datei verwenden könnte:

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

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

businessLogic();

Wenn Sie in der Methode someTask einen Haltepunkt hinzufügen oder den in der Konsole ausgegebenen Trace untersuchen, wird der Aufruf businessLogic() nicht erwähnt, der die Ursache für diesen Vorgang war.

Stattdessen sehen Sie nur die Framework-Planungslogik, die zur Ausführung der Aufgaben geführt hat, und keine Navigationspfade im Stacktrace, um die kausalen Zusammenhänge zwischen Ereignissen zu ermitteln, die zu dieser Aufgabe führen.

Ein Stacktrace mit einem asynchron ausgeführten Code ohne Informationen darüber, wann er geplant wurde.

Dank der neuen Funktion „Async Stack Tagging“ ist es möglich, die ganze Geschichte zu erzählen, indem beide Teile des asynchronen Codes miteinander verknüpft werden.

Mit der Async Stack Tagging API wurde die neue console-Methode console.createTask() eingeführt. Die API-Signatur sieht so aus:

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

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

Der console.createTask()-Aufruf gibt eine Task-Instanz zurück, die Sie später zum Ausführen des Inhalts f der Aufgabe verwenden können.

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

// Task Execution
task.run(f);

Die Aufgabe stellt die Verknüpfung zwischen dem Kontext, in dem sie erstellt wurde, und dem Kontext der ausgeführten asynchronen Funktion dar.

Wird der Code auf die oben angegebene Funktion makeScheduler angewendet, sieht er so aus:

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

Dadurch können die Chrome-Entwicklertools jetzt einen besseren Stacktrace anzeigen.

Ein Stacktrace eines asynchron ausgeführten Codes mit Informationen darüber, wann er geplant wurde.

Sie sehen, dass businessLogic() jetzt im Stacktrace enthalten ist. Nicht nur das: Die Aufgabe hat auch den bekannten Namen someTask anstelle des generischen requestAnimationFrame wie zuvor.

Freundliche Call-Frames

Frameworks generieren beim Erstellen eines Projekts oft Code aus allen Arten von Vorlagensprachen, z. B. Angular- oder JSX-Vorlagen, die HTML-Code in einfachen JavaScript-Code umwandeln, der schließlich im Browser ausgeführt wird. Manchmal erhalten diese Arten von generierten Funktionen Namen, die nicht sehr ansprechend sind – entweder Namen mit einzelnen Buchstaben, nachdem sie reduziert wurden, oder unklare oder unbekannte Namen, selbst wenn dies nicht der Fall ist.

Im Beispielprojekt ist ein Beispiel dafür AppComponent_Template_app_button_handleClick_1_listener. Sie sehen sie im Stacktrace.

Screenshot des Stacktrace mit einem automatisch generierten Funktionsnamen.

Aus diesem Grund unterstützt die Chrome-Entwicklertools das Umbenennen dieser Funktionen mithilfe von Source Maps. Wenn eine Quellzuordnung einen Namenseintrag für den Anfang eines Funktionsbereichs hat, sollte der Aufrufframe diesen Namen im Stacktrace anzeigen.

Als Autor müssen Sie nichts unternehmen, um dieses neue Verhalten zu ermöglichen. Es liegt an den Rahmenbedingungen, diese Änderung umzusetzen.

Zukunftspläne

Dank der Ergänzungen, die in diesem Beitrag beschrieben werden, können die Chrome-Entwicklertools eine bessere Fehlerbehebung ermöglichen. Es gibt weitere Bereiche, die das Team gerne untersuchen würde. Insbesondere, wie die Profilerstellung in den Entwicklertools verbessert werden kann.

Das Team der Chrome-Entwicklertools ermutigt Framework-Autoren, diese neuen Funktionen zu nutzen. In der Fallstudie: Better Angular Debugging with DevTools erfahren Sie, wie Sie dies umsetzen können.