Recommended resources
The freely available resources this lesson will direct you to.
Hello! Welcome back to our module on Memory Leak Detection and Analysis.
In our last lesson, we established the critical difference between Shallow Size and Retained Size. You learned that while Shallow Size tells you the memory an object uses itself, Retained Size reveals the total memory that would be freed if that object were garbage collected. We concluded that sorting a heap snapshot by Retained Size is the best first step to find which objects are having the biggest impact on memory.
Today, we'll move from analyzing a static moment in time to a much more dynamic and powerful technique. Our goal is to use heap snapshots to identify memory leaks, such as detached DOM nodes, by comparing snapshots taken at different times. This method allows you to isolate the specific objects that are being created but not properly cleaned up during user interactions, which is the very definition of a memory leak.
The Core Technique: Comparing Snapshots
The fundamental workflow for finding memory leaks is a classic "before and after" experiment. You establish a baseline, perform an action you suspect is causing a leak, return the application to its initial state, and then see what has changed.
The official Chrome documentation provides a clear, step-by-step process for this.
Record heap snapshots | Chrome DevTools
This resource, from the official Chrome DevTools documentation, outlines the exact procedure for using the Comparison view to detect leaks.
Please read the section titled 'Comparison view'. It describes a four-step process for verifying that an operation doesn't create leaks. This is the core methodology for this entire lesson.
To summarize and reinforce the process:
- Get to a stable state and take a baseline heap snapshot (Snapshot 1).
- Perform an action (e.g., open a modal, switch a route).
- Perform the reverse action to return to the stable state (e.g., close the modal, navigate back). It's often good to repeat this cycle a few times to make the leak more prominent.
- Force garbage collection by clicking the trash can icon (
).
- Take a second heap snapshot (Snapshot 2).
- In the DevTools UI, select Snapshot 2 and change the view from 'Summary' to 'Comparison', ensuring you are comparing it against Snapshot 1.
The resulting view will show you the delta—what was allocated and not released between the two snapshots. You'll want to pay close attention to the Size Delta column. A large positive value for objects that you expect to be temporary is a strong sign of a leak.
A Common Culprit: Detached DOM Nodes
One of the most common types of memory leaks in front-end applications involves detached DOM nodes. As a lead developer, you've likely encountered situations where parts of the UI are removed, but performance degrades over time. This is a classic symptom.
A detached DOM node occurs when an element is removed from the DOM tree, but a reference to it is still held in your JavaScript code (e.g., in a global variable, a closure, or an event listener). Because this reference exists, the garbage collector cannot reclaim the memory for that node—or any of its children.
Let's read a concise explanation of this problem.
Fix memory problems | Chrome DevTools
This article clearly defines what a detached DOM node is and provides a simple, effective walkthrough for finding them using the heap snapshot's class filter.
Please read the section titled 'Discover detached DOM tree memory leaks with Heap Snapshots'. Pay attention to the simple code example and the screenshot showing how to filter for Detached in the snapshot view.
Practical Demonstration: Finding and Fixing a Leak
Now that we understand the theory, let's see it in action. The following video provides an excellent, end-to-end demonstration of identifying a memory leak caused by detached DOM nodes using the snapshot comparison technique.
The first segment will show you the process of taking the snapshots and using the comparison view to zero in on the problem.
He's Dead Jim: Finding JS Memory Leaks with Chrome Dev Tools
This video walks through a realistic scenario. The presenter uses the snapshot comparison technique to investigate a bug where an application gets progressively slower.
Watch from 07:25 to 10:27. The presenter takes a baseline snapshot, interacts with a form multiple times, and then takes a second snapshot. Notice how they switch to the 'Comparison' view and immediately identify a growing number of objects.
After comparing the snapshots, the presenter finds a suspicious entry: (detached DOM tree). This is exactly what we discussed. The next part of the video explains what these detached elements are and what the color-coding in DevTools signifies.
He's Dead Jim: Finding JS Memory Leaks with Chrome Dev Tools
Now that the leak has been spotted, let's understand exactly what DevTools is showing us.
Continue watching from 10:18 to 12:53. The presenter provides a fantastic visual analogy for how JavaScript references can prevent DOM nodes from being garbage collected. They also explain the meaning of the yellow and red highlighting for nodes in the snapshot.
To summarize the key points from the video:
- Yellow-highlighted nodes have a direct reference from your JavaScript code. These are often the root cause of the leak.
- Red-highlighted nodes are "detached" but are being kept alive because they are part of the same DOM subtree as a yellow-highlighted node. They don't have a direct JS reference themselves, but they can't be collected because their parent (or an ancestor) does.
A diagram showing how a JS reference to a detached DOM node prevents garbage collection.
This illustrates the core problem: a DOM node is removed from the page's tree, but a lingering reference in JavaScript (leafRef in this example) prevents it and its entire parent hierarchy from being garbage collected.
The rest of the video (LINK from 12:53 onwards) goes on to show how the developer debugs the code to remove the leaking reference and then verifies the fix by repeating the snapshot process, confirming that the detached nodes no longer appear. This full cycle—identify, fix, and verify—is a robust workflow for tackling memory issues.
Test your understanding!
You are working on a single-page application (SPA) with a photo gallery. Users report that after viewing several photos by opening them in a full-screen "lightbox" overlay and then closing them, the entire site becomes sluggish. You suspect a memory leak related to the lightbox component.
Describe the exact steps you would take using heap snapshots to confirm if closing the lightbox is leaking DOM nodes. What specific entry would you look for in the comparison view?
Show answer
- Initial State & Baseline: Open the application to the main gallery page. Open DevTools, go to the Memory panel, force garbage collection (trash can icon), and take Heap Snapshot 1.
- Perform Action Cycle: Open a photo in the lightbox, then close it. Repeat this process for 5-10 different photos to amplify any potential leak.
- Final State & Comparison Snapshot: Return to the main gallery view. Force garbage collection again to clean up any memory that can be freed. Take Heap Snapshot 2.
- Analyze: Select Snapshot 2, switch the view to Comparison, and set it to compare against Snapshot 1.
- Look For Leaks: Sort the list by
Size Delta(descending). Look for constructors related to your lightbox component that have a large positive delta. Crucially, filter the list by typingDetachedin the "Class filter" input box and look for(detached DOM tree). A non-zero count here is a strong confirmation of your suspected leak.
Conclusion
In this lesson, you've learned one of the most effective techniques for hunting down memory leaks. By comparing heap snapshots, you can move beyond static analysis and see exactly what memory is being "left behind" after specific user interactions.
Key Takeaways:
- The snapshot comparison workflow is a reliable method for isolating memory leaks: Baseline Snapshot -> Action -> Reverse Action -> Final Snapshot -> Compare.
- Detached DOM nodes are a frequent source of memory leaks in dynamic web apps, occurring when a JavaScript reference outlives the node's presence in the DOM.
- In the Comparison view, a large positive
Size Deltafor objects that should have been temporary is your primary indicator of a leak. - Filtering for
(detached DOM tree)is a direct way to confirm if DOM nodes are being leaked.
We've successfully identified a leak and know what type of object is leaking. But we don't yet know why it's leaking. What specific variable or property is holding onto that reference? In our next lesson, we will answer that question by learning how to trace object retention paths using the Containment view to find the root cause of a memory leak.