You’ll need to configure
babel-preset-fbjs to hoist its require calls — but only on the server.
We’ll get into more detail, but first, this graph illustrates why you need to do this:
The vertical line represents a deployment of a server-side optimized Relay. The light blue is the time spent in the node.js process, which is almost exclusively time spent in
ReactDOMServer.renderToString. The dramatic drop in time spent in the node.js process is obvious. It went from an average of 110ms per request to 55ms (roughly). The performance difference is even more remarkable in synthetic benchmarks.
Client optimizations harm server-side rendering
The issue was introduced way back in Relay 0.9. The Relay team added an optimization to their babel configuration that improves performance on mobile devices. Unfortunately, it harms the server-side use-case. Since there are workarounds to solve the issue, the Relay team felt that it wasn’t something they needed to focus on.
At 1stdibs, we ran into this issue a little over a year ago and we’re working with the Relay team to come up with a solution that works for everyone. But in the meantime, here’s what we did to get around it.
The core of the problem is the configuration of
inlineRequires option is set to true, which causes module require calls to be inlined. The fix is to have a build that sets the that option to false.
So, we forked Relay, updated the
inlineRequires option to false, and published our fork to our private registry.
In our projects, we use the
babel-plugin-module-resolver to alias
react-relay/compat to the server-optimized version — but only in the server babel configuration (that last part is important since the server optimization is a de-optimization on the client).
The workaround is fairly simple, which is why the Relay team hasn’t offered a solution. But, you do need to maintain the fork when you upgrade and ensure that your projects are all configured to use the server-optimized fork on the server.