vue-hot-reload-api icon indicating copy to clipboard operation
vue-hot-reload-api copied to clipboard

Hot reload and memory leak (functional components)

Open AndreiSoroka opened this issue 5 years ago • 3 comments
trafficstars

Version:

v2.3.4

How to reproduce:

Just comand+c & comand-v in your terminal: (ctrl+c & ctrl+v / copy & past)

vue create -d -n vue-memory-leak-functional;
cd vue-memory-leak-functional;
yarn;
# create Functional.vue
echo "<script>
  export default {
    name: 'Functional',
    functional: true,
    render(createElement) {
      return createElement('div', 'HelloWorld');
    }
  }
</script>" > src/components/Functional.vue

# create JustComponent.vue
echo "<template>
  <div>
    <functional v-for=\"i in 100\" :key=\"i\" />
  </div>
</template>
<script>
import Functional from \"./Functional\";
export default {
  name: 'JustComponent',
  components: { Functional },
}
</script>" > src/components/JustComponent.vue

# update HelloWorld.vue
echo "<template>
  <div>
    <just-component v-if=\"show\" />
  </div>
</template>
<script>
import JustComponent from \"./JustComponent\";
export default {
  name: 'HelloWorld',
  components: {JustComponent},
  data() {
    return {
      show: true
    }
  },
  created() {
    setInterval(()=>{
      this.show = \!this.show;
    }, 1000);
  },
}
</script>" > src/components/HelloWorld.vue
yarn serve;

after that open devtool > more tools > performance monitor

image

AndreiSoroka avatar Jun 16 '20 16:06 AndreiSoroka

Or, manual:

vue create -d -n vue-memory-leak-functional;
cd vue-memory-leak-functional;
yarn;

Update HelloWorld.vue

<template>
  <div>
    <just-component v-if="show" />
  </div>
</template>
<script>
import JustComponent from "./JustComponent";
export default {
  name: 'HelloWorld',
  components: {JustComponent},
  data() {
    return {
      show: true
    }
  },
  created() {
    setInterval(()=>{
      this.show = !this.show;
    }, 1000);
  },
}
</script>

Functional.vue

<script>
  export default {
    name: 'Functional',
    functional: true,
    render(createElement) {
      return createElement('div', 'HelloWorld');
    }
  }
</script>

JustComponent.vue

<template>
  <div>
    <functional v-for="i in 100" :key="i" />
  </div>
</template>
<script>
import Functional from "./Functional";
export default {
  name: 'JustComponent',
  components: { Functional },
}
</script>

After that just start

yarn serve;

AndreiSoroka avatar Jun 16 '20 16:06 AndreiSoroka

I can confirm this is still an issue in 2.6.10 on my end. I'm testing this with an empty functional component:

<template functional>
</template>

toggling v-if on a parent where this component is nested into will cause a detached HTMLDivElement in the memory heap. I got the suspicion that this causes further memory issues. As soon as I remove functional from the template tag this leak is gone.

In conclusion, functional components cannot be used in Vue 2, I will convert all my functional components to normal components to bypass this issue.

martin-braun avatar Aug 22 '20 00:08 martin-braun

@martin-braun this only affects the hot reload mode. Yes it can mess up development because memory increases, and you can't really debug memory leaks, but in a production build, the functional components are cleaned up correctly.

Narretz avatar Aug 06 '21 11:08 Narretz