CodePark/ questions / Memory leaks in SPAs
START PRACTICINGPRACTICE
Frontend question · Browser & web performance › Memory leaks in SPAs

What is a detached DOM element, how does it leak memory in a single-page app, and how do you find leaks with Chrome DevTools?

A detached DOM element is an element that was removed from the page, but JavaScript still holds a reference to it. So the garbage collector can't free it. It also keeps its whole subtree and its event listeners alive.

In a single-page app, the page never reloads, so a small leak grows with every route change. Common causes:

  • A module-level array or cache that stores elements, like const openModals = [].
  • A listener on window or document whose closure uses an old element.
  • A third-party widget that is never destroyed when its component unmounts.

Finding it with DevTools (the three-snapshot method):

  • Open the Memory panel. Load the page and take a heap snapshot.
  • Do the suspicious action several times, for example open and close a dialog 5 times. Take a second snapshot.
  • Repeat once more and take a third snapshot.
  • Compare the snapshots. Objects that grow by the same count every round are the leak.
  • Type "Detached" in the class filter to list detached elements. Open one and read its Retainers. They show the chain of references that keeps it alive, and that leads you to your code.

The Performance monitor and the Allocation timeline help you first confirm that memory keeps rising.

  • A detached element is removed from the page but still referenced from JavaScript.
  • It keeps its subtree and listeners in memory too.
  • In a single-page app, leaks add up with every navigation because the page never reloads.
  • Take heap snapshots before and after repeating an action, and compare them.
  • Filter by "Detached" and read the Retainers to find the reference that keeps it alive.