Skip to content

Instantly share code, notes, and snippets.

@grabbou
Created July 21, 2015 06:16
Show Gist options
  • Save grabbou/d4b2340fd4953e22f0d1 to your computer and use it in GitHub Desktop.
Save grabbou/d4b2340fd4953e22f0d1 to your computer and use it in GitHub Desktop.
import DocumentTitle from 'react-document-title';
import Html from './html.react';
import Promise from 'bluebird';
import React from 'react';
import Router from 'react-router';
import config from '../config';
import immutable from 'immutable';
import initialState from '../initialstate';
import routes from '../../client/routes';
import stateMerger from '../lib/merger';
export default function render(req, res, ...customStates) {
const appState = immutable.fromJS(initialState).mergeWith(stateMerger, ...customStates).toJS();
return renderPage(req, res, appState);
}
function renderPage(req, res, appState) {
return new Promise((resolve, reject) => {
const router = Router.create({
routes,
location: req.originalUrl,
onError: reject,
onAbort: (abortReason) => {
// Some requireAuth higher order component requested redirect.
if (abortReason.constructor.name === 'Redirect') {
const {to, params, query} = abortReason;
const path = router.makePath(to, params, query);
res.redirect(path);
resolve();
return;
}
reject(abortReason);
}
});
router.run((Handler, routerState) => {
const html = getPageHtml(Handler, appState, {hostname: req.hostname}); //options parameter
const notFound = routerState.routes.some(route => route.name === 'not-found');
const status = notFound ? 404 : 200;
res.status(status).send(html);
resolve();
});
});
}
function getPageHtml(Handler, appState, {hostname}) {
const appHtml = `<div id="app">${
React.renderToString(<Handler initialState={appState} />)
}</div>`;
const appScriptSrc = config.isProduction
? '/build/app.js?v=' + config.version
: `//${hostname}/build/app.js`; // render hostname here
let scriptHtml = `
<script>
(function() {
window._appState = ${JSON.stringify(appState)};
var app = document.createElement('script'); app.type = 'text/javascript'; app.async = true;
var src = '${appScriptSrc}';
// IE<11 and Safari need Intl polyfill.
if (!window.Intl) src = src.replace('.js', 'intl.js');
app.src = src;
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(app, s);
})();
</script>`;
if (config.isProduction && config.googleAnalyticsId !== 'UA-XXXXXXX-X')
scriptHtml += `
<script>
(function(b,o,i,l,e,r){b.GoogleAnalyticsObject=l;b[l]||(b[l]=
function(){(b[l].q=b[l].q||[]).push(arguments)});b[l].l=+new Date;
e=o.createElement(i);r=o.getElementsByTagName(i)[0];
e.src='//www.google-analytics.com/analytics.js';
r.parentNode.insertBefore(e,r)}(window,document,'script','ga'));
ga('create','${config.googleAnalyticsId}');ga('send','pageview');
</script>`;
const title = DocumentTitle.rewind();
return '<!DOCTYPE html>' + React.renderToStaticMarkup(
<Html
bodyHtml={appHtml + scriptHtml}
isProduction={config.isProduction}
title={title}
version={config.version}
/>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment