vuejs / core

🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
https://vuejs.org/
MIT License
46.8k stars 8.21k forks source link

Memory leak / component v-if ? #7448

Open michelvermeulen opened 1 year ago

michelvermeulen commented 1 year ago

Vue version

3.2.45

Link to minimal reproduction

https://sfc.vuejs.org/#eNqdVE2P2jAQ/StWVGlBgniXthcKiFba2/bW3nIJyWQ33cS2bCe7CPHf++wkEMKC0OYQzXjefHjmjXfBT6XCuqJgHixMonNlV5HISyW1ZX/izQPLtCxZFITcaQ4ZBT/6iNkJYjZE7JimbMKk+C0rYSll+w7fAendA1PK4qqAQyQYSyS8BQlr5s0B88VMDuLMi3v/N2QrNRp3wEQKY5l5kW++/qUrYGR1RWMkcwANvBYdHP4ttI2+9zAX2kkLfugKFEulKmJL0BhbpHntBYg+1VoqEq64ZRT08mdxYXBVVk/zrGfBCe+5z9h6Eyevp66ubO9JCNHCF7zJu+C9aqAauy2ImQRFpCuU7VRYgknQjGJaxir8Z6TAqP3do9ZgouDQ5XYscwgv1ioz57wS6vU5xET4GjauMca8pGkqy/XXcBZ++456jO2fh2TK6UbLN0MaGaOg7awPznFYk55qEilp0leTDbAnCQe2s6R+ihgiGtAR05H8fISwXuzpYCN2RyI7Tv+iTGr6K0p3dBuzG7IqLZWZIByVORwH3H2lbSrfBOY/ojFbro5UzTMchbCz5RKJHk0SK+Q6+LvPhRxFgSMTLC3nfSuO7GbHe4ywOf0UqUyqEpsXxmn6WEN4QrNJkEbMtjAMtKuxi7/vhEFTLkbXVMqaPpGg295ra9qsQhGLZ7dOiQEbPlyM7kn7mBftbuZCVdY9IojlZQSzW0VQLb07La6szHAxc1zoTWWtFFhc9ML5sVywh/v7e6DXSZH7Pf/iJ3XXPRp34yhYPeWCFrzxvr7t15iJYs/ZeI2PAwI2V25eTlEVxXG4F0jDuXcJ67ioKPS9GF2c3IHMzuWGR/e2ae7/A16gPXA=

Steps to reproduce

What is expected?

What is actually happening?

System Info

No response

Any additional comments?

I've been scratching my head for days now. I have a similar issue in my app, and it looks like it doesn't happen if I don't add the focus to the field in the mounted hook.

Problem seems systematic on Vue SFC, and it also happens, although not as consistently, on my test app:

https://we.tl/t-yXD6l3kVxm

LinusBorg commented 1 year ago

Can you try replicating it with the devtools disabled, maybe in an private tab?

michelvermeulen commented 1 year ago

I did and it does the same thing.

LinusBorg commented 1 year ago

I compared two heap snapshots on the provided reproduction and can't really spot anything extraordinary. Would you be able to provide a bit more guidance on where and how you see the leaked components and listeners?

michelvermeulen commented 1 year ago

Sorry, I actually commented out the focus in the SFC. It's back on.

What I do is play around with the buttons/esc to go back and forth, and randomly force GC in the Chrome console.

This is what I start with, and end up with after playing for a minute:

Fresh state CleanShot 2023-01-02 at 17 34 18

After a minute CleanShot 2023-01-02 at 17 34 10

michelvermeulen commented 1 year ago

Not a major overhead but when you work with lots of lines and an app that stays in for a long time you end up with a large chunk of memory leaking.

michelvermeulen commented 1 year ago

Actually my screenshot shows a lower Heap but I can also reproduce more listeners and more dom nodes with a higher heap.

michelvermeulen commented 1 year ago

Here's another interesting bit. I was testing again in private mode, on VueSFC, and after clicking and fiddling around for a while, just refreshing the page is increasing the memory heap.

-> After going back and forth between components, way too many event listeners compared to what it's supposed to be, and it's not going down even after garbage collecting. CleanShot 2023-01-02 at 19 55 55

-> After several refresh of the page, the heap is going nuts! CleanShot 2023-01-02 at 19 56 37

weidehai commented 1 year ago

because vue didn't removeEventlistener explicit(in modern browser,removeEventlistener will be call automatic after dom remove),the question you mentioned that event listeners not going down,I guess the reason is browser control it clear action at specific conditions(not exactly at remove dom),and after reach a certain amount, it will not be grow up(switch tab many times and watch the event listeners count change) if you want to explict immediately remove it,you can do it like that image

ferferga commented 1 year ago

@weidehai Unless I'm missing something, there's a removeEventListener in a onBeforeUnmount hook

ChuChencheng commented 1 year ago

Another similar reproduction here with Vue 3.3.4 I've tested in private mode.

  1. Switch to 'SelectPage' tab and switch back to 'EmptyPage'
  2. GC

The heap size/DOM nodes did not go back. But it worked as expected when I switched between EmptyPage and DivPage tabs. Maybe there's something to do with the native select/option tag?

Also can check out the video in this issue