Subscribe on changes!

Memory leak in hoist static

avatar
Jan 13th 2022

Version

3.2.26

Reproduction link

github.com

Steps to reproduce

  1. Open dist/index.html
  2. Click click button three times.
  3. Open memory panel in chrome devtools, then take heap snapshot, then search BigData。

What is expected?

old component instance can reacyled

What is actually happening?

old component instance not reacyled


静态节点优化会在闭包中创建一个 hoisted${num} 的变量,之后渲染时,会将 hoisted.el 设置为dom。假如此组件中有事件监听,则会造成实例无法回收,从而造成内存泄漏。

Static hoist will creates a hoisted variable in the closure, and later sets dom to hoisted.el when rendering. If there are event listeners in the component, the component instance cannot be recycled, resulting in a memory leak.

avatar
Jan 13th 2022

image

avatar
Jan 16th 2022

This only keeps the first component instance in memory, so it's technically not a memory leak because the total memory won't increase over time. It's still inefficient though and can be improved.

avatar
Jul 4th 2022

I also ran into this issue while trying to fix a memory leak. It's quite inconvenient while hunting for leaks, as it's something that will get you on the wrong track. Glad to know this now..

avatar
Jul 4th 2022

You can temporarily circumvent this problem by using the following methods

vue-cli:

  chainWebpack: (config) => {
    config.module
      .rule('vue')
      .use('vue-loader')
      .tap((options) => {
        options.compilerOptions = options.compilerOptions || {};
        options.compilerOptions.hoistStatic = false;
        return options;
      });

  },
avatar
Jul 4th 2022

Thanks. For vite you can use:

plugins: [vue({ template: { compilerOptions: { hoistStatic: false } } })],
avatar
Sep 27th 2022

This only keeps the first component instance in memory, so it's technically not a memory leak because the total memory won't increase over time. It's still inefficient though and can be improved.

这种场景放到动态路由上: 反复大量的不同内容的相同页面组件, 递增的量就异常可观了, 浏览器标签爆掉就非常的简单了.