Server-render renderToNodeStream with react-helmet-async

Hello there,

currently my code on the server looks like this:

onPageLoad((sink) => {
  const store = const store = createStore();
  const appJsx = (
    <HelmetProvider context={helmetContext}>
      <Provider store={store}>
        <ReduxIntlProvider>
          <StaticRouter location={sink.request.url} context={context}>
            <App />
          </StaticRouter>
        </ReduxIntlProvider>
      </Provider>
    </HelmetProvider>);

  sink.renderIntoElementById('root', renderToString(appJsx));

  const { helmet } = helmetContext;
  sink.appendToHead(helmet.meta.toString());
  sink.appendToHead(helmet.link.toString());
  sink.appendToHead(helmet.title.toString());

  sink.appendToBody(`
    <script>
      window.__PRELOADED_STATE__ = ${JSON.stringify(store.getState()).replace(/</g, '\\u003c')}
    </script>
  `);
}

I would like to use renderToNodeStream in order to improve TTFB. The example at https://github.com/staylor/react-helmet-async is also not that clear to me. I’m also not familiar what server-render does with the sink object behind the scene.

Has someone a working example or a suggestion how this might work?

Best regards,

HK

The problem with helmet and renderToNodeStream is that even with helmet-async, you still need to render the complete React tree first, to get any kind of output, and if rendering to a node stream, by that time you cannot set the head tags using sink.appendToHead, because those will already have been sent to the client. This means you may have to use a caching solution, which sounds like a headache, or find some other way to load the react tree to grab Helmet data. I don’t know what kind of impact on TTFB that would have, whether or not it defeats the point of using renderToNodeStream, since I haven’t measured any of this.

I do know that a bunch of apollo SSR examples I’ve seen do exactly this when rendering on the server, since it has the same requirement. Maybe look into how Apollo does that, for some ideas.

1 Like

When a full render is required prior to sending first data to the client, the effect on TTFB might be minimal. If someone has experience, I would be glad to hear some feedback.

Thanks for the suggestion with Apollo. I will look into this.

Apollo does some thing where it “parses” the react tree - but maybe saves some time in actual rendering? I’m not really sure…