styled-components: SSR Memory Leak SC - 3.2.3

Environment

System:

  • OS: Linux 3.13
  • CPU: x64 Intel® Xeon® CPU E5-2666 v3 @ 2.90GHz
  • Free Memory: 723.59 MB
  • Total Memory: 7.30 GB
  • Shell: ¯_(ツ)_/¯

Binaries:

  • Node: 8.4.0
  • Yarn: 0.27.5
  • npm: 5.3.0
  • Watchman: Not Found

npmPackages:

babel-plugin-styled-components:

  • wanted: ~1.5.0
  • installed: 1.5.0

styled-components:

  • wanted: 3.2.3
  • installed: 3.2.3

Reproduction

Reproduction is a little hard. We have relatively large Next.js application with a large amount of styles. Running here - https://weedmaps.com/deals. This behavior doesn’t seem to be present on smaller example applications

Steps to reproduce

Using the same method for re-hrydration as the next.js examples -

  static async getInitialProps(context) {
    const { renderPage, req } = context;
    const sheet = new ServerStyleSheet();
    const page = renderPage(App => props =>
      sheet.collectStyles(<App {...props} />),
    );
    // Flush Styled Components
    const styleTags = sheet.getStyleElement();

    return {
      ...page,
      styleTags,
    };
  }

We are seeing accumulation of tags in the tagMap in the master StyleSheet. Here is an snap of the captured heap.

screen shot 2018-03-20 at 11 07 02 am screen shot 2018-03-20 at 11 06 56 am

I can provide the actual Heapdump if it is useful, but I don’t want to attach it here. This leak is slower in 3.2.3, after the fixes were applied, but it is still present

Expected Behavior

The master StyleSheet should not retain tags across requests.

Actual Behavior

Seeing slow and steady memory leak in the StyleSheet.master.tagMap. After a time we are seeing hundreds of thousands of retained tags.

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 1
  • Comments: 20 (6 by maintainers)

Commits related to this issue

Most upvoted comments

@kitten I have tracked this down and we are creating dynamic components at runtime. This is causing the server render to not be deterministic across page refreshes. I would imagine this is causing the tagMap to grow indefinitely as well. Closing this, as we can fix on our side. Thanks for your work and patience

We ran into similar issues were our server memory kept increasing over time, which caused several pods to crash but also performance issues : as stated above, response time is directly linked to the StyleSheet (tagMap) size.

Here is the problem :

styled-components is responsible for calling sheet.complete() when the rendering part is done, cleaning the memory up.

Nevertheless, if something bad happens during the rendering process - and bad things always happen - exceptions may be thrown, and they get nicely caught by the server which will log stuff and send a 4xx or 5xx HTTP error back… In that case, sheet.complete() is not called, resulting in a potentially huge leak.

This is how we fixed it, I think you should update all SSR examples accordingly :

    const sheet = new ServerStyleSheet();
    try {
      const page = await renderPage((App) => (props) => sheet.collectStyles(<App {...props} />));
      const styleTags = sheet.getStyleElement();
      return {
        assets, data, ...page, styleTags,
      };
    } catch (e) {
      sheet.complete();
      throw e;
    }
  }```

Hope this helps.

@maxparelius yes it would be a Styled Component that is created inside something that is called dynamically (like a React Component) e.g.


export class SomeComponent extends React.Component {
  render() {
    // defined on every render
    const Div = styled.div``;
    return <Div>Hello</Div>;
  }
}

vs.

// defined once at module creation time
const Div = styled.div``;

export class SomeComponent extends React.Component {
  render() {
    return <Div>Hello</Div>;
  }
}

@bringking regarding that code snippet, what is it being used for, since I thought we’re talking about an SSR leak. Maybe I misunderstood parts of your issue description? 😅

Btw, HTMLTag#sheet won’t work on all browsers; Not related but since I’m already seeing this, I might as well point it out 😄 https://github.com/styled-components/styled-components/blob/master/src/utils/insertRuleHelpers.js#L7-L21