This article was originally published at github.com/bigo-fronte… Welcome attention, reprint.

background

Stalar e-commerce platform is a new business of BigO in 2020. The target market is mainly five countries in the Middle East, and the main technology stack is NUXT.

After the regular demand goes online, I accidentally open the Chrome memory panel and hit a few memory snapshots. I found that the memory has been rising, and no matter what page is jumped to, the memory is growing steadily; In order to eliminate interference factors, I manually clicked GC before the snapshot, and found that the memory increment only decreased a little bit, but still showed a stable growth trend overall. Aware that this is a serious problem, because the dealer detail page is recommended goods module, that is to say, users’ browsing path here is endless, is likely to have users appear in the browser browse pages collapse after a large number of goods or flash back of the (lack of monitoring page collapse as of yet, so you also not sure).

In the memory snapshot below, the first one is the first time to enter the business page, and the second one is to click the recommended product in the business page to enter the next business page. Repeat for ten times (this method is used in the following screenshots comparing the changes in memory etc.). After manually clicking GC before both snapshots are generated, you can see that the memory is 12.3MB

Reasons for screening

Nuxt framework issues

Observed any page jump, can let the memory stable growth, even some simple page, no logic also has a certain degree of memory leaks, so first suspected nuxt framework or on other wheels itself there is a memory leak problem, googled found nuxt there is some small version of a memory leak, Such as: nuxt/issue / 7855

Since doubt framework has a problem, first do is to nuxt upgrade to the latest version (in fact, we use nuxt version has been relatively new, see some of nuxt issue seems to be a small version has rapid memory problems, more confused), observed situation just a little bit better, for some simple page, memory has not increased, But in the worst-hit areas, you can still see a large increase in memory.

Code problem

Go back to Chrome to analyze the cause of the memory leak, reopen the Business page and open the Performance Monitor, and repeat the previous operation of clicking on the recommended products from the Business page. It is found that JS Heep size, DOM Nodes, JS and Event Listenters all increase steadily, and DOM Nodes also jumps for 10 times. DOM Nodes rises from 3k to 11K. The following is the screenshot of the Performance Monitor panel after 10 jumps:

For the same business page, even if the elements of different commodity pages are different, DOM Nodes cannot have such a huge difference, and event listenters also have a steady growth, so it is suspected that some DOM event monitors are not unbound, leading to the non-release of free Nodes. Let’s compare the two memory snapshots above. The discovery that there are indeed very large detached node growth confirms this speculation.

Start with the global approach.

An encapsulated custom directive for reporting

V.directive('report', {
  bind(el) {
    if (option.onload) {
      el.addEventListener('load', option.onload);
    }
    if (option.onerror) {
      el.addEventListener('error', option.onerror); }}});Copy the code

After adding the unbinding method

V.directive('report', {
  bind(el) {
    if (option.onload) {
      el.addEventListener('load', option.onload);
    }
    if (option.onerror) {
      el.addEventListener('error', option.onerror); }},unbind(el) {
    if (option.onload) {
      el.removeEventListener('load', option.onload);
    }
    if (option.onerror) {
      el.removeEventListener('error', option.onerror); }}});Copy the code

Similarly, there are some global encapsulation of scroll listener and so on.

After the global method scan, found that the situation is still not much better, back to the above two memory snapshots, try to find the details of the memory leak caused by the specific method.

SpecsSChange is monitored in the SkuBlock component:

The code is:

mounted() {
  eventBus.$on('specsSChange'.(specsS) = > {
    this.specsS = specsS;
  });
}
Copy the code

Revised:

mounted() {
  eventBus.$on('specsSChange'.(specsS) = > {
    this.specsS = specsS;
  });
},
beforeDestroy() {
  eventBus.$off('specsSChange');
}
Copy the code

There are some similar listening methods, modify the way similar, not an example.

Wheel not destroyed

With some third-party wheels, you need to create an instance in the component. If the wheel instance is not destroyed after the component is destroyed, it may cause a memory leak. You can also look at the memory snapshot details to find out which component wheel is causing the memory leak.

For example, the business page has a copy and share link function, using clipboard.js, which is used in the business page like this:

mounted() {
  const clipboard = new Clipboard('#copyLinkBtn');
  clipboard.on('success'.() = > {
    // do something
  });
}
Copy the code

I didn’t go into the details of why clipboard.js did not destroy the memory leak, but I guess it is because the DOM object reference was not freed. The modification method is also simple, just call the wheel provided the destruction method

mounted() {
  this.clipboard = new Clipboard('#copyLinkBtn');
  this.clipboard.on('success'.() = > {
    // do something
  });
},
beforeDestroy() {
  if (this.clipboard) {
    this.clipboard.destroy(); }}Copy the code

The final result

After all the modifications are made online, the method of clicking the recommended products on the business page to enter the next business page is repeated for ten times to test the memory leak. First, observe that the number of Performance Monitor, DOM Nodes and JS Event Listeners does not increase significantly:

Before optimization

The optimized

The Delta value of the free node (the difference between the two snapshots) drops to 0!

Before optimization

The optimized

Finally, looking at the memory snapshot overview, you can see that the memory has not been increased

Before optimization

The optimized

conclusion

Memory leak causes troubleshooting, learning to use Chrome DevTools Tools is very important, you can refer to Chrome Tools, troubleshooting ideas can be considered to the following aspects:

  • The global variable
  • DomReferences are still made outside the document stream
  • closure
  • Third party wheel not destroyed and duplicate created

Welcome to leave a message and discuss, I wish a smooth work, happy life!

I’m bigo front end, see you next time.