freeCodeCamp/server/boot/a-react.js

91 lines
2.3 KiB
JavaScript
Raw Normal View History

import React from 'react';
2015-09-14 01:12:22 +00:00
import { RoutingContext } from 'react-router';
import Fetchr from 'fetchr';
2015-09-14 01:12:22 +00:00
import { createLocation } from 'history';
2015-06-29 19:01:56 +00:00
import debugFactory from 'debug';
2015-12-23 03:28:07 +00:00
import { dehydrate } from 'thundercats';
import { renderToString$ } from 'thundercats-react';
2016-01-06 17:33:55 +00:00
import app$ from '../../common/app';
2015-06-29 16:50:25 +00:00
const debug = debugFactory('freecc: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 = [
2015-08-31 16:53:25 +00:00
'/jobs',
2015-12-23 03:28:07 +00:00
'/jobs/*',
2015-10-20 06:16:56 +00:00
'/hikes',
'/hikes/*'
];
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) {
const services = new Fetchr({ req });
2015-09-14 01:12:22 +00:00
const location = createLocation(req.path);
2015-06-29 16:50:25 +00:00
// returns a router wrapped app
2015-09-14 01:12:22 +00:00
app$({ location })
2015-06-29 16:50:25 +00:00
// if react-router does not find a route send down the chain
2015-10-20 06:16:56 +00:00
.filter(function({ props }) {
2015-09-14 01:12:22 +00:00
if (!props) {
debug('react tried to find %s but got 404', location.pathname);
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
})
2015-09-14 01:12:22 +00:00
.flatMap(function({ props, AppCat }) {
2015-12-23 03:28:07 +00:00
const cat = AppCat(null, services);
debug('render react markup and pre-fetch data');
2016-01-04 03:40:49 +00:00
const store = cat.getStore('appStore');
// primes store to observe action changes
// cleaned up by cat.dispose further down
store.subscribe(() => {});
2015-12-23 03:28:07 +00:00
return renderToString$(
cat,
2015-09-14 01:12:22 +00:00
React.createElement(RoutingContext, props)
2015-12-23 03:28:07 +00:00
)
.flatMap(
dehydrate(cat),
({ markup }, data) => ({ markup, data, cat })
);
2015-06-29 16:50:25 +00:00
})
2015-12-23 03:28:07 +00:00
.flatMap(function({ data, markup, cat }) {
debug('react markup rendered, data fetched');
cat.dispose();
const { title } = data.AppStore;
res.expose(data, 'data');
return res.render$(
'layout-react',
{ markup, title }
);
2015-06-29 16:50:25 +00:00
})
.subscribe(
function(markup) {
2015-12-23 03:28:07 +00:00
debug('html rendered and ready to send');
2015-06-29 16:50:25 +00:00
res.send(markup);
},
next
);
}
2015-06-29 19:01:56 +00:00
}