tusen-ai / naive-ui

A Vue 3 Component Library. Fairly Complete. Theme Customizable. Uses TypeScript. Fast.
https://www.naiveui.com
MIT License
16.2k stars 1.67k forks source link

组件库内置Icon的错误用法会导致页面detached,从而造成内存无法被回收 #6299

Open tracy2zhang opened 2 months ago

tracy2zhang commented 2 months ago

Describe the bug

很多组件的内置Icon(比如checkbox的CheckMark)使用方式不当,导致dom元素在卸载之后仍然被引用,造成内存无法被回收。

image

比如上面这个就是CheckMark,这种写法,会导致checkmark是一个全局的vnode,这个vnode是永久存在的,因此它绑定的el也不会被回收,因此会成为一个detachedElement。甚至会造成使用checkbox的大组件整个都detached。

Steps to reproduce

edge浏览器devtools有个比较好用工具-分离的元素detached element:https://learn.microsoft.com/en-us/microsoft-edge/devtools-guide-chromium/memory-problems/dom-leaks 1.打开devtools的「分离的元素」工具 2.点击toggle按钮,显示checkbox及其他元素 3.再次点击toggle,卸载checkbox及其他元素 4.在「分离的元素」工具中查看现有的detached element可以看到无法被GC的元素

image

Link to minimal reproduction

https://github.com/tracy2zhang/naive-demo

System Info

System:
    OS: macOS 14.5
    CPU: (10) arm64 Apple M1 Max
    Memory: 9.51 GB / 64.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 20.5.1 - ~/.nvm/versions/node/v20.5.1/bin/node
    Yarn: 1.22.15 - /usr/local/bin/yarn
    npm: 9.8.0 - ~/.nvm/versions/node/v20.5.1/bin/npm
    pnpm: 9.5.0 - /opt/homebrew/bin/pnpm
  Browsers:
    Chrome: 128.0.6613.86
    Safari: 17.5
  npmPackages:
    naive-ui: ^2.39.0 => 2.39.0 
    vue: ^3.4.37 => 3.4.38

Used Package Manager

yarn

Validations

Zheng-Changfu commented 2 months ago

你是在开发环境吧,开发环境无法 GC 是因为 Vue 在开发环境会在 Dom 上定义 2 个属性,一个 vnode,一个 vueParentComponent,这 2 个属性是给 Vue Devtools 使用的,你可以使用生产环境的试试

tracy2zhang commented 2 months ago

你是在开发环境吧,开发环境无法 GC 是因为 Vue 在开发环境会在 Dom 上定义 2 个属性,一个 vnode,一个 vueParentComponent,这 2 个属性是给 Vue Devtools 使用的,你可以使用生产环境的试试

生产环境一样有这个问题,hoistStatic我也设置成false了。这个并不是DOM上是否有vnode,而是vnode上的el引用了DOM。而这个icon这种写法会被编译成一个全局的vnode。

yeyuqh commented 2 months ago

看来 #6200 这个就是由于 checkbox 的 icon 导致的内存无法回收?

tracy2zhang commented 2 months ago

@Zheng-Changfu 这种Icon写法问题在naive-ui这个库的好几个组件中都存在,checkbox只是其中之一。其中用到replacable方法的那几个icon都会有这个问题,不过这种可以通过在n-config-provider上设置icons属性,用自定义的icon替换内置icon的方式避免内置icon引起的内存问题。

Zheng-Changfu commented 2 months ago

@Zheng-Changfu 这种Icon写法问题在naive-ui这个库的好几个组件中都存在,checkbox只是其中之一。其中用到replacable方法的那几个icon都会有这个问题,不过这种可以通过在n-config-provider上设置icons属性,用自定义的icon替换内置icon的方式避免内置icon引起的内存问题。

在你还没有回复之前,我发现了这个问题,我在这个 pr 里面对这些问题进行了修复:https://github.com/tusen-ai/naive-ui/pull/6319

Zheng-Changfu commented 2 months ago

其实现在还有一个很大的问题,就是 @vicons 这个 icon图标库也存在内存泄漏问题,除了对 naive-ui 组件库中 data-table 会产生影响之外,还会对开发者的业务项目产生影响,目前正在跟进这个问题