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 |
1x
1x
1x
1x
1x
1x
8x
8x
8x
8x
8x
10x
10x
1x
1x
1x
1x | "use strict";
var fs = require('fs');
var path = require('path');
var express = require('express');
var createMemoryHistory = require("react-router").createMemoryHistory;
var utils = require('./utils');
var skippedExtensions = [
'.coffee',
'.css',
'.eot',
'.gif',
'.jpg',
'.jpeg',
'.less',
'.png',
'.sass',
'.scss',
'.svg',
'.ts',
'.ttf',
'.woff',
'.woff2'
];
function skipRequireExtensions(additional) {
skippedExtensions
.concat(additional || [])
.forEach(function(ext) {
require.extensions[ext] = function() {};
});
}
function createWebpackMiddleware(compiler, config) {
if (!compiler.outputFileSystem) {
throw new Error('Compiler has no file system yet, use inside config.devServer.setup(cb) callback');
}
return function(options) {
options.fs = compiler.outputFileSystem;
return createExpressMiddleware(options);
};
}
/**
* @param {function} options.createRoutes function must return routes or routes config for React Router
* @param {function} [options.createStore] if set function must return an instance of Redux Store with initial state
* @param {function} [options.template] main [template function](#template-function), performs injection of rendered HTML to the template, default = replaces `<div id="root"></div>` with `<div id="root">%HTML%</div>`
* @param {string} [options.outputPath] path with static files, usually equals to Webpack's `output.path`
* @param {string} [options.templatePath] path to `index.html`, default = `%outputPath%/index.html`
* @param {boolean} [options.debug] emits to console some extra information about request handling, default = `false`
* @param {object} [options.fs] internal option used to pass an instance of file system object
* @param {string} [options.initialStateKey] key in `window` object that will be used to pass initial props, default = `__INITIAL_PROPS__`
* @param {string} [options.initialPropsKey] key in `window` object that will be used to pass initial state, default = `__INITIAL_STATE__`
* @return {Function}
*/
function createExpressMiddleware(options) {
options = options || {};
//TODO Create every time?
var history = createMemoryHistory();
var routes = options.createRoutes();
options.fs = options.fs || fs;
return function(req, res, next) {
utils.waitForTemplate(options).then(function(template){
utils.middleware(options, routes, history, template, req, res, next);
});
}
}
/**
* @param {string} options.outputPath path with static files, usually equals to Webpack's `output.path`
* @param {function} options.createRoutes function must return routes or routes config React Router
* @param {function} [options.createStore] if set function must return an instance of Redux Store with initial state
* @param {function} [options.template] main [template function](#template-function), performs injection of rendered HTML to the template, default = replaces `<div id="root"></div>` with `<div id="root">%HTML%</div>`
* @param {string} [options.templatePath] path to `index.html`, default = `%outputPath%/index.html`
* @param {boolean} [options.debug] emits to console some extra information about request handling, default = `false`
* @param {object} [options.fs] internal option used to pass an instance of file system object
* @param {string} [options.initialStateKey] key in `window` object that will be used to pass initial props, default = `__INITIAL_PROPS__`
* @param {string} [options.initialPropsKey] key in `window` object that will be used to pass initial state, default = `__INITIAL_STATE__`
* @param {string[]} [options.skipExtensions] array of strings that represent most commonly imported non-JS extensions that has to be skipped during server build, default = `['css', 'jpg', 'gif', ...]`
* @param {number} [options.port] listening port, default = `3000`
* @param {function} [options.listen] Express's listen function
* @return {Function}
*/
function createExpressServer(options) {
skipRequireExtensions(options.skipExtensions || null);
var app = express();
var port = options.port || 3000;
app.use(createExpressMiddleware(options));
app.use(express.static(options.outputPath));
app.listen(port, options.listen || function(err) {
if (err) throw err;
console.log('Listening', port);
});
return app;
}
exports.skipRequireExtensions = skipRequireExtensions;
exports.createWebpackMiddleware = createWebpackMiddleware;
exports.createExpressMiddleware = createExpressMiddleware;
exports.createExpressServer = createExpressServer; |