Home > front end >  Vue.js memory leak with Turbolinks even with destroy() being called - browser always keeps a referen
Vue.js memory leak with Turbolinks even with destroy() being called - browser always keeps a referen

Time:10-06

I have a Rails apps that uses Turbolinks. If you're not familiar, turbolinks makes so that the document and window object always remains the same (the page is never refreshed), and it intercepts all link clicks via AJAX and replaces the body tag.

When navigating TO and FROM a page that has a Vue app mounted, this is the memory/nodes pattern that we observe (it grows to infinity):

enter image description here

As you can see, on each page change, memory only increases, never being reclaimed.

Our App uses enter image description here

CodePudding user response:

The syntax should be something like

beforeMount() {
 document.addEventListener('turbolinks:visit', this.tearDown());
},
methods: {
 tearDown() {
  ....
  // Have this method in case if you want to perform any actions for the eventListener and not for destroying purpose
 }
},
beforeDestroy() {
 ....de-allocate variable memories
 document.removeEventListener('turbolinks:visit', this.tearDown());
}

CodePudding user response:

Boy, was I in for a ride. There were 6 memory leaks in my app.

To discover them, do this:

  1. Open your Chrome devtools and focus the Memory tab (I suggest doing this in a icognito tab, so extensions don't mess with the measurements); refresh your app, and then click the little trash can (which will force a Garbage Collect - GC);

Start noting the indicator of MB in the "Select Javascript VM Instance" (you'll probably have one line there only). You can ignore the up/down arrow indicators there, focus only on the first number, which is how many MB your tab is using right now.

enter image description here

  1. Start using your app; in your case, navigating TO and FROM the page that had the Vue app; note if the memory is going always up or if when you navigate away from the Vue app it comes down;

In your case, navigating TO and FROM the app increased memory usage of 20 MB every time, eventually reaching 200MB after 10 times or so; clicking the Garbage Collect icon only decreased usage of around 10MB, so it was obvious we head a leak.

After you have put the page in this leak state and clicked the GC trash icon, select "Heap snapshot" in the radio options. It will collect a snapshot. Click on it.

In our case, our Vue app was being kept in memory due to the leak. So we focused on the "VueComponent" items in the list. Click the little triangles and watch the lower part of the screen. It will start showing you what pieces of code are retaining those references in memory. Sometimes you'll get lucky and even get some line numbers there, that you can click and it will open in the sources tab.

We had 6 leaks in your app; below I'm showing one of them, and you'll see the memory trace is pointing to $notify, which was a lib (vue-notification) we were using:

enter image description here

Yes, you can have leaks from other people's code, that's a bummer. Looking at that lib, I could find the culprit was two event handlers defined on the created hook, that were never released; I issued a pull request enter image description here enter image description here enter image description here

  • Related