6

I am running a react app that renders on a nodejs server. I saw after a few days that the memory of the nodeJs process increased depending on the number of visitors. Everytime I reloaded the page, the memory usage increased a bit. At the beginning the process takes about ~60MB memory. After a few days it increased to ~450MB. For now I am restarting the node-process to solve this problem.

I think it is a problem with my React setup. Even if I only render a very small App I get the leak. Example:

// 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);
  }
});

To check the memoryleak I am forcing garbage collection every 3 seconds and print out the memory usage while using autocannon to make a few thousand requests. This gives the following result:

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.

The memory usage of course increases highly when I render the "real" React application. The following screenshot shows the difference between first time starting the app and one single request to the page:

comparison

If I only return a string without React's renderToStaticMarkup the problem is gone (e.g. res.send("<!doctype html><html><head /><body><h1>hello</h1></body></html>");.

Am I missing something here? Or is there a known problem? Or is it maybe an express issue?

I am running on node v8.4.0 and here are my dependencies (I am using 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"
  },

1 Answer 1

3

I did some more testing and found out that the leak was gone when I build the app in development (debug) mode. After some investigation I found this babel plugin beeing loaded in my webpack file only in production mode: https://babeljs.io/docs/en/babel-plugin-transform-react-constant-elements

After I removed that plugin, the memory leak was gone. I guess this plugin should only be loaded for the client-app, because what the plugin does is

"Treat React JSX elements as value types and hoist them to the highest scope"

As the scope is gone on a client app when you close the page/tab it is not that big deal, but on the node server it causes the memory to build up with each request.

Sign up to request clarification or add additional context in comments.

2 Comments

How did you remove this plugin ? it is an indirect dependency of react-scripts rite ?
hey @lime_pal this answer is 4 years old, I am not quite sure if this still suits. Maybe take a look at your code and check if there are any global variables that may mess stuff up. Or use developer.chrome.com/docs/devtools/performance the performance tool from chrome to see what actually causes the memory leak.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.