Render React isomorphically using react-router in hapi using a data store of your choice (e.g. MobX).
npm install hapi-react-ssr vision --save
The plugin accepts the following options
:
routes
: The routes defined by react-router
as a manifest.getInitialContext
: A function to initialise your store(s) and eventually pass on to the client as initial state.bootstrapAction
: The static function to call for server-side rendering from all React components that define it.rootElement
: The root React element.template
: The template file /path/name
to use for rendering the view. Internally uses reply.view
provided by vision
. The templating engine to use is up to you. See vision docs.visionOptions
: The options to pass on to vision
.params
: Additional params to pass to the template context object. componentRenderedToString
and context
are reserved for internal use (see below).renderToStaticMarkup
: Choose whether to renderToStaticMarkup
(value true
) instead of renderToString
(value false
, default).contextAsProps
: Choose whether to spread out the context object as separate props on the root element (value true
) or to keep the context inside a single context
prop (value false
, default).Define your routes as a PlainRoute:
// routes.js
import App from './components/App';
import Homepage from './components/Homepage';
const routes = [
{
path: '/',
component: App,
indexRoute: { component: Homepage },
childRoutes: [...]
}
];
export default routes;
// server.js
import HapiReactSSR from "hapi-react-ssr";
import Vision from "vision";
import { Provider } from "mobx-react"; // or use any other Provider to pass context down to all children
...
const plugins = [
Vision,
{
register: HapiReactSSR,
options: {
routes,
getInitialContext: () => {
return {
state: new AppState(),
store: new AppStore()
}
},
bootstrapAction: 'fetchData',
rootElement: Provider,
template: './src/server/index',
params: {
env: process.env.NODE_ENV
}
}
},
// other plugins
];
server.register(plugins, (err) => {});
componentRenderedToString
prop to store the server-side rendered root React component, and context
to store the computed initial state from your data store. Include them appropriately in your template.{{! handlebars example }}
<html>
<body>
<div id="react-root">{{{ componentRenderedToString }}}</div>
<script type="application/javascript">
window.__INITIAL_STATE__ = {{{ context }}};
</script>
</body>
</html>
MIT