@modern-js/server 0.0.0-plugins-202111301002 → 0.0.0-runtime-2021112193858

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 (87) hide show
  1. package/CHANGELOG.md +59 -0
  2. package/dist/js/modern/dev-tools/babel/register.js +2 -2
  3. package/dist/js/modern/dev-tools/mock/getMockData.js +2 -2
  4. package/dist/js/modern/libs/context/context.js +15 -7
  5. package/dist/js/modern/libs/context/index.js +2 -2
  6. package/dist/js/modern/libs/hook-api/route.js +37 -0
  7. package/dist/js/modern/libs/{hook-api.js → hook-api/template.js} +0 -0
  8. package/dist/js/modern/libs/{measure.js → metrics.js} +2 -2
  9. package/dist/js/modern/libs/proxy.js +2 -2
  10. package/dist/js/modern/libs/render/cache/__tests__/cache.test.js +2 -2
  11. package/dist/js/modern/libs/render/cache/index.js +2 -2
  12. package/dist/js/modern/libs/render/ssr.js +1 -1
  13. package/dist/js/modern/libs/route/index.js +4 -0
  14. package/dist/js/modern/libs/route/matcher.js +4 -0
  15. package/dist/js/modern/libs/route/route.js +1 -1
  16. package/dist/js/modern/server/dev-server/dev-server-split.js +28 -0
  17. package/dist/js/modern/server/{dev-server.js → dev-server/dev-server.js} +41 -22
  18. package/dist/js/modern/server/dev-server/index.js +2 -0
  19. package/dist/js/modern/server/index.js +65 -63
  20. package/dist/js/modern/server/modern-server-split.js +81 -0
  21. package/dist/js/modern/server/modern-server.js +121 -70
  22. package/dist/js/modern/utils.js +11 -3
  23. package/dist/js/node/dev-tools/babel/register.js +2 -2
  24. package/dist/js/node/dev-tools/mock/getMockData.js +2 -2
  25. package/dist/js/node/libs/context/context.js +15 -7
  26. package/dist/js/node/libs/context/index.js +2 -2
  27. package/dist/js/node/libs/hook-api/route.js +46 -0
  28. package/dist/js/node/libs/{hook-api.js → hook-api/template.js} +0 -0
  29. package/dist/js/node/libs/{measure.js → metrics.js} +3 -3
  30. package/dist/js/node/libs/proxy.js +2 -2
  31. package/dist/js/node/libs/render/cache/__tests__/cache.test.js +2 -2
  32. package/dist/js/node/libs/render/cache/index.js +2 -2
  33. package/dist/js/node/libs/render/ssr.js +1 -1
  34. package/dist/js/node/libs/route/index.js +4 -0
  35. package/dist/js/node/libs/route/matcher.js +4 -0
  36. package/dist/js/node/libs/route/route.js +1 -1
  37. package/dist/js/node/server/dev-server/dev-server-split.js +41 -0
  38. package/dist/js/node/server/{dev-server.js → dev-server/dev-server.js} +42 -21
  39. package/dist/js/node/server/dev-server/index.js +27 -0
  40. package/dist/js/node/server/index.js +72 -64
  41. package/dist/js/node/server/modern-server-split.js +97 -0
  42. package/dist/js/node/server/modern-server.js +124 -71
  43. package/dist/js/node/utils.js +14 -4
  44. package/dist/types/libs/context/context.d.ts +5 -5
  45. package/dist/types/libs/context/index.d.ts +3 -3
  46. package/dist/types/libs/hook-api/route.d.ts +13 -0
  47. package/dist/types/libs/{hook-api.d.ts → hook-api/template.d.ts} +0 -0
  48. package/dist/types/libs/metrics.d.ts +3 -0
  49. package/dist/types/libs/render/type.d.ts +2 -2
  50. package/dist/types/libs/route/index.d.ts +1 -0
  51. package/dist/types/libs/route/matcher.d.ts +1 -0
  52. package/dist/types/libs/route/route.d.ts +2 -10
  53. package/dist/types/server/dev-server/dev-server-split.d.ts +15 -0
  54. package/dist/types/server/{dev-server.d.ts → dev-server/dev-server.d.ts} +6 -5
  55. package/dist/types/server/dev-server/index.d.ts +2 -0
  56. package/dist/types/server/index.d.ts +3 -1
  57. package/dist/types/server/modern-server-split.d.ts +26 -0
  58. package/dist/types/server/modern-server.d.ts +20 -12
  59. package/dist/types/type.d.ts +9 -4
  60. package/dist/types/utils.d.ts +3 -2
  61. package/package.json +18 -20
  62. package/src/libs/context/context.ts +12 -8
  63. package/src/libs/context/index.ts +3 -3
  64. package/src/libs/hook-api/route.ts +38 -0
  65. package/src/libs/{hook-api.ts → hook-api/template.ts} +0 -0
  66. package/src/libs/{measure.ts → metrics.ts} +3 -3
  67. package/src/libs/render/ssr.ts +1 -1
  68. package/src/libs/render/type.ts +2 -2
  69. package/src/libs/route/index.ts +4 -0
  70. package/src/libs/route/matcher.ts +4 -0
  71. package/src/libs/route/route.ts +4 -20
  72. package/src/server/{web-server.ts → dev-server/dev-server-split.ts} +12 -14
  73. package/src/server/{dev-server.ts → dev-server/dev-server.ts} +62 -33
  74. package/src/server/dev-server/index.ts +2 -0
  75. package/src/server/index.ts +81 -48
  76. package/src/server/modern-server-split.ts +97 -0
  77. package/src/server/modern-server.ts +140 -90
  78. package/src/type.ts +9 -4
  79. package/src/utils.ts +16 -2
  80. package/dist/js/modern/server/api-server.js +0 -36
  81. package/dist/js/modern/server/web-server.js +0 -30
  82. package/dist/js/node/server/api-server.js +0 -50
  83. package/dist/js/node/server/web-server.js +0 -44
  84. package/dist/types/libs/measure.d.ts +0 -3
  85. package/dist/types/server/api-server.d.ts +0 -17
  86. package/dist/types/server/web-server.d.ts +0 -15
  87. package/src/server/api-server.ts +0 -47
@@ -1,16 +1,24 @@
1
- import {
2
- IncomingMessage,
3
- ServerResponse,
4
- createServer,
5
- Server as httpServer,
6
- } from 'http';
7
- import { createServer as createHttpsServer } from 'https';
1
+ import { IncomingMessage, ServerResponse, Server as httpServer } from 'http';
2
+ import path from 'path';
8
3
  import { serverManager } from '@modern-js/server-plugin';
9
4
  import { logger as defaultLogger } from '@modern-js/utils';
10
- import { ModernServerOptions, ServerHookRunner, ReadyOptions } from '../type';
5
+ import {
6
+ AppContext,
7
+ initAppContext,
8
+ initAppDir,
9
+ loadUserConfig,
10
+ ConfigContext,
11
+ UserConfig,
12
+ } from '@modern-js/core';
11
13
  import { ModernServer } from './modern-server';
12
14
  import type { ModernDevServer } from './dev-server';
13
- import { measure as defaultMeasure } from '@/libs/measure';
15
+ import {
16
+ ModernAPIServer,
17
+ ModernSSRServer,
18
+ ModernWebServer,
19
+ } from './modern-server-split';
20
+ import { ModernServerOptions, ServerHookRunner, ReadyOptions } from '@/type';
21
+ import { metrics as defaultMetrics } from '@/libs/metrics';
14
22
 
15
23
  export class Server {
16
24
  public options: ModernServerOptions;
@@ -23,9 +31,6 @@ export class Server {
23
31
 
24
32
  constructor(options: ModernServerOptions) {
25
33
  this.options = options;
26
- options.plugins?.forEach(p => {
27
- serverManager.usePlugin(p);
28
- });
29
34
  }
30
35
 
31
36
  public getRequestHandler() {
@@ -41,38 +46,24 @@ export class Server {
41
46
 
42
47
  public async init() {
43
48
  const { options } = this;
44
- this.runner = await serverManager.init({});
45
-
46
- const { logger, measure } = await this.runner.create(
47
- {
48
- loggerOptions: options.logger,
49
- measureOptions: options.measure,
50
- },
51
- { onLast: () => ({} as any) },
52
- );
53
49
 
54
- options.logger = options.logger || logger || defaultLogger;
55
- options.measure = options.measure || measure || defaultMeasure;
50
+ options.logger = options.logger || defaultLogger;
51
+ options.metrics = options.metrics || defaultMetrics;
56
52
 
53
+ // initialize server
57
54
  if (options.dev) {
58
55
  this.server = this.createDevServer();
59
-
60
- // check if https is configured when start dev server
61
- const devHttpsOption =
62
- typeof options.dev === 'object' && options.dev.https;
63
- if (devHttpsOption) {
64
- const { genHttpsOptions } = require('@/dev-tools/https');
65
- const httpsOptions = await genHttpsOptions(devHttpsOption);
66
- this.app = createHttpsServer(httpsOptions, this.getRequestHandler());
67
- } else {
68
- this.app = createServer(this.getRequestHandler());
69
- }
70
56
  } else {
71
57
  this.server = this.createProdServer();
72
- this.app = createServer(this.getRequestHandler());
73
58
  }
59
+ // check if https is configured when start dev server
60
+ this.app = await this.server.createHTTPServer(this.getRequestHandler());
61
+
62
+ this.runner = await this.createHookRunner();
63
+
64
+ // runner can only be used after server init
65
+ await this.server.init(this.runner);
74
66
 
75
- await this.server.init();
76
67
  return this;
77
68
  }
78
69
 
@@ -103,28 +94,70 @@ export class Server {
103
94
  const { options } = this;
104
95
 
105
96
  if (options.apiOnly) {
106
- const { APIModernServer } = require('./api-server');
107
- return new APIModernServer(options, this.runner);
97
+ return new ModernAPIServer(options);
98
+ } else if (options.ssrOnly) {
99
+ return new ModernSSRServer(options);
108
100
  } else if (options.webOnly) {
109
- const { WebModernServer } = require('./web-server');
110
- return new WebModernServer(options, this.runner);
101
+ return new ModernWebServer(options);
111
102
  } else {
112
- return new ModernServer(options, this.runner);
103
+ return new ModernServer(options);
113
104
  }
114
105
  }
115
106
 
116
107
  private createDevServer() {
117
108
  const { options } = this;
109
+ const {
110
+ ModernAPIDevServer,
111
+ ModernSSRDevServer,
112
+ ModernDevServer,
113
+ } = require('./dev-server');
118
114
 
119
115
  if (options.apiOnly) {
120
- const { APIModernDevServer } = require('./api-server');
121
- return new APIModernDevServer(options, this.runner);
122
- } else if (options.webOnly) {
123
- const { WebModernDevServer } = require('./web-server');
124
- return new WebModernDevServer(options, this.runner);
116
+ return new ModernAPIDevServer(options);
117
+ } else if (options.ssrOnly) {
118
+ return new ModernSSRDevServer(options);
125
119
  } else {
126
- const { ModernDevServer } = require('./dev-server');
127
- return new ModernDevServer(options, this.runner);
120
+ return new ModernDevServer(options);
128
121
  }
129
122
  }
123
+
124
+ private async createHookRunner() {
125
+ const { options } = this;
126
+
127
+ options.plugins?.forEach(p => {
128
+ serverManager.usePlugin(p);
129
+ });
130
+
131
+ const appContext = await this.initAppContext();
132
+ serverManager.run(() => {
133
+ ConfigContext.set(this.options.config as UserConfig);
134
+ AppContext.set({
135
+ ...appContext,
136
+ distDirectory: path.join(
137
+ options.pwd,
138
+ options.config.output.path || 'dist',
139
+ ),
140
+ });
141
+ });
142
+
143
+ return serverManager.init({});
144
+ }
145
+
146
+ private async initAppContext() {
147
+ const appDirectory = await initAppDir();
148
+
149
+ const loaded = await loadUserConfig(appDirectory);
150
+
151
+ const plugins = this.options.plugins?.map(p => ({
152
+ server: p,
153
+ cli: undefined,
154
+ }));
155
+
156
+ const appContext = initAppContext(
157
+ appDirectory,
158
+ plugins || [],
159
+ loaded.filePath,
160
+ );
161
+ return appContext;
162
+ }
130
163
  }
@@ -0,0 +1,97 @@
1
+ import { APIServerStartInput } from '@modern-js/server-plugin';
2
+ import { ModernServer } from './modern-server';
3
+ import { mergeExtension } from '@/utils';
4
+ import { ModernRoute, ModernRouteInterface, RouteMatcher } from '@/libs/route';
5
+ import { ApiServerMode } from '@/constants';
6
+ import { ModernServerContext } from '@/libs/context';
7
+
8
+ export class ModernSSRServer extends ModernServer {
9
+ // Todo should not invoke any route hook in modernSSRServer
10
+
11
+ protected async warmupSSRBundle() {
12
+ // empty
13
+ }
14
+
15
+ protected verifyMatch(context: ModernServerContext, matched: RouteMatcher) {
16
+ if (matched.generate().isApi) {
17
+ this.render404(context);
18
+ }
19
+ }
20
+
21
+ protected prepareAPIHandler(
22
+ _m: ApiServerMode,
23
+ _: APIServerStartInput['config'],
24
+ ) {
25
+ return null as any;
26
+ }
27
+
28
+ protected async prepareWebHandler(
29
+ extension: ReturnType<typeof mergeExtension>,
30
+ ) {
31
+ return super.prepareWebHandler(extension);
32
+ }
33
+
34
+ // protected filterRoutes(routes: ModernRouteInterface[]) {
35
+ // return routes.filter(route => route.entryName);
36
+ // }
37
+
38
+ protected async preServerInit() {
39
+ // empty
40
+ }
41
+ }
42
+
43
+ export class ModernAPIServer extends ModernServer {
44
+ protected async emitRouteHook(_: string, _input: any) {
45
+ // empty
46
+ }
47
+
48
+ protected async warmupSSRBundle() {
49
+ // empty
50
+ }
51
+
52
+ protected prepareWebHandler(_: ReturnType<typeof mergeExtension>) {
53
+ return null as any;
54
+ }
55
+
56
+ protected async prepareAPIHandler(
57
+ mode: ApiServerMode,
58
+ extension: APIServerStartInput['config'],
59
+ ) {
60
+ return super.prepareAPIHandler(mode, extension);
61
+ }
62
+
63
+ protected filterRoutes(routes: ModernRouteInterface[]) {
64
+ return routes.filter(route => route.isApi);
65
+ }
66
+
67
+ protected async preServerInit() {
68
+ // empty
69
+ }
70
+ }
71
+
72
+ export class ModernWebServer extends ModernServer {
73
+ protected async warmupSSRBundle() {
74
+ // empty
75
+ }
76
+
77
+ protected async handleAPI(context: ModernServerContext) {
78
+ const { proxyTarget } = this;
79
+ if (!proxyTarget?.api) {
80
+ this.proxy();
81
+ } else {
82
+ this.render404(context);
83
+ }
84
+ }
85
+
86
+ protected async handleWeb(context: ModernServerContext, route: ModernRoute) {
87
+ const { proxyTarget } = this;
88
+
89
+ if (route.isSSR && proxyTarget?.ssr) {
90
+ return this.proxy();
91
+ } else {
92
+ // if no proxyTarget but access web server, degradation to csr
93
+ route.isSSR = false;
94
+ return super.handleWeb(context, route);
95
+ }
96
+ }
97
+ }
@@ -1,10 +1,10 @@
1
1
  /* eslint-disable max-lines */
2
- import { IncomingMessage, ServerResponse, Server } from 'http';
2
+ import { IncomingMessage, ServerResponse, Server, createServer } from 'http';
3
3
  import util from 'util';
4
4
  import path from 'path';
5
5
  import { fs, ROUTE_SPEC_FILE } from '@modern-js/utils';
6
- import { Adapter } from '@modern-js/server-plugin';
7
- import { gather, createMiddlewareCollecter } from '@modern-js/server-utils';
6
+ import { Adapter, APIServerStartInput } from '@modern-js/server-plugin';
7
+ import { createMiddlewareCollecter } from '@modern-js/server-utils';
8
8
  import type { NormalizedConfig } from '@modern-js/core';
9
9
  import mime from 'mime-types';
10
10
  import axios from 'axios';
@@ -12,17 +12,22 @@ import {
12
12
  ModernServerOptions,
13
13
  NextFunction,
14
14
  ServerHookRunner,
15
- Measure,
15
+ Metrics,
16
16
  Logger,
17
17
  ReadyOptions,
18
18
  ConfWithBFF,
19
- } from '../type';
20
- import { RouteMatchManager, ModernRouteInterface } from '../libs/route';
21
- import { createRenderHandler } from '../libs/render';
22
- import { createStaticFileHandler } from '../libs/serve-file';
23
- import { createErrorDocument, mergeExtension, noop } from '../utils';
24
- import * as reader from '../libs/render/reader';
25
- import { createProxyHandler, ProxyOptions } from '../libs/proxy';
19
+ } from '@/type';
20
+ import {
21
+ RouteMatchManager,
22
+ ModernRouteInterface,
23
+ ModernRoute,
24
+ RouteMatcher,
25
+ } from '@/libs/route';
26
+ import { createRenderHandler } from '@/libs/render';
27
+ import { createStaticFileHandler } from '@/libs/serve-file';
28
+ import { createErrorDocument, mergeExtension, noop } from '@/utils';
29
+ import * as reader from '@/libs/render/reader';
30
+ import { createProxyHandler, ProxyOptions } from '@/libs/proxy';
26
31
  import { createContext, ModernServerContext } from '@/libs/context';
27
32
  import {
28
33
  AGGRED_DIR,
@@ -30,7 +35,8 @@ import {
30
35
  ERROR_DIGEST,
31
36
  ERROR_PAGE_TEXT,
32
37
  } from '@/constants';
33
- import { createTemplateAPI } from '@/libs/hook-api';
38
+ import { createTemplateAPI } from '@/libs/hook-api/template';
39
+ import { createRouteAPI } from '@/libs/hook-api/route';
34
40
 
35
41
  type ModernServerHandler = (
36
42
  context: ModernServerContext,
@@ -63,11 +69,13 @@ export class ModernServer {
63
69
 
64
70
  protected presetRoutes?: ModernRouteInterface[];
65
71
 
72
+ protected runner!: ServerHookRunner;
73
+
66
74
  protected readonly logger: Logger;
67
75
 
68
- protected readonly measure: Measure;
76
+ protected readonly metrics: Metrics;
69
77
 
70
- private readonly runner: ServerHookRunner;
78
+ protected readonly proxyTarget: ModernServerOptions['proxyTarget'];
71
79
 
72
80
  private readonly isDev: boolean = false;
73
81
 
@@ -85,30 +93,28 @@ export class ModernServer {
85
93
 
86
94
  private proxyHandler: ReturnType<typeof createProxyHandler> = null;
87
95
 
88
- constructor(
89
- {
90
- pwd,
91
- config,
92
- dev,
93
- routes,
94
- staticGenerate,
95
- logger,
96
- measure,
97
- }: ModernServerOptions,
98
- runner: ServerHookRunner,
99
- ) {
96
+ constructor({
97
+ pwd,
98
+ config,
99
+ dev,
100
+ routes,
101
+ staticGenerate,
102
+ logger,
103
+ metrics,
104
+ proxyTarget,
105
+ }: ModernServerOptions) {
100
106
  require('ignore-styles');
101
107
  this.isDev = Boolean(dev);
102
108
 
103
109
  this.pwd = pwd;
104
- this.distDir = path.join(pwd, config.output.path || '');
110
+ this.distDir = path.join(pwd, config.output.path || 'dist');
105
111
  this.workDir = this.isDev ? pwd : this.distDir;
106
112
  this.conf = config;
107
- this.runner = runner;
108
113
  this.logger = logger!;
109
- this.measure = measure!;
114
+ this.metrics = metrics!;
110
115
  this.router = new RouteMatchManager();
111
116
  this.presetRoutes = routes;
117
+ this.proxyTarget = proxyTarget;
112
118
 
113
119
  if (staticGenerate) {
114
120
  this.staticGenerate = staticGenerate;
@@ -122,7 +128,9 @@ export class ModernServer {
122
128
  }
123
129
 
124
130
  // server prepare
125
- public async init() {
131
+ public async init(runner: ServerHookRunner) {
132
+ this.runner = runner;
133
+
126
134
  const { distDir, isDev, staticGenerate, conf } = this;
127
135
 
128
136
  this.addHandler((ctx: ModernServerContext, next: NextFunction) => {
@@ -198,16 +206,14 @@ export class ModernServer {
198
206
  reader.close();
199
207
  }
200
208
 
201
- // warmup ssr function
202
- protected warmupSSRBundle() {
203
- const { distDir } = this;
204
- const bundles = this.router.getBundles();
205
-
206
- bundles.forEach(bundle => {
207
- const filepath = path.join(distDir, bundle!);
208
- // if error, just throw and let process die
209
- require(filepath);
210
- });
209
+ public async createHTTPServer(
210
+ handler: (
211
+ req: IncomingMessage,
212
+ res: ServerResponse,
213
+ next?: () => void,
214
+ ) => void,
215
+ ) {
216
+ return createServer(handler);
211
217
  }
212
218
 
213
219
  // read route spec from route.json
@@ -239,14 +245,7 @@ export class ModernServer {
239
245
 
240
246
  // gather frame extension and get framework handler
241
247
  protected async prepareFrameHandler() {
242
- const { workDir, runner, conf } = this;
243
-
244
- // inner tool, gather user inject
245
- let userAPIExt = [];
246
- let userWebExt = [];
247
- if (!conf.server.disableUserExtension) {
248
- ({ api: userAPIExt, web: userWebExt } = gather(workDir));
249
- }
248
+ const { workDir, runner } = this;
250
249
 
251
250
  // server hook, gather plugin inject
252
251
  const { getMiddlewares, ...collector } = createMiddlewareCollecter();
@@ -259,7 +258,7 @@ export class ModernServer {
259
258
 
260
259
  // get api or web server handler from server-framework plugin
261
260
  if (await fs.pathExists(path.join(serverDir))) {
262
- const webExtension = mergeExtension(pluginWebExt, userWebExt);
261
+ const webExtension = mergeExtension(pluginWebExt);
263
262
  this.frameWebHandler = await this.prepareWebHandler(webExtension);
264
263
  }
265
264
 
@@ -269,14 +268,16 @@ export class ModernServer {
269
268
  : ApiServerMode.func;
270
269
 
271
270
  // if use lambda/, mean framework style of writing, then discard user extension
272
- const apiExtension = mergeExtension(
273
- pluginAPIExt,
274
- mode === ApiServerMode.frame ? [] : userAPIExt,
275
- );
271
+ const apiExtension = mergeExtension(pluginAPIExt);
276
272
  this.frameAPIHandler = await this.prepareAPIHandler(mode, apiExtension);
277
273
  }
278
274
  }
279
275
 
276
+ // Todo
277
+ protected async proxy() {
278
+ return null as any;
279
+ }
280
+
280
281
  /* —————————————————————— function will be overwrite —————————————————————— */
281
282
  protected async prepareWebHandler(
282
283
  extension: ReturnType<typeof mergeExtension>,
@@ -294,7 +295,7 @@ export class ModernServer {
294
295
 
295
296
  protected async prepareAPIHandler(
296
297
  mode: ApiServerMode,
297
- extension: ReturnType<typeof mergeExtension>,
298
+ extension: APIServerStartInput['config'],
298
299
  ) {
299
300
  const { workDir, runner, conf } = this;
300
301
  const { bff } = conf as ConfWithBFF;
@@ -305,7 +306,7 @@ export class ModernServer {
305
306
  pwd: workDir,
306
307
  mode,
307
308
  config: extension,
308
- prefix,
309
+ prefix: Array.isArray(prefix) ? prefix[0] : prefix,
309
310
  },
310
311
  { onLast: () => null as any },
311
312
  );
@@ -315,62 +316,89 @@ export class ModernServer {
315
316
  return routes;
316
317
  }
317
318
 
319
+ protected async emitRouteHook(
320
+ eventName: 'beforeMatch' | 'afterMatch' | 'beforeRender' | 'afterRender',
321
+ input: any,
322
+ ) {
323
+ return this.runner[eventName](input, { onLast: noop as any });
324
+ }
325
+
326
+ // warmup ssr function
327
+ protected warmupSSRBundle() {
328
+ const { distDir } = this;
329
+ const bundles = this.router.getBundles();
330
+
331
+ bundles.forEach(bundle => {
332
+ const filepath = path.join(distDir, bundle as string);
333
+ // if error, just throw and let process die
334
+ require(filepath);
335
+ });
336
+ }
337
+
318
338
  protected async preServerInit() {
319
- const { conf } = this;
339
+ const { conf, runner } = this;
320
340
  const preMiddleware: ModernServerAsyncHandler[] =
321
- await this.runner.preServerInit(conf);
341
+ await runner.preServerInit(conf);
322
342
 
323
- preMiddleware.forEach(mid => {
343
+ preMiddleware.flat().forEach(mid => {
324
344
  this.addHandler(mid);
325
345
  });
326
346
  }
327
347
 
328
- private prepareFavicons(
329
- favicon: string | undefined,
330
- faviconByEntries?: Record<string, string | undefined>,
331
- ) {
332
- const faviconNames = [];
333
- if (favicon) {
334
- faviconNames.push(favicon.substring(favicon.lastIndexOf('/') + 1));
335
- }
336
- if (faviconByEntries) {
337
- Object.keys(faviconByEntries).forEach(f => {
338
- const curFavicon = faviconByEntries[f];
339
- if (curFavicon) {
340
- faviconNames.push(
341
- curFavicon.substring(curFavicon.lastIndexOf('/') + 1),
342
- );
343
- }
344
- });
348
+ protected async handleAPI(context: ModernServerContext) {
349
+ const { req, res } = context;
350
+
351
+ if (!this.frameAPIHandler) {
352
+ throw new Error('can not found api hanlder');
345
353
  }
346
- return faviconNames;
354
+
355
+ await this.frameAPIHandler(req, res);
347
356
  }
348
357
 
349
- /* —————————————————————— private function —————————————————————— */
358
+ protected async handleWeb(context: ModernServerContext, route: ModernRoute) {
359
+ return this.routeRenderHandler(context, route);
360
+ }
361
+
362
+ protected verifyMatch(_c: ModernServerContext, _m: RouteMatcher) {
363
+ // empty
364
+ }
350
365
 
366
+ /* —————————————————————— private function —————————————————————— */
351
367
  // handler route.json, include api / csr / ssr
352
368
  // eslint-disable-next-line max-statements
353
369
  private async routeHandler(context: ModernServerContext) {
354
370
  const { req, res } = context;
355
371
 
372
+ await this.emitRouteHook('beforeMatch', { context });
373
+
356
374
  // match routes in the route spec
357
375
  const matched = this.router.match(context.url);
358
376
  if (!matched) {
359
377
  this.render404(context);
360
378
  return;
379
+ } else {
380
+ this.verifyMatch(context, matched);
381
+ }
382
+
383
+ if (res.headersSent) {
384
+ return;
361
385
  }
362
386
 
363
- const route = matched.generate();
364
- const params = matched.parseURLParams(context.url);
387
+ const routeAPI = createRouteAPI(matched, this.router);
388
+ await this.emitRouteHook('afterMatch', { context, routeAPI });
389
+
390
+ if (res.headersSent) {
391
+ return;
392
+ }
393
+
394
+ const { current } = routeAPI as any;
395
+ const route: ModernRoute = current.generate();
396
+ const params = current.parseURLParams(context.url);
365
397
  context.setParams(params);
366
398
 
367
399
  // route is api service
368
400
  if (route.isApi) {
369
- if (!this.frameAPIHandler) {
370
- throw new Error('can not found api hanlder');
371
- }
372
-
373
- await this.frameAPIHandler(req, res);
401
+ this.handleAPI(context);
374
402
  return;
375
403
  }
376
404
 
@@ -383,7 +411,11 @@ export class ModernServer {
383
411
  return;
384
412
  }
385
413
 
386
- const file = await this.routeRenderHandler(context, route);
414
+ if (route.entryName) {
415
+ await this.emitRouteHook('beforeRender', { context });
416
+ }
417
+
418
+ const file = await this.handleWeb(context, route);
387
419
  if (!file) {
388
420
  this.render404(context);
389
421
  return;
@@ -399,10 +431,7 @@ export class ModernServer {
399
431
  let response = file.content;
400
432
  if (route.entryName) {
401
433
  const templateAPI = createTemplateAPI(file.content.toString());
402
- await this.runner.afterRender(
403
- { context, templateAPI },
404
- { onLast: noop as any },
405
- );
434
+ await this.emitRouteHook('afterRender', { context, templateAPI });
406
435
  await this.injectMicroFE(context, templateAPI);
407
436
  response = templateAPI.get();
408
437
  }
@@ -519,7 +548,7 @@ export class ModernServer {
519
548
  res.statusCode = 200;
520
549
  const context: ModernServerContext = createContext(req, res, {
521
550
  logger: this.logger,
522
- measure: this.measure,
551
+ metrics: this.metrics,
523
552
  });
524
553
 
525
554
  try {
@@ -565,5 +594,26 @@ export class ModernServer {
565
594
  const text = ERROR_PAGE_TEXT[status] || ERROR_PAGE_TEXT[500];
566
595
  res.end(createErrorDocument(status, text));
567
596
  }
597
+
598
+ private prepareFavicons(
599
+ favicon: string | undefined,
600
+ faviconByEntries?: Record<string, string | undefined>,
601
+ ) {
602
+ const faviconNames = [];
603
+ if (favicon) {
604
+ faviconNames.push(favicon.substring(favicon.lastIndexOf('/') + 1));
605
+ }
606
+ if (faviconByEntries) {
607
+ Object.keys(faviconByEntries).forEach(f => {
608
+ const curFavicon = faviconByEntries[f];
609
+ if (curFavicon) {
610
+ faviconNames.push(
611
+ curFavicon.substring(curFavicon.lastIndexOf('/') + 1),
612
+ );
613
+ }
614
+ });
615
+ }
616
+ return faviconNames;
617
+ }
568
618
  }
569
619
  /* eslint-enable max-lines */
package/src/type.ts CHANGED
@@ -2,7 +2,7 @@ import { Buffer } from 'buffer';
2
2
  import type Webpack from 'webpack';
3
3
  import { serverManager } from '@modern-js/server-plugin';
4
4
  import type { NormalizedConfig } from '@modern-js/core';
5
- import type { Measure, Logger, NextFunction } from '@modern-js/types/server';
5
+ import type { Metrics, Logger, NextFunction } from '@modern-js/types/server';
6
6
  import { ModernRouteInterface } from './libs/route';
7
7
 
8
8
  declare module '@modern-js/core' {
@@ -45,11 +45,16 @@ export type ModernServerOptions = {
45
45
  staticGenerate?: boolean;
46
46
  customServer?: boolean;
47
47
  loggerOptions?: Record<string, string>;
48
- measureOptions?: Record<string, string>;
48
+ metricsOptions?: Record<string, string>;
49
49
  logger?: Logger;
50
- measure?: Measure;
50
+ metrics?: Metrics;
51
51
  apiOnly?: boolean;
52
+ ssrOnly?: boolean;
52
53
  webOnly?: boolean;
54
+ proxyTarget?: {
55
+ ssr?: string;
56
+ api?: string;
57
+ };
53
58
  };
54
59
 
55
60
  export type RenderResult = {
@@ -71,4 +76,4 @@ export type ServerHookRunner = Then<ReturnType<typeof serverManager.init>>;
71
76
 
72
77
  export type ReadyOptions = { routes?: ModernRouteInterface[] };
73
78
 
74
- export type { Measure, Logger, NextFunction };
79
+ export type { Metrics, Logger, NextFunction };