首页 > 解决方案 > server.js 中的内存泄漏 反应/快递/ SSR

问题描述

我正在运行一个在 nodejs 服务器上呈现的反应应用程序。几天后我看到nodeJs进程的内存根据访问者的数量而增加。每次我重新加载页面时,内存使用量都会增加一点。一开始,该过程需要大约 60MB 内存。几天后,它增加到〜450MB。现在我正在重新启动节点进程来解决这个问题。

我认为这是我的 React 设置的问题。即使我只渲染一个非常小的应用程序,我也会得到泄漏。例子:

// Express server
app.get('*', async (req, res, next) => {
  try {
    const html = ReactDOM.renderToStaticMarkup(
      <html>
        <head />
        <body>
          <h1>hello</h1>
        </body>
      </html>,
    );
    res.status(200);
    res.send(`<!doctype html>${html}`);
  } catch (err) {
    next(err);
  }
});

为了检查内存泄漏,我强制每 3 秒进行一次垃圾收集,并在使用autocannon发出几千个请求时打印出内存使用情况。这给出了以下结果:

Program is using 16234160 bytes of Heap. // Start, no requests yet
Program is using 16177744 bytes of Heap.
Program is using 16177864 bytes of Heap.
Program is using 15185808 bytes of Heap. // Idle heap
Program is using 15185808 bytes of Heap.
Program is using 15185808 bytes of Heap.
Program is using 15185808 bytes of Heap.
Program is using 19199696 bytes of Heap. // Beginning of first 10k requests
Program is using 20890376 bytes of Heap.
Program is using 20201600 bytes of Heap. // New idle heap
Program is using 20201600 bytes of Heap.
Program is using 20201600 bytes of Heap.
Program is using 20201600 bytes of Heap.
Program is using 21761368 bytes of Heap. // Beginning of second 10k requests
Program is using 23862168 bytes of Heap.
Program is using 25191168 bytes of Heap.
Program is using 24731176 bytes of Heap.
Program is using 24512424 bytes of Heap. // New idle heap
Program is using 24512424 bytes of Heap.
Program is using 24512424 bytes of Heap.

当我渲染“真实”的 React 应用程序时,内存使用量当然会大大增加。以下屏幕截图显示了第一次启动应用程序和向页面发出单个请求之间的区别:

比较

如果我只返回一个没有 React 的字符串renderToStaticMarkup,问题就消失了(例如res.send("<!doctype html><html><head /><body><h1>hello</h1></body></html>");.

我在这里错过了什么吗?还是有已知问题?或者它可能是一个明确的问题?

我在节点上运行v8.4.0,这是我的依赖项(我正在使用react-starter-kit):

"dependencies": {
    "@babel/polyfill": "^7.0.0-beta.44",
    "bluebird": "^3.5.1",
    "body-parser": "^1.18.2",
    "classnames": "^2.2.5",
    "cookie-parser": "^1.4.3",
    "core-js": "^2.5.4",
    "express": "^4.17.1",
    "express-http-proxy": "^1.1.0",
    "express-jwt": "^5.3.1",
    "history": "^4.7.2",
    "intl": "^1.2.5",
    "isomorphic-fetch": "^2.2.1",
    "isomorphic-style-loader": "^4.0.0",
    "node-fetch": "^2.1.2",
    "normalize.css": "^8.0.0",
    "pretty-error": "^2.1.1",
    "prop-types": "^15.6.1",
    "react": "^16.9.0",
    "react-dom": "^16.9.0",
    "react-helmet": "^5.2.0",
    "react-slick": "0.23.1",
    "serialize-javascript": "^1.4.0",
    "smoothscroll-polyfill": "^0.4.4",
    "source-map-support": "^0.5.4",
    "universal-router": "^6.0.0",
    "whatwg-fetch": "^2.0.4"
  },

标签: node.jsreactjsexpressmemory-leaksgarbage-collection

解决方案


我做了一些更多的测试,发现当我在development(调试)模式下构建应用程序时泄漏已经消失了。production经过一番调查,我发现这个 babel 插件仅在模式下加载到我的 webpack 文件中: https ://babeljs.io/docs/en/babel-plugin-transform-react-constant-elements

删除该插件后,内存泄漏就消失了。我猜这个插件应该只为客户端应用程序加载,因为插件的作用是

“将 React JSX 元素视为值类型并将它们提升到最高范围”

当您关闭页面/选项卡时,客户端应用程序上的范围已经消失,这没什么大不了的,但在节点服务器上,它会导致内存随着每个请求而累积。


推荐阅读