sevenLee
5/30/2016 - 5:12 PM

Isomorphic server.js

Isomorphic server.js

import express                  from 'express';
import bodyParser               from 'body-parser';
import path                     from 'path';
import session                  from 'express-session';
import axios                    from 'axios';
import React                    from 'react';
import { renderToString }       from 'react-dom/server'
import { RouterContext, match } from 'react-router';
import { Provider }             from 'react-redux';
import routes                   from 'routes';
import * as reducers            from 'redux/reducers';
import favicon                  from 'serve-favicon';
import promiseMiddleware        from 'lib/promiseMiddleware';
import fetchComponentData       from 'lib/fetchComponentData';
import { createStore,
         combineReducers,
         applyMiddleware,
         compose }              from 'redux';
import apiRouter                from './api';
import config                   from './config';
import Html                     from './helpers/Html';


Object.assign = require('object-assign');

const app = express();

if (__DEVELOPMENT__) {
  require('../../webpack/webpack.dev').default(app);
}

app.use(favicon(path.join(__dirname, '..', '..', 'static', 'favicon.ico')));

app.use(express.static(path.join(__dirname, '..', '..', 'static'), { maxAge: '7 days' }));

app.use(bodyParser.urlencoded({
  extended: true
}));

app.use(bodyParser.json());

app.use(config.apiBaseUrl, apiRouter);

app.use((req, res) => {
  if (__DEVELOPMENT__) {
    global.webpackIsomorphicTools.refresh();
  }

  res.contentType('text/html');

  const isoAssets = global.webpackIsomorphicTools.assets();
   // isoAssets is the object I would like to pass in redux store

  const reducer  = combineReducers(reducers);
  const store    = applyMiddleware(promiseMiddleware)(createStore)(reducer);

  match({routes, location: req.url}, (err, redirectLocation, renderProps) => {
    if (err) {
      console.error(err);
      return res.status(500).end('Internal server error');
    }
    if (redirectLocation) {
      return res.redirect(302, redirectLocation.pathname + redirectLocation.search);
    }

    if (!renderProps)
      return res.status(404).end('Not found');

    function renderView(errOrArrayFromPromiseAll) {
      const createElement = (Component, props) => (
        <Component
          {...props}
          radiumConfig={{ userAgent: req.headers['user-agent'] }}
        />
      );
      
      //pass into redux state..
      const InitialView = (
        <Provider store={store}>
          <RouterContext
            {...renderProps}
            createElement={createElement} />
        </Provider>
      );

      const componentHTML = renderToString(InitialView);

      const HTML = '<!doctype html>\n' +
        renderToString(<Html assets={global.webpackIsomorphicTools.assets()} componentHtml={componentHTML} store={store}/>);

      return HTML;
    }

    fetchComponentData(store.dispatch, renderProps.components, renderProps.params)
      .then(renderView)
      .then(html => res.end(html))
      .catch(err => res.end(err.message));
  });
});


export default app;
import 'babel-polyfill';
import React                    from 'react';
import { render }               from 'react-dom';
import {
  Router,
  browserHistory,
}                               from 'react-router';
import { createHistory }        from 'history'
import { Provider }             from 'react-redux';
import * as reducers            from 'redux/reducers';
import routes                   from 'routes';
import axios                    from 'axios';
import promiseMiddleware        from 'lib/promiseMiddleware';
import immutifyState            from 'lib/immutifyState';
import { createStore,
         combineReducers,
         applyMiddleware,
         compose }              from 'redux';


const initialState = immutifyState(window.__INITIAL_STATE__);
const reducer = combineReducers(reducers);
const store   = applyMiddleware(promiseMiddleware)(createStore)(reducer, initialState, compose(
  window.devToolsExtension ? window.devToolsExtension() : f => f
));

const history = createHistory();

render(
  <Provider store={store}>
    <Router history={history} children={routes} />
  </Provider>,
  document.getElementById('react-view')
);