core: Detached nodes after unmount component(Memory leaks)
Version
3.2.29
Reproduction link
Steps to reproduce
first step run npm run build, open dist/index.html
highlight element with id app , write in console $0.__vue_app__.unmount()
after unmount app create heap snapshot, we have memory leaks in heap snapshot

What is expected?
zero detached dom elements and detached vue EventListeners…
What is actually happening?
exist in heap snapshot: 2001 Detached HTMLDivElement Detached EventListener …
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Comments: 19 (11 by maintainers)
@LinusBorg here we go

I investigated the repro and noticed a few very complicated conditions. For the original reproduction, the “leak” only happens if I click the button first, then unmount the app via the inspector + console.
If you change
main.jsto the following:The leak doesn’t happen after app is unmounted.
If you add a button outside of the app (in
public/index.html), and then manually attach an event listener to it that callsapp.unmount(), the leak also doesn’t happen. So I don’t think the leak is caused by Vue’s patching mechanism, and in some way Chrome devtool inspection also affects the behavior.The leak does happen if the unmount is triggered by an event dispatched from an element within the unmounted parent element. Interestingly, this seems to be a Chrome bug - because I was able to reproduce this without Vue involved at all in this gist.
In addition, this leak seems to be “temporary” - i.e. if this process is repeated by clicking the “reset” button in the above gist, the total amount of nodes in memory does not increase. In fact, I’ve noticed that the detached nodes are garbage collected when another event listener is triggered. Previously detached nodes are somehow reclaimed. So in some way, this isn’t really a “leak” since the total memory does not increase over time.
To sum up: this seems to be a Chrome issue, and I couldn’t find any way to “fix” this in Vue, since even replacing current event patching with plain
addEventListenercalls makes no difference from my tests. The fact that it also affects Vue 2 may be an indication that this is a recently introduced bug in Chrome. I’ve filed a Chrome bug here: https://bugs.chromium.org/p/chromium/issues/detail?id=1324096@LinusBorg Now I’m pretty sure it’s a bug.
We created invoker at here and reference component instance.
https://github.com/vuejs/core/blob/c35ec47d73212b1b1fb1abca9004f992c45aa942/packages/runtime-dom/src/modules/events.ts#L107-L132
These elements reference invoker’s closure (_vei) https://github.com/vuejs/core/blob/c35ec47d73212b1b1fb1abca9004f992c45aa942/packages/runtime-dom/src/modules/events.ts#L81-L82
So after removeChild, these elements become detached, even can’t remove component instance.
https://github.com/vuejs/core/blob/9aa5dfd4bb8efac0041e33ef5fdbebab59cc6516/packages/runtime-dom/src/nodeOps.ts#L17
Because we should remove these references before removeChild:
Sorry, I misunderstood you, it’s similar to vue-devtools’s behavior, but it’s another problem😥. There is a related issue
It seems that those invokers not be cleaned during unmount.
https://github.com/vuejs/core/blob/c35ec47d73212b1b1fb1abca9004f992c45aa942/packages/runtime-dom/src/modules/events.ts#L72
@Akryum Do you agree with @caozhong1996? Should we move this issue to the devtools repo?
We just have a hard time figuring out a reason as to why detached elements aren’t garbage collected.
I’m just as confused by this as you, even in this situation which still appeared😥
It’s not memory leak. This is due to vue-devtools recorded some information which contains thoese elements and this only happen on development environment(I can’t reproduced what you said), but I think vue-devtools should be improved.