forked from erikras/react-redux-universal-hot-example
-
Notifications
You must be signed in to change notification settings - Fork 0
/
server.js
executable file
·130 lines (114 loc) · 4.02 KB
/
server.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
import Express from 'express';
import React from 'react';
import ReactDOM from 'react-dom/server';
import config from './config';
import favicon from 'serve-favicon';
import compression from 'compression';
import httpProxy from 'http-proxy';
import path from 'path';
import createStore from './redux/create';
import ApiClient from './helpers/ApiClient';
import Html from './helpers/Html';
import PrettyError from 'pretty-error';
import http from 'http';
import SocketIo from 'socket.io';
import {ReduxRouter} from 'redux-router';
import createHistory from 'history/lib/createMemoryHistory';
import {reduxReactRouter, match} from 'redux-router/server';
import {Provider} from 'react-redux';
import qs from 'query-string';
import getRoutes from './routes';
import getStatusFromRoutes from './helpers/getStatusFromRoutes';
const pretty = new PrettyError();
const app = new Express();
const server = new http.Server(app);
const proxy = httpProxy.createProxyServer({
target: 'http://' + config.apiHost + ':' + config.apiPort,
ws: true
});
app.use(compression());
app.use(favicon(path.join(__dirname, '..', 'static', 'favicon.ico')));
app.use(Express.static(path.join(__dirname, '..', 'static')));
// Proxy to API server
app.use('/api', (req, res) => {
proxy.web(req, res);
});
// added the error handling to avoid https://github.com/nodejitsu/node-http-proxy/issues/527
proxy.on('error', (error, req, res) => {
let json;
if (error.code !== 'ECONNRESET') {
console.error('proxy error', error);
}
if (!res.headersSent) {
res.writeHead(500, {'content-type': 'application/json'});
}
json = {error: 'proxy_error', reason: error.message};
res.end(JSON.stringify(json));
});
app.use((req, res) => {
if (__DEVELOPMENT__) {
// Do not cache webpack stats: the script file would change since
// hot module replacement is enabled in the development env
webpackIsomorphicTools.refresh();
}
const client = new ApiClient(req);
const store = createStore(reduxReactRouter, getRoutes, createHistory, client);
function hydrateOnClient() {
res.send('<!doctype html>\n' +
ReactDOM.renderToString(<Html assets={webpackIsomorphicTools.assets()} store={store}/>));
}
if (__DISABLE_SSR__) {
hydrateOnClient();
return;
}
store.dispatch(match(req.originalUrl, (error, redirectLocation, routerState) => {
if (redirectLocation) {
res.redirect(redirectLocation.pathname + redirectLocation.search);
} else if (error) {
console.error('ROUTER ERROR:', pretty.render(error));
res.status(500);
hydrateOnClient();
} else if (!routerState) {
res.status(500);
hydrateOnClient();
} else {
// Workaround redux-router query string issue:
// https://github.com/rackt/redux-router/issues/106
if (routerState.location.search && !routerState.location.query) {
routerState.location.query = qs.parse(routerState.location.search);
}
store.getState().router.then(() => {
const component = (
<Provider store={store} key="provider">
<ReduxRouter/>
</Provider>
);
const status = getStatusFromRoutes(routerState.routes);
if (status) {
res.status(status);
}
res.send('<!doctype html>\n' +
ReactDOM.renderToString(<Html assets={webpackIsomorphicTools.assets()} component={component} store={store}/>));
}).catch((err) => {
console.error('DATA FETCHING ERROR:', pretty.render(err));
res.status(500);
hydrateOnClient();
});
}
}));
});
if (config.port) {
if (config.isProduction) {
const io = new SocketIo(server);
io.path('/api/ws');
}
server.listen(config.port, (err) => {
if (err) {
console.error(err);
}
console.info('----\n==> ✅ %s is running, talking to API server on %s.', config.app.title, config.apiPort);
console.info('==> 💻 Open http://%s:%s in a browser to view the app.', config.host, config.port);
});
} else {
console.error('==> ERROR: No PORT environment variable has been specified');
}