Chrome DevTools ist im Browser eingebaut und funktioniert auf jeder Website, auch bei veröffentlichten Apps. Es zeigt dir das DOM, die Requests, was im Browser gespeichert ist, wie viel die Seite verbraucht und was im Speicher bleibt. Angular DevTools ist eine eigene Erweiterung, die einen Tab „Angular“ mit Komponentenbaum, Profiler, Injectoren und Routen ergänzt.
Die Schritte unten verwenden die exakten Button-Namen aus Chrome DevTools, entnommen aus dessen Quellcode. Jeder Abschnitt hat eine Übung, die du direkt auf dieser Seite machen kannst.
- Auf einer veröffentlichten Website (Production-Build) sind Klassennamen minifiziert,
window.ngexistiert nicht, und Angular DevTools startet nicht. Dafür brauchst du deine eigene App, gestartet mitng serve. - Elements, Network, Application, Performance Monitor und Heap Snapshots funktionieren überall. Suche nach Tags und nativen Typen, nicht nach deinen Klassennamen.
- Ein Leak zeigt sich als Zahl, die mit jeder Wiederholung wächst und nie sinkt: JS event listeners im Performance Monitor, ein positives
# Deltain Comparison. - DevTools selbst kann Objekte am Leben halten: was du in Elements ausgewählt oder in der Console ausgegeben hast. Leere die Console vor dem letzten Snapshot.
- Klassennamen sind minifiziert. Ein Heap Snapshot zeigt nicht
LeakyWidget, sonderne,Geoderdc. HTML-Tags (<app-leaky-widget>) und native Browser-Typen (DOMTimer,EventListener) bleiben aber lesbar. - Die
ng.*-Hilfsfunktionen in der Console gibt es nur in der Entwicklung. Auf der veröffentlichten Website istngundefined. - Angular DevTools funktioniert nicht mit Production-Builds. Es zeigt „We detected an application built with production configuration. Angular DevTools only supports development builds.“
- Die HTTP-Beispiele dieser Website nutzen ein im Browser simuliertes Backend. Ihre Requests erscheinen nie in Network. Das Labor unten schickt einen echten Request, damit du etwas verfolgen kannst.
DevTools öffnen und jedes Panel finden
- DevTools öffnest du mit F12 oder Ctrl+Shift+I (Windows, Linux) bzw. Cmd+Option+I (Mac). Oder Rechtsklick auf die Seite → Inspect (Untersuchen).
- Die Panels sind Tabs oben: Elements, Console, Sources, Network, Performance, Memory, Application. Was nicht passt, liegt unter ».
- Der schnellste Weg zu allem ist das Befehlsmenü, mit Ctrl+Shift+P bzw. Cmd+Shift+P. Tippe „memory“ und wähle Show Memory, oder „performance monitor“ und wähle Show Performance monitor.
- Esc öffnet und schließt die untere Drawer-Leiste mit der Console. So siehst du die Console neben jedem anderen Panel.
Auf dieser Seite üben
Lass DevTools neben der Seite offen. Jede Karte sagt, was du hier drückst und was du dort suchst.
Elements
Klicke auf das Inspect-Symbol in der DevTools-Ecke (oder Ctrl+Shift+C / Cmd+Shift+C) und dann auf den grauen Text neben dem Button. Drücke danach ein paarmal +1: In Elements blinkt das Attribut data-clicks bei jeder Änderung.
Console
Drücke den Button und tippe dann atlas in das Feld Filter der Console. Klicke auf den Pfeil vor dem Objekt, um es aufzuklappen.
Network
Wähle in Network den Filter Fetch/XHR und drücke den Button. Eine Zeile robots.txt?atlas-lab=1 erscheint. Klicke sie an und sieh dir Headers, Response und Timing an.
Stell das Throttling auf Slow 4G und sende erneut: Die Zeit steigt, und Timing zeigt, wohin sie geht.
Application
Speichere einen Text und öffne dann Application → Storage → Local storage → die Adresse der Website. Doppelklicke auf den Wert des Schlüssels atlas-devtools-lab, ändere ihn und drücke Erneut lesen.
Was jetzt in localStorage steht: null
Dort liegt auch der Schlüssel atlas-progress: dein Fortschritt durch die Lektionen, nur in deinem Browser gespeichert.
Elements: was Angular gerendert hat
Elements zeigt das DOM, wie es jetzt ist, nicht das HTML, das der Server geschickt hat. Ein paar Dinge, die Angular darin hinterlässt:
- Das Wurzelelement (
<app-root>) trägt ein Attributng-versionmit der exakten Angular-Version. Auf dieser Website:22.2.2. - Die Attribute
_nghost-ng-c…und_ngcontent-ng-c…stammen aus der Style-Kapselung (Modus Emulated). Im Bereich Styles rechts sehen Selektoren aus wie.btn[_ngcontent-ng-c…]. - Die leeren Kommentare
<!---->sind Angulars Anker für@if,@forund@defer: die Stelle, an der es Inhalt einfügt oder entfernt. - Das ausgewählte Element ist in der Console als
$0verfügbar. Attribute und Text, die sich ändern, blinken in Elements kurz auf: So siehst du, was Angular aktualisiert.
Console: die ng-Hilfsfunktionen (nur Entwicklung)
In deiner eigenen App, gestartet mit ng serve, legt Angular ein globales Objekt ng auf die Seite. Wähle ein Element in Elements und dann in der Console:
// Elements: Element auswählen; in der Console ist es $0 (nur Entwicklung)
ng.getComponent($0) // die Komponente, deren Host $0 ist
ng.getOwningComponent($0) // die Komponente, in deren Template $0 steht
ng.getDirectives($0) // die Direktiven auf $0
ng.getInjector($0) // der Element-Injector: .get(EinService)
ng.getListeners($0) // die Listener, die Angular auf $0 gesetzt hat
ng.getRootComponents() // die Root-Komponenten
const c = ng.getComponent($0);
c.count.set(42); // ein Signal wird direkt geschrieben; Angular rendert selbst
c.title = 'Test'; // eine einfache Property braucht applyChanges
ng.applyChanges(c);In einem Production-Build gibt es diese Funktionen nicht. Das ist kein Fehler: Sie werden absichtlich entfernt, damit sie die App nicht belasten.
Network: was die App anfragt
Network zeichnet nur auf, solange es geöffnet ist. Öffnest du es nach dem Laden der Seite, lade die Seite neu.
- Die Filter oben (Fetch/XHR, JS, CSS, Img …) und das Textfeld lassen nur die Requests übrig, die dich interessieren.
- Klicke auf einen Request: Headers (URL, Status, Header), Payload (was du geschickt hast), Preview und Response (was zurückkam), Initiator (welcher Code ihn gestartet hat), Timing (wohin die Zeit ging).
- Keep log (in älteren Versionen: Preserve log) behält die Liste bei Navigation und Neuladen. Disable cache umgeht den Cache, solange DevTools offen ist.
- Das Menü Throttling simuliert ein langsameres Netz: Fast 4G, Slow 4G, 3G oder Offline. So siehst du Skeletons, Ladezustände und was ohne Netz passiert.
Application: was die App im Browser speichert
- Storage → Local storage / Session storage → die Adresse der Website: Schlüssel und Werte, die du bearbeiten oder löschen kannst.
- Cookies, IndexedDB und Cache storage liegen am selben Ort. Im Cache storage hält ein Service Worker die Dateien für offline.
- Der Bereich Service workers zeigt den aktiven Worker. Update on reload erzwingt die neue Version bei jedem Neuladen, Bypass for network umgeht ihn. Beides ist praktisch, während du daran arbeitest.
- Storage → Clear site data löscht alles, was die Website gespeichert hat. Der sicherste Weg, einen „ersten Besuch“ zu testen.
Performance Monitor: der schnelle Check
Vor jedem Snapshot: Schau dir Live-Zahlen an.
- Befehlsmenü (Ctrl/Cmd+Shift+P) → „performance monitor“ → Show Performance monitor. Er öffnet sich unten in der Drawer-Leiste.
- Beobachte JS heap size, DOM nodes und JS event listeners. Ein Klick auf einen Namen blendet seinen Graphen ein oder aus.
- Drücke im Labor unten, mit abgewählten Fixes, 10-mal öffnen und schließen. JS event listeners steigt um 10 und bleibt dort. Drücke Zombies aufräumen: Der Wert sinkt wieder. Mit allen Fixes aktiviert steigt er gar nicht.
Memory: ein Leak, Schritt für Schritt gefunden
Das Labor aus der Lektion über Memory Leaks, hier, damit du etwas zu messen hast. Jedes Widget, das mit abgewählten Fixes geschlossen wird, hinterlässt einen Timer, einen Listener und eine Subscription, die die Komponente im Speicher halten.
Kein Widget auf der Seite.
- zerstört, noch am Leben
- 0
- gehaltener Speicher
- 0.00 MB
- Zombie-Arbeit
- 0/s
- Subscriptions
- 0
- Timer
- 0
- Listener
- 0
- erstellte Widgets
- 0
Heap Snapshot und Comparison
- Öffne das Panel Memory. Wähle unter Select profiling type den Eintrag Heap snapshot.
- Klicke auf das Papierkorb-Symbol, Collect garbage, dann auf Take snapshot. Links erscheint Snapshot 1.
- Drücke auf der Seite, mit abgewählten Fixes, 10-mal öffnen und schließen und warte, bis es fertig ist.
- Wieder Collect garbage und Take snapshot: Snapshot 2 erscheint.
- Stelle bei ausgewähltem Snapshot 2 das erste Menü in der oberen Leiste von Summary auf Comparison. Das Menü daneben zeigt, womit du vergleichst: Snapshot 1.
- Tippe einen Namen aus der Tabelle unten in Filter by class und sieh dir die Spalten # New und # Delta an.
- Drücke Zombies aufräumen, nimm Snapshot 3 auf und vergleiche ihn mit Snapshot 2: Dieselben Zeilen stehen jetzt unter # Deleted.
| Filter by class | # Delta | Was es bedeutet |
|---|---|---|
app-leaky-widget | +10 | Die Host-Elemente der 10 Widgets, aus der Seite entfernt, aber noch im Speicher gehalten. Auch auf der veröffentlichten Website sichtbar. |
DOMTimer | +10 | Die 10 setInterval, die noch laufen. Ein nativer Browser-Typ, daher bleibt der Name auch in Produktion lesbar. |
EventListener | +10 | Die Listener auf document, die nie entfernt wurden. |
LeakyWidget | +10 | Die Komponentenklasse. Erscheint nur in der Entwicklung (meist als _LeakyWidget). In Produktion ist der Name minifiziert, dort suchst du nach dem Tag. |
Wer das Objekt hält: Retainers
Klappe eine Zeile auf und klicke auf eine Instanz. Der Bereich Retainers unten zeigt, wer sie am Leben hält: Die oberen Zeilen sind die direkten Referenzen, und beim Aufklappen gehst du die Kette hinauf zu etwas Langlebigem (Window, ein Listener, ein Timer). Die Spalte Distance sagt, wie viele Schritte es bis window sind. Das Leak ist das Glied, das dein Code beim Destroy hätte trennen sollen.
Direkter: Detached elements
- Wähle in Memory → Select profiling type den Eintrag Detached elements.
- Wiederhole die Aktion auf der Seite und drücke dann Get detached elements.
- Die Liste zeigt Elemente, die aus der Seite entfernt, aber noch von JavaScript referenziert werden. Hier: ein
<app-leaky-widget>pro geschlossenem Widget.
console.log ausgegeben hast, oder ein Ergebnis in der Console bleiben im Speicher, solange DevTools sie braucht. Zeigt ein Snapshot nach dem Aufräumen immer noch Objekte, leere die Console (das Symbol mit dem durchgestrichenen Kreis, oder Ctrl+L, auf dem Mac Cmd+K), wähle ein anderes Element und wiederhole. In Summary zeigt der Filter Objects retained by DevTools Console genau diese Objekte.Performance: was über die Zeit passiert
- Record zeichnet auf, während du etwas auf der Seite tust. Record and reload lädt die Seite neu und zeichnet den Start auf.
- Aktiviere Show memory timeline, um JS Heap, Dokumente, Knoten und Listener auf derselben Achse zu sehen. Ein Leak sieht aus wie eine Treppe, die steigt und nie sinkt.
- In der Entwicklung kann Angular eine eigene Spur Angular mit Komponenten, Change Detection und Hooks ergänzen. Du schaltest sie mit
ng.enableProfiling()in der Console ein, vor Record.
// in der Console, in deiner mit ng serve gestarteten App:
ng.enableProfiling();
// oder in main.ts, um auch den Start zu erfassen:
import { enableProfiling } from '@angular/core';
enableProfiling();
bootstrapApplication(App, appConfig);Angular DevTools
Die Erweiterung sieht die App so, wie Angular sie sieht: Komponenten, Inputs, Signals, Injectoren, Routen.
- Installiere Angular DevTools aus dem Chrome Web Store (es gibt auch eine Firefox-Version).
- Starte deine App mit
ng serve, öffne DevTools und suche den Tab Angular, eventuell unter ». Auf der Seite „Neuer Tab“ des Browsers laufen keine Erweiterungen. - Bei einem Production-Build, auch auf dieser Website, siehst du nur die Meldung „We detected an application built with production configuration“. Das ist normal.
| Tab | Was du siehst |
|---|---|
| Components | Der Baum der Komponenten und Direktiven, einschließlich @defer-Blöcken. Klicke auf eine Komponente: Inputs, Outputs und Properties rechts. Rechtsklick auf einen Wert, um ihn zu bearbeiten. |
| Profiler | Jeder Change-Detection-Zyklus als Balken; je höher, desto länger hat er gedauert. Gestartet wird mit dem Kreis oben links (Start recording). Die Checkbox Change detection zeigt, welche Komponenten tatsächlich geprüft wurden. |
| Injector Tree | Die Hierarchie der Environment- und Element-Injectoren und der Weg, den eine Abhängigkeitssuche nimmt (Angular 17+). |
| Router Tree | Der Routenbaum: Pfad, Komponente, Guards, Resolver, lazy oder nicht, welche aktiv ist. |
$ng0in der Console ist die gerade in Angular DevTools ausgewählte Komponente,$ng1die davor.- Das Inspect-Symbol in der Ecke der Erweiterung: Fahre mit der Maus über die Seite und sieh, welche Komponente dort ist.
- Ein Doppelklick auf eine Komponente bringt dich zu ihrem Element in Elements; das Symbol oben rechts zu ihrem Quellcode in Sources.
- Show Signal Graph im Kopf des Property-Bereichs zeichnet die Signals, Computeds und Effects der Komponente und wer wen liest (Angular 19+). Gib ihnen einen
debugName, damit sie lesbare Namen haben.
Die üblichen Quellen von Leaks und wie du jede schließt, findest du unter Memory Leaks. Was du tust, wenn du gefunden hast, was langsam ist: Performance und Change Detection.
Häufige Stolperfallen
- Du suchst in einem Production-Build nach deinem Klassennamen. Er ist nicht da: Suche nach Tag oder nativem Typ, oder starte die App mit
ng serve. - Snapshots vergleichen ohne vorher Collect garbage: Der Heap steigt und fällt von selbst, kleine Unterschiede bedeuten nichts.
- Die Aktion nur einmal wiederholen. Ein Leak ist eine Zahl, die bei jeder Wiederholung um denselben Schritt wächst. Wiederhole 10-mal und suche nach +10.
- Network erst nach dem Laden öffnen und glauben, es sei nichts angefragt worden. Network zeichnet nur auf, solange es offen ist: Lade die Seite neu.
Spickzettel
F12 · Ctrl+Shift+I · Cmd+Option+I DevTools öffnen
Ctrl+Shift+C · Cmd+Shift+C ein Element auf der Seite auswählen
Ctrl+Shift+P · Cmd+Shift+P das Befehlsmenü
Esc die Drawer-Leiste mit der Console
Network Fetch/XHR · Keep log · Disable cache · Throttling
Application Storage → Local storage · Service workers · Clear site data
Perf monitor JS heap size · DOM nodes · JS event listeners
Memory Heap snapshot → Take snapshot → Comparison → Filter by class
Memory Detached elements → Get detached elements
Performance Record · Record and reload · Show memory timeline
nur Entwicklung:
ng.getComponent($0) · ng.applyChanges(c) · ng.enableProfiling()
Angular DevTools: Components · Profiler · Injector Tree · Router Tree · $ng0