@modern-js/prod-server 2.0.0-beta.0 → 2.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +110 -0
- package/dist/js/modern/constants.js +0 -2
- package/dist/js/modern/index.js +0 -1
- package/dist/js/modern/libs/context/context.js +10 -56
- package/dist/js/modern/libs/hook-api/index.js +0 -31
- package/dist/js/modern/libs/hook-api/route.js +0 -8
- package/dist/js/modern/libs/hook-api/template.js +0 -16
- package/dist/js/modern/libs/loadConfig.js +3 -10
- package/dist/js/modern/libs/metrics.js +6 -6
- package/dist/js/modern/libs/proxy.js +7 -12
- package/dist/js/modern/libs/render/cache/__tests__/cache.fun.test.js +0 -1
- package/dist/js/modern/libs/render/cache/__tests__/cache.test.js +0 -9
- package/dist/js/modern/libs/render/cache/index.js +8 -16
- package/dist/js/modern/libs/render/cache/page-caches/lru.js +0 -10
- package/dist/js/modern/libs/render/cache/spr.js +12 -62
- package/dist/js/modern/libs/render/cache/util.js +0 -6
- package/dist/js/modern/libs/render/index.js +6 -11
- package/dist/js/modern/libs/render/measure.js +1 -11
- package/dist/js/modern/libs/render/modern/index.js +2 -13
- package/dist/js/modern/libs/render/reader.js +13 -24
- package/dist/js/modern/libs/render/ssr.js +5 -6
- package/dist/js/modern/libs/render/static.js +6 -9
- package/dist/js/modern/libs/render/type.js +0 -1
- package/dist/js/modern/libs/route/index.js +8 -19
- package/dist/js/modern/libs/route/matcher.js +21 -29
- package/dist/js/modern/libs/route/route.js +0 -13
- package/dist/js/modern/libs/serve-file.js +5 -6
- package/dist/js/modern/server/index.js +25 -52
- package/dist/js/modern/server/modern-server-split.js +0 -11
- package/dist/js/modern/server/modern-server.js +87 -167
- package/dist/js/modern/utils.js +12 -27
- package/dist/js/modern/worker-server.js +34 -0
- package/dist/js/node/constants.js +0 -2
- package/dist/js/node/index.js +0 -10
- package/dist/js/node/libs/context/context.js +10 -65
- package/dist/js/node/libs/context/index.js +0 -3
- package/dist/js/node/libs/hook-api/index.js +0 -42
- package/dist/js/node/libs/hook-api/route.js +0 -10
- package/dist/js/node/libs/hook-api/template.js +0 -22
- package/dist/js/node/libs/loadConfig.js +3 -22
- package/dist/js/node/libs/metrics.js +6 -6
- package/dist/js/node/libs/proxy.js +7 -17
- package/dist/js/node/libs/render/cache/__tests__/cache.fun.test.js +0 -5
- package/dist/js/node/libs/render/cache/__tests__/cache.test.js +0 -12
- package/dist/js/node/libs/render/cache/index.js +8 -22
- package/dist/js/node/libs/render/cache/page-caches/index.js +0 -2
- package/dist/js/node/libs/render/cache/page-caches/lru.js +0 -14
- package/dist/js/node/libs/render/cache/spr.js +12 -71
- package/dist/js/node/libs/render/cache/util.js +0 -18
- package/dist/js/node/libs/render/index.js +6 -26
- package/dist/js/node/libs/render/measure.js +0 -17
- package/dist/js/node/libs/render/modern/index.js +2 -20
- package/dist/js/node/libs/render/reader.js +12 -39
- package/dist/js/node/libs/render/ssr.js +4 -16
- package/dist/js/node/libs/render/static.js +6 -18
- package/dist/js/node/libs/render/type.js +0 -1
- package/dist/js/node/libs/route/index.js +8 -22
- package/dist/js/node/libs/route/matcher.js +18 -34
- package/dist/js/node/libs/route/route.js +0 -15
- package/dist/js/node/libs/serve-file.js +5 -13
- package/dist/js/node/server/index.js +25 -72
- package/dist/js/node/server/modern-server-split.js +0 -13
- package/dist/js/node/server/modern-server.js +87 -196
- package/dist/js/node/utils.js +13 -52
- package/dist/js/node/worker-server.js +41 -0
- package/dist/js/treeshaking/constants.js +28 -0
- package/dist/js/treeshaking/index.js +13 -0
- package/dist/js/treeshaking/libs/context/context.js +243 -0
- package/dist/js/treeshaking/libs/context/index.js +5 -0
- package/dist/js/treeshaking/libs/hook-api/index.js +157 -0
- package/dist/js/treeshaking/libs/hook-api/route.js +33 -0
- package/dist/js/treeshaking/libs/hook-api/template.js +91 -0
- package/dist/js/treeshaking/libs/loadConfig.js +39 -0
- package/dist/js/treeshaking/libs/metrics.js +12 -0
- package/dist/js/treeshaking/libs/proxy.js +80 -0
- package/dist/js/treeshaking/libs/render/cache/__tests__/cache.fun.test.js +124 -0
- package/dist/js/treeshaking/libs/render/cache/__tests__/cache.test.js +464 -0
- package/dist/js/treeshaking/libs/render/cache/__tests__/cacheable.js +53 -0
- package/dist/js/treeshaking/libs/render/cache/__tests__/error-configuration.js +35 -0
- package/dist/js/treeshaking/libs/render/cache/__tests__/matched-cache.js +121 -0
- package/dist/js/treeshaking/libs/render/cache/index.js +184 -0
- package/dist/js/treeshaking/libs/render/cache/page-caches/index.js +30 -0
- package/dist/js/treeshaking/libs/render/cache/page-caches/lru.js +46 -0
- package/dist/js/treeshaking/libs/render/cache/spr.js +362 -0
- package/dist/js/treeshaking/libs/render/cache/type.js +1 -0
- package/dist/js/treeshaking/libs/render/cache/util.js +101 -0
- package/dist/js/treeshaking/libs/render/index.js +100 -0
- package/dist/js/treeshaking/libs/render/measure.js +61 -0
- package/dist/js/treeshaking/libs/render/modern/browser-list.js +7 -0
- package/dist/js/treeshaking/libs/render/modern/index.js +39 -0
- package/dist/js/treeshaking/libs/render/reader.js +191 -0
- package/dist/js/treeshaking/libs/render/ssr.js +98 -0
- package/dist/js/treeshaking/libs/render/static.js +84 -0
- package/dist/js/treeshaking/libs/render/type.js +6 -0
- package/dist/js/treeshaking/libs/route/index.js +94 -0
- package/dist/js/treeshaking/libs/route/matcher.js +113 -0
- package/dist/js/treeshaking/libs/route/route.js +26 -0
- package/dist/js/treeshaking/libs/serve-file.js +75 -0
- package/dist/js/treeshaking/server/index.js +339 -0
- package/dist/js/treeshaking/server/modern-server-split.js +152 -0
- package/dist/js/treeshaking/server/modern-server.js +946 -0
- package/dist/js/treeshaking/type.js +1 -0
- package/dist/js/treeshaking/utils.js +90 -0
- package/dist/js/treeshaking/worker-server.js +56 -0
- package/dist/types/index.d.ts +0 -2
- package/dist/types/libs/context/context.d.ts +0 -3
- package/dist/types/libs/loadConfig.d.ts +0 -1
- package/dist/types/libs/render/cache/index.d.ts +0 -2
- package/dist/types/libs/render/cache/spr.d.ts +0 -2
- package/dist/types/server/index.d.ts +0 -3
- package/dist/types/utils.d.ts +2 -3
- package/dist/types/worker-server.d.ts +16 -0
- package/package.json +31 -15
|
@@ -1,15 +1,9 @@
|
|
|
1
1
|
const _excluded = ["getMiddlewares"];
|
|
2
|
-
|
|
3
2
|
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
4
|
-
|
|
5
3
|
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
6
|
-
|
|
7
4
|
function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
|
|
8
|
-
|
|
9
5
|
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
|
|
10
|
-
|
|
11
6
|
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
12
|
-
|
|
13
7
|
/* eslint-disable max-lines */
|
|
14
8
|
import { createServer } from 'http';
|
|
15
9
|
import util from 'util';
|
|
@@ -29,8 +23,11 @@ const API_DIR = './api';
|
|
|
29
23
|
const SERVER_DIR = './server';
|
|
30
24
|
export class ModernServer {
|
|
31
25
|
// appDirectory
|
|
26
|
+
|
|
32
27
|
// product dist dir
|
|
28
|
+
|
|
33
29
|
// work on src or dist
|
|
30
|
+
|
|
34
31
|
constructor({
|
|
35
32
|
pwd,
|
|
36
33
|
config,
|
|
@@ -41,54 +38,30 @@ export class ModernServer {
|
|
|
41
38
|
runMode,
|
|
42
39
|
proxyTarget
|
|
43
40
|
}) {
|
|
44
|
-
var _config$output;
|
|
45
|
-
|
|
46
41
|
_defineProperty(this, "pwd", void 0);
|
|
47
|
-
|
|
48
42
|
_defineProperty(this, "distDir", void 0);
|
|
49
|
-
|
|
50
43
|
_defineProperty(this, "workDir", void 0);
|
|
51
|
-
|
|
52
44
|
_defineProperty(this, "router", void 0);
|
|
53
|
-
|
|
54
45
|
_defineProperty(this, "conf", void 0);
|
|
55
|
-
|
|
56
46
|
_defineProperty(this, "handlers", []);
|
|
57
|
-
|
|
58
47
|
_defineProperty(this, "presetRoutes", void 0);
|
|
59
|
-
|
|
60
48
|
_defineProperty(this, "runner", void 0);
|
|
61
|
-
|
|
62
49
|
_defineProperty(this, "logger", void 0);
|
|
63
|
-
|
|
64
50
|
_defineProperty(this, "metrics", void 0);
|
|
65
|
-
|
|
66
51
|
_defineProperty(this, "runMode", void 0);
|
|
67
|
-
|
|
68
52
|
_defineProperty(this, "reader", reader);
|
|
69
|
-
|
|
70
53
|
_defineProperty(this, "proxyTarget", void 0);
|
|
71
|
-
|
|
72
54
|
_defineProperty(this, "staticFileHandler", void 0);
|
|
73
|
-
|
|
74
55
|
_defineProperty(this, "routeRenderHandler", void 0);
|
|
75
|
-
|
|
76
56
|
_defineProperty(this, "beforeRouteHandler", null);
|
|
77
|
-
|
|
78
57
|
_defineProperty(this, "frameWebHandler", null);
|
|
79
|
-
|
|
80
58
|
_defineProperty(this, "frameAPIHandler", null);
|
|
81
|
-
|
|
82
59
|
_defineProperty(this, "proxyHandler", null);
|
|
83
|
-
|
|
84
60
|
_defineProperty(this, "_handler", void 0);
|
|
85
|
-
|
|
86
61
|
_defineProperty(this, "staticGenerate", void 0);
|
|
87
|
-
|
|
88
62
|
require('ignore-styles');
|
|
89
|
-
|
|
90
63
|
this.pwd = pwd;
|
|
91
|
-
this.distDir = path.join(pwd,
|
|
64
|
+
this.distDir = path.join(pwd, config.output.path || 'dist');
|
|
92
65
|
this.workDir = this.distDir;
|
|
93
66
|
this.conf = config;
|
|
94
67
|
debug('server conf', this.conf);
|
|
@@ -98,44 +71,48 @@ export class ModernServer {
|
|
|
98
71
|
this.presetRoutes = routes;
|
|
99
72
|
this.proxyTarget = proxyTarget;
|
|
100
73
|
this.staticGenerate = staticGenerate || false;
|
|
101
|
-
this.runMode = runMode || RUN_MODE.FULL;
|
|
102
|
-
|
|
103
|
-
|
|
74
|
+
this.runMode = runMode || RUN_MODE.FULL;
|
|
75
|
+
// process.env.BUILD_TYPE = `${this.staticGenerate ? 'ssg' : 'ssr'}`;
|
|
76
|
+
}
|
|
104
77
|
|
|
78
|
+
// server prepare
|
|
105
79
|
async onInit(runner, app) {
|
|
106
80
|
var _conf$bff;
|
|
107
|
-
|
|
108
81
|
this.runner = runner;
|
|
109
82
|
const {
|
|
110
83
|
distDir,
|
|
111
84
|
staticGenerate,
|
|
112
85
|
conf
|
|
113
86
|
} = this;
|
|
114
|
-
debug('final server conf', this.conf);
|
|
115
|
-
|
|
87
|
+
debug('final server conf', this.conf);
|
|
88
|
+
// proxy handler, each proxy has own handler
|
|
116
89
|
this.proxyHandler = createProxyHandler((_conf$bff = conf.bff) === null || _conf$bff === void 0 ? void 0 : _conf$bff.proxy);
|
|
117
|
-
|
|
118
90
|
if (this.proxyHandler) {
|
|
119
91
|
this.proxyHandler.forEach(handler => {
|
|
120
92
|
this.addHandler(handler);
|
|
121
93
|
});
|
|
122
|
-
}
|
|
123
|
-
|
|
94
|
+
}
|
|
124
95
|
|
|
96
|
+
// start file reader
|
|
125
97
|
this.reader.init();
|
|
126
98
|
app.on('close', () => {
|
|
127
99
|
this.reader.close();
|
|
128
|
-
});
|
|
100
|
+
});
|
|
129
101
|
|
|
102
|
+
// use preset routes priority
|
|
130
103
|
const usageRoutes = this.filterRoutes(this.getRoutes());
|
|
131
|
-
this.router.reset(usageRoutes);
|
|
104
|
+
this.router.reset(usageRoutes);
|
|
132
105
|
|
|
106
|
+
// warmup ssr bundle in production env
|
|
133
107
|
this.warmupSSRBundle();
|
|
134
108
|
await this.prepareFrameHandler();
|
|
135
|
-
await this.prepareBeforeRouteHandler(usageRoutes, distDir);
|
|
136
|
-
// Setting `assetPrefix` means these resources should be uploaded to CDN.
|
|
109
|
+
await this.prepareBeforeRouteHandler(usageRoutes, distDir);
|
|
137
110
|
|
|
138
|
-
|
|
111
|
+
// Only work when without setting `assetPrefix`.
|
|
112
|
+
// Setting `assetPrefix` means these resources should be uploaded to CDN.
|
|
113
|
+
const staticPathRegExp = getStaticReg(this.conf.output || {},
|
|
114
|
+
// FIXME:
|
|
115
|
+
this.conf.html);
|
|
139
116
|
this.staticFileHandler = createStaticFileHandler([{
|
|
140
117
|
path: staticPathRegExp,
|
|
141
118
|
target: distDir
|
|
@@ -145,34 +122,33 @@ export class ModernServer {
|
|
|
145
122
|
staticGenerate
|
|
146
123
|
});
|
|
147
124
|
await this.setupBeforeProdMiddleware();
|
|
148
|
-
this.addHandler(this.staticFileHandler);
|
|
125
|
+
this.addHandler(this.staticFileHandler);
|
|
149
126
|
|
|
127
|
+
// execute after staticFileHandler, can rename to staticFallbackHandler if needed.
|
|
150
128
|
this.addHandler(faviconFallbackHandler);
|
|
151
129
|
this.addBeforeRouteHandler();
|
|
152
|
-
this.addHandler(this.routeHandler.bind(this));
|
|
130
|
+
this.addHandler(this.routeHandler.bind(this));
|
|
153
131
|
|
|
132
|
+
// compose middlewares to http handler
|
|
154
133
|
this.compose();
|
|
155
|
-
} // server ready
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
onRepack(_) {// empty
|
|
159
134
|
}
|
|
160
135
|
|
|
136
|
+
// server ready
|
|
137
|
+
onRepack(_) {
|
|
138
|
+
// empty
|
|
139
|
+
}
|
|
161
140
|
addBeforeRouteHandler() {
|
|
162
141
|
this.addHandler(async (context, next) => {
|
|
163
142
|
if (this.beforeRouteHandler) {
|
|
164
143
|
await this.beforeRouteHandler(context);
|
|
165
|
-
|
|
166
144
|
if (this.isSend(context.res)) {
|
|
167
145
|
return;
|
|
168
146
|
}
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
|
|
147
|
+
}
|
|
148
|
+
// eslint-disable-next-line consistent-return
|
|
172
149
|
return next();
|
|
173
150
|
});
|
|
174
151
|
}
|
|
175
|
-
|
|
176
152
|
onServerChange({
|
|
177
153
|
filepath
|
|
178
154
|
}) {
|
|
@@ -191,73 +167,63 @@ export class ModernServer {
|
|
|
191
167
|
onlyWeb,
|
|
192
168
|
onlyApi
|
|
193
169
|
});
|
|
194
|
-
}
|
|
195
|
-
|
|
170
|
+
}
|
|
196
171
|
|
|
172
|
+
// exposed requestHandler
|
|
197
173
|
getRequestHandler() {
|
|
198
174
|
return this.requestHandler.bind(this);
|
|
199
175
|
}
|
|
200
|
-
|
|
201
176
|
async render(req, res, url) {
|
|
202
177
|
req.logger = this.logger;
|
|
203
178
|
req.metrics = this.metrics;
|
|
204
179
|
const context = createContext(req, res);
|
|
205
180
|
const matched = this.router.match(url || context.path);
|
|
206
|
-
|
|
207
181
|
if (!matched) {
|
|
208
182
|
return null;
|
|
209
183
|
}
|
|
210
|
-
|
|
211
184
|
const route = matched.generate(context.url);
|
|
212
185
|
const result = await this.handleWeb(context, route);
|
|
213
|
-
|
|
214
186
|
if (!result) {
|
|
215
187
|
return null;
|
|
216
188
|
}
|
|
217
|
-
|
|
218
189
|
return result.content.toString();
|
|
219
190
|
}
|
|
220
|
-
|
|
221
191
|
async createHTTPServer(handler) {
|
|
222
192
|
return createServer(handler);
|
|
223
193
|
}
|
|
194
|
+
|
|
224
195
|
/* —————————————————————— function will be overwrite —————————————————————— */
|
|
225
196
|
// get routes info
|
|
226
|
-
|
|
227
|
-
|
|
228
197
|
getRoutes() {
|
|
229
198
|
// Preferred to use preset routes
|
|
230
199
|
if (this.presetRoutes) {
|
|
231
200
|
return this.presetRoutes;
|
|
232
|
-
}
|
|
233
|
-
|
|
201
|
+
}
|
|
234
202
|
|
|
203
|
+
// read routes from spec file
|
|
235
204
|
const file = path.join(this.distDir, ROUTE_SPEC_FILE);
|
|
236
|
-
|
|
237
205
|
if (fs.existsSync(file)) {
|
|
238
206
|
const content = fs.readJSONSync(file);
|
|
239
207
|
return content.routes;
|
|
240
208
|
}
|
|
241
|
-
|
|
242
209
|
return [];
|
|
243
|
-
}
|
|
244
|
-
// handler should do not do more things after invoke next
|
|
245
|
-
|
|
210
|
+
}
|
|
246
211
|
|
|
212
|
+
// add promisify request handler to server
|
|
213
|
+
// handler should do not do more things after invoke next
|
|
247
214
|
addHandler(handler) {
|
|
248
215
|
if (handler[Symbol.toStringTag] === 'AsyncFunction') {
|
|
249
216
|
this.handlers.push(handler);
|
|
250
217
|
} else {
|
|
251
218
|
this.handlers.push(util.promisify(handler));
|
|
252
219
|
}
|
|
253
|
-
}
|
|
254
|
-
|
|
220
|
+
}
|
|
255
221
|
|
|
222
|
+
// return 404 page
|
|
256
223
|
render404(context) {
|
|
257
224
|
context.error(ERROR_DIGEST.ENOTF, '404 Not Found');
|
|
258
225
|
this.renderErrorPage(context, 404);
|
|
259
226
|
}
|
|
260
|
-
|
|
261
227
|
async prepareBeforeRouteHandler(specs, distDir) {
|
|
262
228
|
const {
|
|
263
229
|
runner
|
|
@@ -269,9 +235,9 @@ export class ModernServer {
|
|
|
269
235
|
onLast: () => null
|
|
270
236
|
});
|
|
271
237
|
this.beforeRouteHandler = handler;
|
|
272
|
-
}
|
|
273
|
-
|
|
238
|
+
}
|
|
274
239
|
|
|
240
|
+
// gather frame extension and get framework handler
|
|
275
241
|
async prepareFrameHandler(options) {
|
|
276
242
|
const {
|
|
277
243
|
workDir,
|
|
@@ -280,33 +246,32 @@ export class ModernServer {
|
|
|
280
246
|
const {
|
|
281
247
|
onlyApi,
|
|
282
248
|
onlyWeb
|
|
283
|
-
} = options || {};
|
|
249
|
+
} = options || {};
|
|
284
250
|
|
|
251
|
+
// server hook, gather plugin inject
|
|
285
252
|
const _createMiddlewareColl = createMiddlewareCollecter(),
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
253
|
+
{
|
|
254
|
+
getMiddlewares
|
|
255
|
+
} = _createMiddlewareColl,
|
|
256
|
+
collector = _objectWithoutProperties(_createMiddlewareColl, _excluded);
|
|
291
257
|
await runner.gather(collector);
|
|
292
258
|
const {
|
|
293
259
|
api: pluginAPIExt,
|
|
294
260
|
web: pluginWebExt
|
|
295
261
|
} = getMiddlewares();
|
|
296
262
|
const apiDir = path.join(workDir, API_DIR);
|
|
297
|
-
const serverDir = path.join(workDir, SERVER_DIR);
|
|
263
|
+
const serverDir = path.join(workDir, SERVER_DIR);
|
|
298
264
|
|
|
265
|
+
// get api or web server handler from server-framework plugin
|
|
299
266
|
if ((await fs.pathExists(path.join(serverDir))) && !onlyApi) {
|
|
300
267
|
const webExtension = mergeExtension(pluginWebExt);
|
|
301
268
|
this.frameWebHandler = await this.prepareWebHandler(webExtension);
|
|
302
269
|
}
|
|
303
|
-
|
|
304
270
|
if (fs.existsSync(apiDir) && !onlyWeb) {
|
|
305
271
|
const apiExtension = mergeExtension(pluginAPIExt);
|
|
306
272
|
this.frameAPIHandler = await this.prepareAPIHandler(apiExtension);
|
|
307
273
|
}
|
|
308
274
|
}
|
|
309
|
-
|
|
310
275
|
async prepareWebHandler(extension) {
|
|
311
276
|
const {
|
|
312
277
|
workDir,
|
|
@@ -320,7 +285,6 @@ export class ModernServer {
|
|
|
320
285
|
});
|
|
321
286
|
return handler;
|
|
322
287
|
}
|
|
323
|
-
|
|
324
288
|
async prepareAPIHandler(extension) {
|
|
325
289
|
const {
|
|
326
290
|
workDir,
|
|
@@ -339,11 +303,9 @@ export class ModernServer {
|
|
|
339
303
|
onLast: () => null
|
|
340
304
|
});
|
|
341
305
|
}
|
|
342
|
-
|
|
343
306
|
filterRoutes(routes) {
|
|
344
307
|
return routes;
|
|
345
308
|
}
|
|
346
|
-
|
|
347
309
|
async setupBeforeProdMiddleware() {
|
|
348
310
|
const {
|
|
349
311
|
conf,
|
|
@@ -354,20 +316,16 @@ export class ModernServer {
|
|
|
354
316
|
this.addHandler(mid);
|
|
355
317
|
});
|
|
356
318
|
}
|
|
357
|
-
|
|
358
319
|
async handleAPI(context) {
|
|
359
320
|
const {
|
|
360
321
|
req,
|
|
361
322
|
res
|
|
362
323
|
} = context;
|
|
363
|
-
|
|
364
324
|
if (!this.frameAPIHandler) {
|
|
365
325
|
throw new Error('can not found api handler');
|
|
366
326
|
}
|
|
367
|
-
|
|
368
327
|
await this.frameAPIHandler(req, res);
|
|
369
328
|
}
|
|
370
|
-
|
|
371
329
|
async handleWeb(context, route) {
|
|
372
330
|
return this.routeRenderHandler({
|
|
373
331
|
ctx: context,
|
|
@@ -375,231 +333,198 @@ export class ModernServer {
|
|
|
375
333
|
runner: this.runner
|
|
376
334
|
});
|
|
377
335
|
}
|
|
378
|
-
|
|
379
336
|
async proxy() {
|
|
380
337
|
return null;
|
|
381
|
-
}
|
|
382
|
-
|
|
338
|
+
}
|
|
383
339
|
|
|
340
|
+
// warmup ssr function
|
|
384
341
|
warmupSSRBundle() {
|
|
385
342
|
const {
|
|
386
343
|
distDir
|
|
387
344
|
} = this;
|
|
388
345
|
const bundles = this.router.getBundles();
|
|
389
346
|
bundles.forEach(bundle => {
|
|
390
|
-
const filepath = path.join(distDir, bundle);
|
|
391
|
-
|
|
347
|
+
const filepath = path.join(distDir, bundle);
|
|
348
|
+
// if error, just throw and let process die
|
|
392
349
|
require(filepath);
|
|
393
350
|
});
|
|
394
351
|
}
|
|
395
|
-
|
|
396
352
|
createContext(req, res, options = {}) {
|
|
397
353
|
return createContext(req, res, options);
|
|
398
354
|
}
|
|
355
|
+
|
|
399
356
|
/* —————————————————————— private function —————————————————————— */
|
|
400
357
|
// handler route.json, include api / csr / ssr
|
|
401
|
-
|
|
402
|
-
|
|
403
358
|
async routeHandler(context) {
|
|
404
359
|
const {
|
|
405
360
|
res
|
|
406
|
-
} = context;
|
|
361
|
+
} = context;
|
|
407
362
|
|
|
363
|
+
// match routes in the route spec
|
|
408
364
|
const matched = this.router.match(context.path);
|
|
409
|
-
|
|
410
365
|
if (!matched) {
|
|
411
366
|
this.render404(context);
|
|
412
367
|
return;
|
|
413
|
-
}
|
|
414
|
-
|
|
368
|
+
}
|
|
415
369
|
|
|
370
|
+
// route is api service
|
|
416
371
|
let route = matched.generate(context.url);
|
|
417
|
-
|
|
418
372
|
if (route.isApi) {
|
|
419
373
|
await this.handleAPI(context);
|
|
420
374
|
return;
|
|
421
375
|
}
|
|
376
|
+
const afterMatchContext = createAfterMatchContext(context, route.entryName);
|
|
422
377
|
|
|
423
|
-
|
|
424
|
-
|
|
378
|
+
// only full mode run server hook
|
|
425
379
|
if (this.runMode === RUN_MODE.FULL) {
|
|
426
380
|
await this.runner.afterMatch(afterMatchContext, {
|
|
427
381
|
onLast: noop
|
|
428
382
|
});
|
|
429
383
|
}
|
|
430
|
-
|
|
431
384
|
if (this.isSend(res)) {
|
|
432
385
|
return;
|
|
433
386
|
}
|
|
434
|
-
|
|
435
387
|
const {
|
|
436
388
|
current,
|
|
437
389
|
url,
|
|
438
390
|
status
|
|
439
|
-
} = afterMatchContext.router;
|
|
440
|
-
|
|
391
|
+
} = afterMatchContext.router;
|
|
392
|
+
// redirect to another url
|
|
441
393
|
if (url) {
|
|
442
394
|
this.redirect(res, url, status);
|
|
443
395
|
return;
|
|
444
|
-
}
|
|
445
|
-
|
|
396
|
+
}
|
|
446
397
|
|
|
398
|
+
// rewrite to another entry
|
|
447
399
|
if (route.entryName !== current) {
|
|
448
400
|
const matched = this.router.matchEntry(current);
|
|
449
|
-
|
|
450
401
|
if (!matched) {
|
|
451
402
|
this.render404(context);
|
|
452
403
|
return;
|
|
453
404
|
}
|
|
454
|
-
|
|
455
405
|
route = matched.generate(context.url);
|
|
456
406
|
}
|
|
457
|
-
|
|
458
407
|
context.setParams(route.params);
|
|
459
408
|
context.setServerData('router', {
|
|
460
409
|
baseUrl: route.urlPath,
|
|
461
410
|
params: route.params
|
|
462
411
|
});
|
|
463
|
-
|
|
464
412
|
if (this.frameWebHandler) {
|
|
465
413
|
res.locals = res.locals || {};
|
|
466
414
|
const middlewareContext = createMiddlewareContext(context);
|
|
467
415
|
await this.frameWebHandler(middlewareContext);
|
|
468
416
|
res.locals = _objectSpread(_objectSpread({}, res.locals), middlewareContext.response.locals);
|
|
469
|
-
}
|
|
470
|
-
|
|
417
|
+
}
|
|
471
418
|
|
|
419
|
+
// frameWebHandler has process request
|
|
472
420
|
if (this.isSend(res)) {
|
|
473
421
|
return;
|
|
474
422
|
}
|
|
475
|
-
|
|
476
423
|
if (route.responseHeaders) {
|
|
477
424
|
Object.keys(route.responseHeaders).forEach(key => {
|
|
478
425
|
const value = route.responseHeaders[key];
|
|
479
|
-
|
|
480
426
|
if (value) {
|
|
481
427
|
context.res.setHeader(key, value);
|
|
482
428
|
}
|
|
483
429
|
});
|
|
484
430
|
}
|
|
485
|
-
|
|
486
431
|
const renderResult = await this.handleWeb(context, route);
|
|
487
|
-
|
|
488
432
|
if (!renderResult) {
|
|
489
433
|
this.render404(context);
|
|
490
434
|
return;
|
|
491
|
-
}
|
|
492
|
-
|
|
435
|
+
}
|
|
493
436
|
|
|
437
|
+
// React Router navigation
|
|
494
438
|
if (renderResult.redirect) {
|
|
495
439
|
this.redirect(res, renderResult.content, renderResult.statusCode);
|
|
496
440
|
return;
|
|
497
441
|
}
|
|
498
|
-
|
|
499
442
|
if (this.isSend(res)) {
|
|
500
443
|
return;
|
|
501
444
|
}
|
|
502
|
-
|
|
503
445
|
res.setHeader('content-type', renderResult.contentType);
|
|
504
446
|
const {
|
|
505
447
|
contentStream
|
|
506
448
|
} = renderResult;
|
|
507
|
-
|
|
508
449
|
if (contentStream) {
|
|
509
450
|
contentStream.pipe(templateInjectableStream({
|
|
510
451
|
prependHead: route.entryName ? `<script>window._SERVER_DATA=${JSON.stringify(context.serverData)}</script>` : undefined
|
|
511
452
|
})).pipe(res);
|
|
512
453
|
return;
|
|
513
454
|
}
|
|
514
|
-
|
|
515
455
|
let response = renderResult.content;
|
|
516
|
-
|
|
517
456
|
if (route.entryName) {
|
|
518
|
-
const afterRenderContext = createAfterRenderContext(context, response.toString());
|
|
519
|
-
// FIXME: how to run server hook in streaming
|
|
457
|
+
const afterRenderContext = createAfterRenderContext(context, response.toString());
|
|
520
458
|
|
|
459
|
+
// only full mode run server hook
|
|
460
|
+
// FIXME: how to run server hook in streaming
|
|
521
461
|
if (this.runMode === RUN_MODE.FULL) {
|
|
522
462
|
await this.runner.afterRender(afterRenderContext, {
|
|
523
463
|
onLast: noop
|
|
524
464
|
});
|
|
525
465
|
}
|
|
526
|
-
|
|
527
466
|
if (this.isSend(res)) {
|
|
528
467
|
return;
|
|
529
|
-
}
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
// It will inject _SERVER_DATA twice, when SSG mode.
|
|
530
471
|
// The first time was in ssg html created, the seoncd time was in prod-server start.
|
|
531
472
|
// but the second wound causes route error.
|
|
532
473
|
// To ensure that the second injection fails, the _SERVER_DATA inject at the front of head,
|
|
533
|
-
|
|
534
|
-
|
|
535
474
|
afterRenderContext.template.prependHead(`<script>window._SERVER_DATA=${JSON.stringify(context.serverData)}</script>`);
|
|
536
475
|
response = afterRenderContext.template.get();
|
|
537
476
|
}
|
|
538
|
-
|
|
539
477
|
res.end(response);
|
|
540
478
|
}
|
|
541
|
-
|
|
542
479
|
isSend(res) {
|
|
543
480
|
if (res.headersSent) {
|
|
544
481
|
return true;
|
|
545
482
|
}
|
|
546
|
-
|
|
547
483
|
if (res.getHeader('Location') && isRedirect(res.statusCode)) {
|
|
548
484
|
res.end();
|
|
549
485
|
return true;
|
|
550
486
|
}
|
|
551
|
-
|
|
552
487
|
return false;
|
|
553
|
-
}
|
|
554
|
-
|
|
488
|
+
}
|
|
555
489
|
|
|
490
|
+
// compose handlers and create the final handler
|
|
556
491
|
compose() {
|
|
557
492
|
const {
|
|
558
493
|
handlers
|
|
559
494
|
} = this;
|
|
560
|
-
|
|
561
495
|
if (!Array.isArray(handlers)) {
|
|
562
496
|
throw new TypeError('Middleware stack must be an array!');
|
|
563
497
|
}
|
|
564
|
-
|
|
565
498
|
for (const fn of handlers) {
|
|
566
499
|
if (typeof fn !== 'function') {
|
|
567
500
|
throw new TypeError('Middleware must be composed of functions!');
|
|
568
501
|
}
|
|
569
502
|
}
|
|
570
|
-
|
|
571
503
|
this._handler = (context, next) => {
|
|
572
504
|
let i = 0;
|
|
573
|
-
|
|
574
505
|
const dispatch = error => {
|
|
575
506
|
if (error) {
|
|
576
507
|
return this.onError(context, error);
|
|
577
508
|
}
|
|
578
|
-
|
|
579
509
|
const handler = handlers[i++];
|
|
580
|
-
|
|
581
510
|
if (!handler) {
|
|
582
511
|
return next();
|
|
583
512
|
}
|
|
584
|
-
|
|
585
513
|
return handler(context, dispatch).catch(onError);
|
|
586
514
|
};
|
|
587
|
-
|
|
588
515
|
const onError = err => {
|
|
589
516
|
this.onError(context, err);
|
|
590
517
|
};
|
|
591
|
-
|
|
592
518
|
return dispatch();
|
|
593
519
|
};
|
|
594
520
|
}
|
|
595
|
-
|
|
596
|
-
|
|
521
|
+
requestHandler(req, res, next = () => {
|
|
522
|
+
// empty
|
|
597
523
|
}) {
|
|
598
524
|
res.statusCode = 200;
|
|
599
525
|
req.logger = this.logger;
|
|
600
526
|
req.metrics = this.metrics;
|
|
601
527
|
let context;
|
|
602
|
-
|
|
603
528
|
try {
|
|
604
529
|
context = this.createContext(req, res);
|
|
605
530
|
} catch (e) {
|
|
@@ -608,25 +533,21 @@ export class ModernServer {
|
|
|
608
533
|
res.setHeader('content-type', mime.contentType('html'));
|
|
609
534
|
return res.end(createErrorDocument(500, ERROR_PAGE_TEXT[500]));
|
|
610
535
|
}
|
|
611
|
-
|
|
612
536
|
try {
|
|
613
537
|
return this._handler(context, next);
|
|
614
538
|
} catch (err) {
|
|
615
539
|
return this.onError(context, err);
|
|
616
540
|
}
|
|
617
541
|
}
|
|
618
|
-
|
|
619
542
|
redirect(res, url, status = 302) {
|
|
620
543
|
res.setHeader('Location', url);
|
|
621
544
|
res.statusCode = status;
|
|
622
545
|
res.end();
|
|
623
546
|
}
|
|
624
|
-
|
|
625
547
|
onError(context, err) {
|
|
626
548
|
context.error(ERROR_DIGEST.EINTER, err);
|
|
627
549
|
this.renderErrorPage(context, 500);
|
|
628
550
|
}
|
|
629
|
-
|
|
630
551
|
async renderErrorPage(context, status) {
|
|
631
552
|
const {
|
|
632
553
|
res
|
|
@@ -635,14 +556,15 @@ export class ModernServer {
|
|
|
635
556
|
res.setHeader('content-type', mime.contentType('html'));
|
|
636
557
|
const statusPage = `/${status}`;
|
|
637
558
|
const customErrorPage = `/_error`;
|
|
638
|
-
const matched = this.router.match(statusPage) || this.router.match(customErrorPage);
|
|
559
|
+
const matched = this.router.match(statusPage) || this.router.match(customErrorPage);
|
|
560
|
+
// if no custom status page find
|
|
639
561
|
|
|
640
562
|
if (matched) {
|
|
641
563
|
const route = matched.generate(context.url);
|
|
642
564
|
const {
|
|
643
565
|
entryName
|
|
644
|
-
} = route;
|
|
645
|
-
|
|
566
|
+
} = route;
|
|
567
|
+
// check entryName, avoid matched '/' route
|
|
646
568
|
if (entryName === status.toString() || entryName === '_error') {
|
|
647
569
|
try {
|
|
648
570
|
const file = await this.routeRenderHandler({
|
|
@@ -650,19 +572,17 @@ export class ModernServer {
|
|
|
650
572
|
ctx: context,
|
|
651
573
|
runner: this.runner
|
|
652
574
|
});
|
|
653
|
-
|
|
654
575
|
if (file) {
|
|
655
576
|
context.res.end(file.content);
|
|
656
577
|
return;
|
|
657
578
|
}
|
|
658
|
-
} catch (e) {
|
|
579
|
+
} catch (e) {
|
|
580
|
+
// just catch error when the rendering error occurred in the custom error page.
|
|
659
581
|
}
|
|
660
582
|
}
|
|
661
583
|
}
|
|
662
|
-
|
|
663
584
|
const text = ERROR_PAGE_TEXT[status] || ERROR_PAGE_TEXT[500];
|
|
664
585
|
context.res.end(createErrorDocument(status, text));
|
|
665
586
|
}
|
|
666
|
-
|
|
667
587
|
}
|
|
668
588
|
/* eslint-enable max-lines */
|