nuxt内存泄漏问题记录

nuxt内存泄漏问题记录


nuxt 内存泄漏 性能优化 前端

1.项目发布上线之后,线上经常出现内存溢出的情况,导致项目崩溃。由于使用 pm2 管理,导致的结果就是不断重启。

一开始想的是不是 node 内存分配太少了,没有配置内存大小,使用的应该就是默认的,64 位大概在 1.5G 左右。但是后来觉得就目前的访问量来说,这些内存应该是够用了。
然后怀疑是每次服务端渲染页面的时候会在服务端产生缓存,或者是不是每次请求的时候、请求函数内部有闭包导致变量没有释放,所以在请求返回的拦截里打印了当前占用的内存。
//显示当前占用内存
function showMemory(url = "") {
  let date = new Date();
  date =
    date.getFullYear() +
    "-" +
    (date.getMonth() + 1) +
    "-" +
    date.getDate() +
    "T" +
    date.getHours() +
    ":" +
    date.getMinutes() +
    ":" +
    date.getSeconds();

  let output = `[${date}] 请求接口:${url}`;

  if (process && process.memoryUsage) {
    const {
      heapUsed: used,
      rss,
      heapTotal: tot,
      external: ext,
    } = process.memoryUsage();
    const f = (value) => (!value ? "-" : `${Math.round(value / 1048576)} MB`);
    output += `\
堆中使用的内存: ${f(used)} - 堆中总共申请的内存: ${f(tot)} - 内部占用: ${f(
      ext
    )} - (总内存占用: ${f(rss)})`;
    console.log(`${output}`);
  }
}
通过打印发现,每次刷新页面的时候,内存占用都会升高,并且不会降低,也就是不会被回收。于是使用 heapdump 插件存下内存快照,然后使用 chrome 的控制台分析,排查具体原因,可是也没有找到是什么导致的。
最后再去复习 nuxt 中每个生命周期会在什么时候运行,发现 created 会在服务端和客户端都运行一次,而项目中有两个地方在 created 中使用了 setInterval 定时器,且是 layout 中的组件,也就会导致访问每个页面都会生成一个定时器,且没有销毁。将这两个定时器放在 mounted 中内存使用情况就正常了,同时在项目中只要不是特殊情况都尽量避免使用 created,在 asyncData 和 mounted 中处理。

2.奇怪的页面渲染问题

此项目使用了 at-ui,有一个页面使用了组件,里面写死了两个 tab,如下:
<at-tabs>
  <at-tab-pane label="tab1">
    <component1></component1>
  </at-tab-pane>
  <at-tab-pane label="tab2">
    <component2></component2>
  </at-tab-pane>
</at-tabs>
此时页面渲染了三个 tab,第一个 tab 渲染了两次,这个现象惊到我了。于是我试着把第一个 tab,也就是 tab1 注释了,这时页面渲染正常,只有一个 tab2。一开始找不到原因,看到控制台有个报错,由于是测试环境,第一眼就觉得报错跟这个表现没关系,就没有太关注,于是在 component1 这个组件中找原因,发现注释这个组件后,页面渲染也是正常的。于是又回过头来看了这个报错,报错如下:
[Vue warn]: The client-side rendered virtual DOM tree is not matching server-rendered content. This is likely caused by incorrect HTML markup, for example nesting block-level elements inside

, or missing . Bailing hydration and performing full client-side render.

然后找了这个报错的具体原因:
简单翻译成中文是:
客户端呈现的虚拟DOM树与服务器呈现的内容不匹配。 这可能是由不正确的HTML标记引起的,例如在<p>中嵌套块级元素或缺少<tbody>
可能原因 1 - 不符合 HTML 规范
就像警告信息中说的那样 - 由不正确的HTML标记引起的,例如在<p>中嵌套块级元素或缺少<tbody>
对于这种情况,检查下是否有这样的模板内容是否有不遵守HTML规范的写法,改正就好了,问题不大。
如果是某个引入的插件导致的,自己没办法改,只能选择用<no-ssr>不让它在服务端渲染或者忽略警告。
可能原因 2 - 服务端和客户端数据不一致
有时候按照原因1找了很久也没能解决问题,但有其他一些怪异表现 - 列表渲染不正常:例如刚渲染完列表数量正常,加载完后数量就错了,或有数据消失了。
于是在 component1 组件中排查问题,发现存在嵌套的写法,即:
<nuxt-link>
  <div>
    <nuxt-link></nuxt-link>
  </div>
</nuxt-link>
于是修改写法,不做嵌套,最后页面渲染正常。
© 2025 Niko Xie