2015-07-04 00:40:12 +00:00
|
|
|
import React from 'react';
|
2016-03-03 03:45:54 +00:00
|
|
|
import { RouterContext } from 'react-router';
|
2016-01-27 19:34:44 +00:00
|
|
|
import debug from 'debug';
|
|
|
|
|
2016-05-04 23:46:19 +00:00
|
|
|
import { renderToString } from 'redux-epic';
|
2016-01-27 19:34:44 +00:00
|
|
|
import provideStore from '../../common/app/provide-store';
|
2015-12-23 03:28:07 +00:00
|
|
|
|
2016-03-15 00:22:56 +00:00
|
|
|
import createApp from '../../common/app';
|
2015-06-29 16:50:25 +00:00
|
|
|
|
2016-01-27 19:34:44 +00:00
|
|
|
const log = debug('fcc:react-server');
|
2015-07-01 22:14:10 +00:00
|
|
|
|
|
|
|
// add routes here as they slowly get reactified
|
|
|
|
// remove their individual controllers
|
2015-06-29 19:01:56 +00:00
|
|
|
const routes = [
|
2016-02-02 10:00:48 +00:00
|
|
|
'/videos',
|
2016-03-06 05:06:04 +00:00
|
|
|
'/videos/*',
|
2016-03-15 00:22:56 +00:00
|
|
|
'/challenges',
|
2016-04-19 01:58:29 +00:00
|
|
|
'/challenges/*',
|
2016-03-15 00:22:56 +00:00
|
|
|
'/map'
|
2015-10-20 06:16:56 +00:00
|
|
|
];
|
|
|
|
|
2015-12-23 03:28:07 +00:00
|
|
|
const devRoutes = [];
|
|
|
|
|
2015-06-29 19:01:56 +00:00
|
|
|
export default function reactSubRouter(app) {
|
2015-07-03 06:44:34 +00:00
|
|
|
var router = app.loopback.Router();
|
2015-06-29 16:50:25 +00:00
|
|
|
|
2015-10-30 00:55:42 +00:00
|
|
|
// These routes are in production
|
|
|
|
routes.forEach((route) => {
|
|
|
|
router.get(route, serveReactApp);
|
|
|
|
});
|
2015-10-20 06:16:56 +00:00
|
|
|
|
2015-08-13 18:09:34 +00:00
|
|
|
if (process.env.NODE_ENV === 'development') {
|
2015-10-20 06:16:56 +00:00
|
|
|
devRoutes.forEach(function(route) {
|
2015-08-13 18:09:34 +00:00
|
|
|
router.get(route, serveReactApp);
|
|
|
|
});
|
|
|
|
}
|
2015-06-29 16:50:25 +00:00
|
|
|
|
|
|
|
app.use(router);
|
|
|
|
|
|
|
|
function serveReactApp(req, res, next) {
|
2016-01-27 19:34:44 +00:00
|
|
|
const serviceOptions = { req };
|
2016-03-15 00:22:56 +00:00
|
|
|
createApp({
|
|
|
|
serviceOptions,
|
|
|
|
location: req.path
|
2016-01-27 19:34:44 +00:00
|
|
|
})
|
2015-06-29 16:50:25 +00:00
|
|
|
// if react-router does not find a route send down the chain
|
2016-03-03 03:45:54 +00:00
|
|
|
.filter(({ redirect, props }) => {
|
|
|
|
if (!props && redirect) {
|
2016-04-19 01:58:29 +00:00
|
|
|
log('react router found a redirect');
|
|
|
|
return res.redirect(redirect.pathname + redirect.search);
|
2016-03-03 03:45:54 +00:00
|
|
|
}
|
2015-09-14 01:12:22 +00:00
|
|
|
if (!props) {
|
2016-03-15 00:22:56 +00:00
|
|
|
log(`react tried to find ${req.path} but got 404`);
|
2015-07-04 04:46:22 +00:00
|
|
|
return next();
|
2015-06-29 16:50:25 +00:00
|
|
|
}
|
2015-09-14 01:12:22 +00:00
|
|
|
return !!props;
|
2015-06-29 16:50:25 +00:00
|
|
|
})
|
2016-04-25 04:54:48 +00:00
|
|
|
.flatMap(({ props, store, epic }) => {
|
2016-01-27 19:34:44 +00:00
|
|
|
log('render react markup and pre-fetch data');
|
2016-01-04 03:40:49 +00:00
|
|
|
|
2016-01-27 19:34:44 +00:00
|
|
|
return renderToString(
|
2016-04-25 04:54:48 +00:00
|
|
|
provideStore(React.createElement(RouterContext, props), store),
|
|
|
|
epic
|
2015-12-23 03:28:07 +00:00
|
|
|
)
|
2016-04-25 04:54:48 +00:00
|
|
|
.map(({ markup }) => ({ markup, store, epic }));
|
2015-06-29 16:50:25 +00:00
|
|
|
})
|
2016-06-09 23:02:51 +00:00
|
|
|
.filter(({ store, epic }) => {
|
|
|
|
const { delayedRedirect } = store.getState().app;
|
|
|
|
if (delayedRedirect) {
|
|
|
|
res.redirect(delayedRedirect);
|
|
|
|
epic.dispose();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
})
|
2016-04-25 04:54:48 +00:00
|
|
|
.flatMap(function({ markup, store, epic }) {
|
2016-01-27 19:34:44 +00:00
|
|
|
log('react markup rendered, data fetched');
|
|
|
|
const state = store.getState();
|
2016-06-09 23:02:51 +00:00
|
|
|
const { title } = state.app;
|
2016-04-25 04:54:48 +00:00
|
|
|
epic.dispose();
|
2016-01-27 19:34:44 +00:00
|
|
|
res.expose(state, 'data');
|
2015-07-29 17:16:48 +00:00
|
|
|
return res.render$(
|
|
|
|
'layout-react',
|
|
|
|
{ markup, title }
|
|
|
|
);
|
2015-06-29 16:50:25 +00:00
|
|
|
})
|
2016-01-27 19:34:44 +00:00
|
|
|
.doOnNext(markup => res.send(markup))
|
2015-06-29 16:50:25 +00:00
|
|
|
.subscribe(
|
2016-01-27 19:34:44 +00:00
|
|
|
() => log('html rendered and ready to send'),
|
2015-06-29 16:50:25 +00:00
|
|
|
next
|
|
|
|
);
|
|
|
|
}
|
2015-06-29 19:01:56 +00:00
|
|
|
}
|