@modern-js/prod-server 2.0.0-beta.0 → 2.0.0-beta.1

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