Memory leak in lottie-web

Viewed 788

I'm using lottie web on my front-end. But I still having problem with memory leak. When I remove all lottie, JavaScript VM instance is under 10MB.

When I enable lottie, anytime I refresh page or walking through the other pages, the memory increases rapidly. From 30MB to 80 etc.. Then the page appears lagy.

I found this issue, but the solution is not correct for me because my animations does not use repeaters. Anyway I tried to do it that way, without any result.

You can see the whole test website here.

NOTE: I'm using vue and my custom component for lottie animations

<template>
    <div ref="animation"></div>
</template>

<script>
import lottie from 'lottie-web';

export default {
    data() {
        return {
            hover: false,
        }
    },
    mounted() {
        lottie.loadAnimation({
            container: this.$refs.animation,
            renderer: this.renderer,
            loop: this.loop,
            autoplay: this.autoplay,
            path: this.path, // This is where my animations come from.
        });
    },
    props: { /* my props */ }
}

I also tried to put the animation via import:

import animation from '../../../../images/web/ilu-we-create.json';
...
mounted() {
    lottie.loadAnimation({
        container: this.$refs.animation,
        renderer: this.renderer,
        loop: this.loop,
        autoplay: this.autoplay,

        // Without deep copy
        animationData: animation,

        // With deep copy
        //animationData: JSON.parse(JSON.stringify(animation)),
    });
},
...

The result with memory usage is almost same with every solution.

Is there somebody who know how lottie allocate memory and how to avoid those memory leaks?

Thank you a lot.

1 Answers

I experienced the same issue and may have managed to sort it out (not expert monitoring memory leak so)

I dynamic import lottie and animationData like so.. AND not ONLY call destroy method like this.animation.destroy() but ALSO this.lottie.destroy()

...,
  async mounted () {
    this.lottie = await import('lottie-web').then(module => module.default)
    this.animationData = await import('~/path/to/animationData.json')
    this.$nextTick(() => {
      this.animation = this.lottie.loadAnimation({
        animationData    : JSON.parse(JSON.stringify(this.animationData)),
        loop             : false,
        autoplay         : true,
        renderer         : 'svg',
        container        : this.$refs.heroCanvas,
        rendererSettings : {
          progressiveLoad: false,
        },
      })
    })
  },
  beforeDestroy () {
    if (this.lottie) {
      this.lottie.destroy()
      this.lottie = null
    }
    if (this.animation) {
      this.animation.stop()
      this.animation.destroy()
      this.animation = null
    }
  },
...
Related