Using renderToNodeStream with react-rails / webpacker

Hi all, I’m working on an app using react-rails / webpacker, with a rails server and React frontend. On top of this, we are also using styled-components and have overwritten the existing ReactRailsUJS.serverRender method in the app/javascript/packs/server_rendering.js file to account for styled components as the following (see https://github.com/reactjs/react-rails/issues/864#issue-291728172 for more info):

// server_rendering.js

import React from 'react';
import ReactDOMServer from 'react-dom/server';
import { ServerStyleSheet } from 'styled-components';

const componentRequireContext = require.context('components', true);
const ReactRailsUJS = require('react_ujs');
ReactRailsUJS.useContext(componentRequireContext);

ReactRailsUJS.serverRender = function(renderFunction, componentName, props) {
  const ComponentConstructor = this.getConstructor(componentName);
  const stylesheet = new ServerStyleSheet();
  const wrappedElement = stylesheet.collectStyles(
    <ComponentConstructor {...props} />
  );
  const text = ReactDOMServer[renderFunction](wrappedElement);

  // prepend the style tags to the component HTML
  return `${stylesheet.getStyleTags()}${text}`;
}

This all works well, since the renderFunction param passed as the first argument of the ReactRailsUJS.serverRender function is react-dom/server’s renderToString method. However, we would like to update the application to use the renderToNodeStream method for rendering our react components, which is what brings me to this discussion.

I was wondering if there is anyone out there with some more in depth knowledge of how these libraries work at a more core level to help me figure out how we might be able to use renderToNodeStream, given our application setup.

Any advice / direction is appreciated, and I can provide additional information if necessary. Thank you for the consideration and help!

Hi @Kristine_Alnes!

Why do you want to use renderToNodeStream? It returns the same HTML as renderToString, but you need to be ready to handle a readableStream. I don’t think any Rails server will handle that. The Rails server needs a string of HTML to place on the view.

Maybe what you’re looking for is a Node rendering server rather than ExecJS? The difference is that ExecJS is JavaScript embedded in Ruby rather than a separate Node process. Some of the CSS-in-JS libraries, such as Emotion have support for SSR, but they don’t work with ExecJS within Rails. However, it does work perfectly with the React on Rails Pro Node Rendering Server. Loadable Components is another example of a library that works out-of-the-box with a Node server, but not ExecJS.

I’d encourage you to consider signing up for React on Rails Pro support. It’s not just software, but also a private Slack channel that includes an hour of support per month for issues like this.

Also, if you’d like to switch from react-rails to react_on_rails, it’s pretty easy.

I’d encourage you to join our community Slack. Here’s the invite link.

Thanks,

Justin