You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
importexpressfrom'express';importReactDOMServerfrom'react-dom/server';import{RelayNetworkLayer}from'react-relay-network-modern';importRelayServerSSRfrom'react-relay-network-modern-ssr/lib/server';importserializefrom'serialize-javascript';import{Environment,Network,RecordSource,Store}from'relay-runtime';importschemafrom'./schema';constapp=express();app.get('/*',async(req,res,next)=>{constrelayServerSSR=newRelayServerSSR();constnetwork=newRelayNetworkLayer([// There are three possible ways relayServerSSR.getMiddleware() can be used;// choose the one that best matches your context:// By default, if called without arguments it will use `fetch` under the hood// to request data. (See https://github.com/relay-tools/react-relay-network-modern// for more info)relayServerSSR.getMiddleware(),// OR, you can directly pass in a GraphQL schema, which will use `graphql`// from `graphql-js` to request datarelayServerSSR.getMiddleware({
schema,contextValue: {},}),// OR, if you need to prepare context in async mode, `getMiddleware` will also// accept a function:relayServerSSR.getMiddleware(async()=>({
schema,contextValue: awaitprepareGraphQLContext(req),})),]);constsource=newRecordSource();conststore=newStore(source);constrelayEnvironment=newEnvironment({ network, store });// Once the RelayEnvironment is instantiated, two App renders need to be made in// order to prepare data for hydration:// First, kick off Relay requests with an initial renderReactDOMServer.renderToString(<ApprelayEnvironment={relayEnvironment}/>);// Second, await while all data were recieved from graphql serverconstrelayData=awaitrelayServerSSR.getCache();// Third, render the app a second time now that the Relay store has been primed// and send HTML and bootstrap data to the client for rehydration.constappHtml=ReactDOMServer.renderToString(<ApprelayEnvironment={newEnvironment({network: Network.create(()=>relayData[0][1]),
store,})}/>);try{res.status(200).send(` <html> <body> <div id="react-root">${appHtml}</div> <script> window.__RELAY_BOOTSTRAP_DATA__ = ${serialize(relayData)}; </script> <script src="/assets/bundle.js"></script> </body> </html> `);}catch(error){console.log('(server.js) Error: ',error);next(error);}}app.listen(3000);// simple example, how to asynchronously prepare data for GraphQL contextasyncfunctionprepareGraphQLContext(req){const{ userToken }=req.cookies;constuser=userToken ? (awaitsomehowLoadUser(userToken)) : undefined;return{
user,
req,}}
Client
import{RelayNetworkLayer}from'react-relay-network-modern';importRelayClientSSRfrom'react-relay-network-modern-ssr/lib/client';constrelayClientSSR=newRelayClientSSR(window.__RELAY_BOOTSTRAP_DATA__);constnetwork=newRelayNetworkLayer([relayClientSSR.getMiddleware({lookup: true// Will preserve cache rather than purge after mount.}),]);
...
ReactDOM.render(<QueryRendererdataFrom="STORE_THEN_NETWORK"// Required for Relay 1.5environment={environment}.../>,document.getElementById('react-root'));
Contribute
I actively welcome pull requests with code and doc fixes.