Reputation: 173
For purpose of this post i created a simple example: http://wagoon.demoeshop.net/test-remove-vue.html
In this example you will find two buttons.
DIV
element, then creates a Vue app and mount it to that div
In my example, you will find two buttons
<button type="button" onclick="myTest.mount()">.mount()</button>
<button type="button" onclick="myTest.unmount()">.unmount()</button>
Vue.js 3 is included
<script src="https://unpkg.com/vue@next"></script>
Whole javascript code is wrapped in function testClass()
for debugging reasons:
function testClass(){
// vueApp is public just for debugging reasons
this.vueApp = null;
// creates DIV with id #appDiv and apends it to <body>
function createDiv(){
var div = document.createElement('div');
div.id = "appDiv";
document.body.append(div);
}
// creates new Vue app and mounts it to #appDiv
this.mount = function(){
createDiv();
this.vueApp = Vue.createApp({"template":"Vue mounted"});
this.vueApp.mount('#appDiv');
}
// unmounts Vue app
this.unmount = function(){
// MEMORY LEAK HERE:
this.vueApp.unmount('#appDiv'); // this line should mark vueApp as collectable for garbage collector,it's not
this.vueApp = null; // event this line does not help
// SOLUTION: only removing app taget element from DOM is marking object created with Vue.createApp()
// as collectable by garbage collector.
// document.querySelector('#appDiv').remove();
}
}
myTest = new testClass();
For debugging reason, created app is stored to this.vueApp in testClass so we can find the object id easily. Just follow these steps
Only solution I found is removing DIV#appDiv
from the DOM (code for removing this element is commented in the myTest.unmount()
method). After that, calling garbage collector again will remove this object from memory.
Is there any other solution?
In big apps with multiple screens, creating and deleting whole app is the only way, how to save memory (script just loads code for actual page, and when user wants another page, actual page is destroyed and new page is loaded, then new Vue app is created)
You can't also solve this problem with creating dynamic components, because Vue3 removed (and i thing its big mistake) the $destroy method, so when you create new component for new screen, the old component will remain in memory forever.
Vue router will not solve this problem, because Vue router loads all pages on start and that is not acceptable in big apps, because the network bandwidth will be huge (megabytes of code loaded for just one app is just wrong)
Upvotes: 5
Views: 5595