-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathindex.js
138 lines (121 loc) · 4.97 KB
/
index.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
131
132
133
134
135
136
137
138
import { existsSync } from 'fs';
import express from 'express';
import compression from 'compression';
import portscanner from 'portscanner';
import bodyParser from 'body-parser';
import appConfig from 'ROOT/conf.app';
import log, {
BLUE,
BLACK_ON_GREEN,
BLACK_ON_YELLOW,
} from 'UTILS/logger';
import routes from './routes';
const isDev = process.env.NODE_ENV === 'development';
// =============================================================================
const app = {
init: function(){
this.expressInst = express();
this.server = require('http').createServer(this.expressInst);
// enable gzip (must come before `static` assets)
this.expressInst.use(compression());
// serve static files from `public`
this.expressInst.use(express.static(appConfig.paths.DIST_PUBLIC, {
index: false, // ignore the generated index file
}));
// allows for reading POST data
this.expressInst.use(bodyParser.json()); // to support JSON-encoded bodies
this.expressInst.use(bodyParser.urlencoded({ // to support URL-encoded bodies
extended: true,
}));
// allows for reading cookies
this.expressInst.use(require('cookie-parser')());
// bind server routes
this.setupRoutes();
this.addServerListeners();
},
setupRoutes: function(){
// Has to come before any other routes since it's a dynamic route inserted
// by reload, and won't resolve if any other routes are set up to handle
// js files or there are any catch-all's.
if(isDev) require('reload')(this.expressInst);
// dynamically wire up routes
Object.keys(routes).forEach(type => {
Object.keys(routes[type]).forEach(routeKey => {
const endpoint = routes[type][routeKey];
this.expressInst[type](endpoint.path, endpoint.handler);
});
});
},
addServerListeners: function(){
// Dynamically sets an open port, if the default is in use.
portscanner.checkPortStatus(appConfig.PORT, '127.0.0.1', (error, status) => {
// Status is 'open' if currently in use or 'closed' if available
switch(status){
case 'open' : // port isn't available, so find one that is
portscanner.findAPortNotInUse(appConfig.PORT, appConfig.PORT+20, '127.0.0.1', (error, openPort) => {
log(`${ BLACK_ON_YELLOW } PORT`, `${ appConfig.PORT } in use, using ${ openPort }`);
appConfig.PORT = openPort;
this.startServer();
});
break;
default :
this.startServer();
}
});
},
onBootComplete: function(data){
// let the user know the server is up and ready
log(`${ BLACK_ON_GREEN } SERVER`, 'Running at', `${ BLUE } ${ data.url }`);
// spit out some dev messaging
if( isDev ) log(`${ BLACK_ON_GREEN } WATCHING`, 'For changes.', '\n You can go to', `${ BLUE } chrome://inspect`, 'to debug server code.');
// spit out all the routes that have been registered
log(`${ BLACK_ON_GREEN } ROUTES`, `\n${ require('UTILS/listRoutes').default(this.expressInst) }\n`);
},
startServer: function(){
// don't start server until required files are built
const timeout = setInterval(() => {
const file = `${ appConfig.paths.DIST_PUBLIC }/${ appConfig.webpack.MANIFEST_NAME }`;
const bundleCreated = existsSync(file);
if( bundleCreated ) {
clearInterval(timeout);
// Sometimes the asset message prints after the server message, this
// ensures the same order every time.
setTimeout(() => {
const Loadable = require('react-loadable');
const { initStore } = require('STATE/store');
initStore();
// NOTE - Any Loadable components that need to be rendered on the
// server have to call `Loadable` before `preloadAll` is called,
// otherwise it's internal `ALL_INITIALIZERS` var won't be populated
// and the component may load outside of that mechanism causing the
// component to call `componentWillMount`, then `setState`, leading
// to an SSR error and an eventual hydration error on the client.
//
// TODO - Once this PR https://github.com/jamiebuilds/react-loadable/pull/127
// or anything that switches out `componentWillMount` with
// `componentDidMount` should fix the issue, and the below `require`
// can be removed.
require('ROUTES/shared/composedChunks');
Loadable.preloadAll().then(() => {
this.server.listen(appConfig.PORT, this.onBootComplete.bind(this, {
url: `http://localhost:${ appConfig.PORT }/`,
}));
});
}, 1000);
}
else{
log(`${ BLACK_ON_YELLOW } WAITING`, 'for', `${ BLUE } ${ file }`, 'to be created');
}
}, 200);
},
};
module.exports = app;
const args = process.argv;
if(
// CLI won't have parent
!module.parent
// First arg is node executable, second arg is the .js file, the rest are user args
&& args.length >= 3
){
if( app[args[2]] ) app[args[2]]();
}