@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.
Files changed (113) hide show
  1. package/CHANGELOG.md +110 -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 +25 -52
  29. package/dist/js/modern/server/modern-server-split.js +0 -11
  30. package/dist/js/modern/server/modern-server.js +87 -167
  31. package/dist/js/modern/utils.js +12 -27
  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 +25 -72
  62. package/dist/js/node/server/modern-server-split.js +0 -13
  63. package/dist/js/node/server/modern-server.js +87 -196
  64. package/dist/js/node/utils.js +13 -52
  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 +339 -0
  100. package/dist/js/treeshaking/server/modern-server-split.js +152 -0
  101. package/dist/js/treeshaking/server/modern-server.js +946 -0
  102. package/dist/js/treeshaking/type.js +1 -0
  103. package/dist/js/treeshaking/utils.js +90 -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 +2 -3
  112. package/dist/types/worker-server.d.ts +16 -0
  113. 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, ((_config$output = config.output) === null || _config$output === void 0 ? void 0 : _config$output.path) || 'dist');
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; // process.env.BUILD_TYPE = `${this.staticGenerate ? 'ssg' : 'ssr'}`;
102
- } // server prepare
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); // proxy handler, each proxy has own handler
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
- } // start file reader
123
-
94
+ }
124
95
 
96
+ // start file reader
125
97
  this.reader.init();
126
98
  app.on('close', () => {
127
99
  this.reader.close();
128
- }); // use preset routes priority
100
+ });
129
101
 
102
+ // use preset routes priority
130
103
  const usageRoutes = this.filterRoutes(this.getRoutes());
131
- this.router.reset(usageRoutes); // warmup ssr bundle in production env
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); // Only work when without setting `assetPrefix`.
136
- // Setting `assetPrefix` means these resources should be uploaded to CDN.
109
+ await this.prepareBeforeRouteHandler(usageRoutes, distDir);
137
110
 
138
- const staticPathRegExp = getStaticReg(this.conf.output || {});
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); // execute after staticFileHandler, can rename to staticFallbackHandler if needed.
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)); // compose middlewares to http handler
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
- } // eslint-disable-next-line consistent-return
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
- } // exposed requestHandler
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
- } // read routes from spec file
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
- } // add promisify request handler to server
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
- } // return 404 page
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
- } // gather frame extension and get framework handler
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 || {}; // server hook, gather plugin inject
249
+ } = options || {};
284
250
 
251
+ // server hook, gather plugin inject
285
252
  const _createMiddlewareColl = createMiddlewareCollecter(),
286
- {
287
- getMiddlewares
288
- } = _createMiddlewareColl,
289
- collector = _objectWithoutProperties(_createMiddlewareColl, _excluded);
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); // get api or web server handler from server-framework plugin
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
- } // warmup ssr function
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); // if error, just throw and let process die
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; // match routes in the route spec
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
- } // route is api service
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
- const afterMatchContext = createAfterMatchContext(context, route.entryName); // only full mode run server hook
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; // redirect to another url
440
-
391
+ } = afterMatchContext.router;
392
+ // redirect to another url
441
393
  if (url) {
442
394
  this.redirect(res, url, status);
443
395
  return;
444
- } // rewrite to another entry
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
- } // frameWebHandler has process request
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
- } // React Router navigation
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()); // only full mode run server hook
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
- } // It will inject _SERVER_DATA twice, when SSG mode.
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
- } // compose handlers and create the final handler
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
- requestHandler(req, res, next = () => {// empty
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); // if no custom status page find
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; // check entryName, avoid matched '/' 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) {// just catch error when the rendering error occurred in the custom error page.
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 */