The server will look very familiar to the client-side version. The difference
being, Resolver.resolve
will async render the application, fetch all data, &
return a <Resolved />
component ready for React.render
, as well as the
data
needed to bootstrap the client:
import { renderToString } from "react-dom/server";
import { match, RouterContext } from "react-router";
import { Resolver } from "react-resolver";
match({ routes, location }, (error, redirectLocation, renderProps) => {
Resolver
.resolve(() => <RouterContext {...renderProps} />) // Pass a render function for context!
.then(({ Resolved, data }) => {
res.send(`
<!DOCTYPE html>
<html>
<body>
<div id="app">${renderToString(<Resolved />)}</div>
<script>window.__REACT_RESOLVER_PAYLOAD__ = ${JSON.stringify(data)}</script>
<script src="/client.min.js" async defer></script>
</body>
</html>
`)
})
.catch((error) => res.status(500).send(error)) // Just in case!
;
});
Notice the presence of window.__REACT_RESOLVER_PAYLOAD__
. This is
the object that Resolver.render
on the client will anticipate & leverage
for bootstrapping the client.
Enjoy writing universal apps with clarity around data requirements!