Skip to content

Async safe SSR #389

Closed
Closed
@a-ignatov-parc

Description

@a-ignatov-parc

styled-jsx is awesome but it handles style generation during SSR in a very unsafe way. It uses side effects that can lead to style collision when user will try to render something async (say hello to renderToStream and react@17 in future).

So I want to propose a better solution to this problem.

Instead of using flush from styled-jsx/server and internal stylesheet singleton we need to be able to provide custom styleSheetRegistry to controlled virtual tree.

This can be done with react.js context.

// server.js
import { StyleSheetRegistryProvider, StyleSheetRegistry } from 'styled-jsx/server';

const registry = new StyleSheetRegistry();

const app = ReactDOM.renderToString((
  <StyleSheetRegistryProvider registry={registry}>
    <App />
  </StyleSheetRegistryProvider>
));

const styles = registry.toHTML(); // or .toComponents()

const html = `
  <!doctype html>
  <html>
    <head>${styles}</head>
    <body>
      <div id="root">${app}</div>
    </body>
  </html>
`;

More details:

  • If no registry is provided to StyleSheetRegistryProvider then the default one will be used. This can be useful on the client side.
  • If no StyleSheetRegistryProvider is provided then <style jsx /> must be noop. This will be useful when you need to do something that is not related to rendering markup. Something like data resolution for the final render when you don't want to do extra work that you don't need.
  • StyleSheetRegistryProvider can be combined but children provider should not share its styles with a parent provider.
  • StyleSheetRegistryProvider can be used as config for handled styles.

@giuseppeg what do you think?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions