On changes to the react bundle webpack will store the current redux state in localStorage, waits (to allow the server to restart) then refreshes the page. On page load, it checks if it has state stored and loads it into the app.
81 lines
2.1 KiB
JavaScript
81 lines
2.1 KiB
JavaScript
import React from 'react';
|
|
import { RouterContext } from 'react-router';
|
|
import debug from 'debug';
|
|
|
|
import renderToString from '../../common/app/utils/render-to-string';
|
|
import provideStore from '../../common/app/provide-store';
|
|
|
|
import createApp from '../../common/app';
|
|
|
|
const log = debug('fcc:react-server');
|
|
|
|
// add routes here as they slowly get reactified
|
|
// remove their individual controllers
|
|
const routes = [
|
|
'/videos',
|
|
'/videos/*',
|
|
'/challenges',
|
|
'/map'
|
|
];
|
|
|
|
const devRoutes = [];
|
|
|
|
export default function reactSubRouter(app) {
|
|
var router = app.loopback.Router();
|
|
|
|
// These routes are in production
|
|
routes.forEach((route) => {
|
|
router.get(route, serveReactApp);
|
|
});
|
|
|
|
if (process.env.NODE_ENV === 'development') {
|
|
devRoutes.forEach(function(route) {
|
|
router.get(route, serveReactApp);
|
|
});
|
|
}
|
|
|
|
app.use(router);
|
|
|
|
function serveReactApp(req, res, next) {
|
|
const serviceOptions = { req };
|
|
createApp({
|
|
serviceOptions,
|
|
location: req.path
|
|
})
|
|
// if react-router does not find a route send down the chain
|
|
.filter(({ redirect, props }) => {
|
|
if (!props && redirect) {
|
|
res.redirect(redirect.pathname + redirect.search);
|
|
}
|
|
if (!props) {
|
|
log(`react tried to find ${req.path} but got 404`);
|
|
return next();
|
|
}
|
|
return !!props;
|
|
})
|
|
.flatMap(({ props, store }) => {
|
|
log('render react markup and pre-fetch data');
|
|
|
|
return renderToString(
|
|
provideStore(React.createElement(RouterContext, props), store)
|
|
)
|
|
.map(({ markup }) => ({ markup, store }));
|
|
})
|
|
.flatMap(function({ markup, store }) {
|
|
log('react markup rendered, data fetched');
|
|
const state = store.getState();
|
|
const { title } = state.app.title;
|
|
res.expose(state, 'data');
|
|
return res.render$(
|
|
'layout-react',
|
|
{ markup, title }
|
|
);
|
|
})
|
|
.doOnNext(markup => res.send(markup))
|
|
.subscribe(
|
|
() => log('html rendered and ready to send'),
|
|
next
|
|
);
|
|
}
|
|
}
|