@modern-js/server 1.1.3-beta.1 → 1.1.5-beta.0

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 (69) hide show
  1. package/CHANGELOG.md +42 -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/{measure.js → metrics.js} +2 -2
  7. package/dist/js/modern/libs/proxy.js +2 -2
  8. package/dist/js/modern/libs/render/cache/__tests__/cache.test.js +2 -2
  9. package/dist/js/modern/libs/render/cache/index.js +2 -2
  10. package/dist/js/modern/libs/render/cache/type.js +0 -1
  11. package/dist/js/modern/libs/render/index.js +6 -2
  12. package/dist/js/modern/libs/render/ssr.js +3 -2
  13. package/dist/js/modern/libs/route/route.js +1 -1
  14. package/dist/js/modern/server/dev-server/dev-server-split.js +2 -6
  15. package/dist/js/modern/server/dev-server/dev-server.js +12 -3
  16. package/dist/js/modern/server/dev-server/index.js +1 -1
  17. package/dist/js/modern/server/index.js +19 -16
  18. package/dist/js/modern/server/modern-server-split.js +55 -6
  19. package/dist/js/modern/server/modern-server.js +92 -58
  20. package/dist/js/modern/type.js +0 -1
  21. package/dist/js/modern/utils.js +9 -1
  22. package/dist/js/node/dev-tools/babel/register.js +2 -2
  23. package/dist/js/node/dev-tools/mock/getMockData.js +2 -2
  24. package/dist/js/node/libs/context/context.js +15 -7
  25. package/dist/js/node/libs/context/index.js +2 -2
  26. package/dist/js/node/libs/{measure.js → metrics.js} +3 -3
  27. package/dist/js/node/libs/proxy.js +2 -2
  28. package/dist/js/node/libs/render/cache/__tests__/cache.test.js +2 -2
  29. package/dist/js/node/libs/render/cache/index.js +2 -2
  30. package/dist/js/node/libs/render/index.js +6 -2
  31. package/dist/js/node/libs/render/ssr.js +3 -2
  32. package/dist/js/node/libs/route/route.js +1 -1
  33. package/dist/js/node/server/dev-server/dev-server-split.js +5 -9
  34. package/dist/js/node/server/dev-server/dev-server.js +12 -3
  35. package/dist/js/node/server/dev-server/index.js +4 -4
  36. package/dist/js/node/server/index.js +18 -14
  37. package/dist/js/node/server/modern-server-split.js +61 -9
  38. package/dist/js/node/server/modern-server.js +93 -59
  39. package/dist/js/node/utils.js +12 -2
  40. package/dist/types/libs/context/context.d.ts +5 -5
  41. package/dist/types/libs/context/index.d.ts +3 -3
  42. package/dist/types/libs/metrics.d.ts +3 -0
  43. package/dist/types/libs/render/index.d.ts +10 -1
  44. package/dist/types/libs/render/ssr.d.ts +2 -1
  45. package/dist/types/libs/render/type.d.ts +2 -21
  46. package/dist/types/libs/route/route.d.ts +2 -10
  47. package/dist/types/server/dev-server/dev-server-split.d.ts +3 -4
  48. package/dist/types/server/dev-server/index.d.ts +1 -1
  49. package/dist/types/server/modern-server-split.d.ts +15 -5
  50. package/dist/types/server/modern-server.d.ts +14 -7
  51. package/dist/types/type.d.ts +11 -5
  52. package/dist/types/utils.d.ts +2 -1
  53. package/package.json +7 -7
  54. package/src/libs/context/context.ts +12 -8
  55. package/src/libs/context/index.ts +3 -3
  56. package/src/libs/{measure.ts → metrics.ts} +3 -3
  57. package/src/libs/render/index.ts +21 -11
  58. package/src/libs/render/ssr.ts +5 -1
  59. package/src/libs/render/type.ts +3 -16
  60. package/src/libs/route/route.ts +4 -20
  61. package/src/server/dev-server/dev-server-split.ts +3 -7
  62. package/src/server/dev-server/dev-server.ts +15 -13
  63. package/src/server/dev-server/index.ts +1 -1
  64. package/src/server/index.ts +24 -14
  65. package/src/server/modern-server-split.ts +59 -7
  66. package/src/server/modern-server.ts +105 -67
  67. package/src/type.ts +12 -5
  68. package/src/utils.ts +14 -0
  69. package/dist/types/libs/measure.d.ts +0 -3
@@ -1,13 +1,26 @@
1
1
  import { APIServerStartInput } from '@modern-js/server-plugin';
2
2
  import { ModernServer } from './modern-server';
3
3
  import { mergeExtension } from '@/utils';
4
- import { ModernRouteInterface } from '@/libs/route';
4
+ import { ModernRoute, ModernRouteInterface, RouteMatcher } from '@/libs/route';
5
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
+ }
6
20
 
7
- export class WebModernServer extends ModernServer {
8
21
  protected prepareAPIHandler(
9
22
  _m: ApiServerMode,
10
- _: ReturnType<typeof mergeExtension>,
23
+ _: APIServerStartInput['config'],
11
24
  ) {
12
25
  return null as any;
13
26
  }
@@ -18,12 +31,24 @@ export class WebModernServer extends ModernServer {
18
31
  return super.prepareWebHandler(extension);
19
32
  }
20
33
 
21
- protected filterRoutes(routes: ModernRouteInterface[]) {
22
- return routes.filter(route => route.entryName);
34
+ // protected filterRoutes(routes: ModernRouteInterface[]) {
35
+ // return routes.filter(route => route.entryName);
36
+ // }
37
+
38
+ protected async preServerInit() {
39
+ // empty
23
40
  }
24
41
  }
25
42
 
26
- export class APIModernServer extends ModernServer {
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
+
27
52
  protected prepareWebHandler(_: ReturnType<typeof mergeExtension>) {
28
53
  return null as any;
29
54
  }
@@ -40,6 +65,33 @@ export class APIModernServer extends ModernServer {
40
65
  }
41
66
 
42
67
  protected async preServerInit() {
43
- // noop
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
+ }
44
96
  }
45
97
  }
@@ -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,
@@ -68,7 +73,9 @@ export class ModernServer {
68
73
 
69
74
  protected readonly logger: Logger;
70
75
 
71
- protected readonly measure: Measure;
76
+ protected readonly metrics: Metrics;
77
+
78
+ protected readonly proxyTarget: ModernServerOptions['proxyTarget'];
72
79
 
73
80
  private readonly isDev: boolean = false;
74
81
 
@@ -93,19 +100,21 @@ export class ModernServer {
93
100
  routes,
94
101
  staticGenerate,
95
102
  logger,
96
- measure,
103
+ metrics,
104
+ proxyTarget,
97
105
  }: ModernServerOptions) {
98
106
  require('ignore-styles');
99
107
  this.isDev = Boolean(dev);
100
108
 
101
109
  this.pwd = pwd;
102
- this.distDir = path.join(pwd, config.output.path || '');
110
+ this.distDir = path.join(pwd, config.output.path || 'dist');
103
111
  this.workDir = this.isDev ? pwd : this.distDir;
104
112
  this.conf = config;
105
113
  this.logger = logger!;
106
- this.measure = measure!;
114
+ this.metrics = metrics!;
107
115
  this.router = new RouteMatchManager();
108
116
  this.presetRoutes = routes;
117
+ this.proxyTarget = proxyTarget;
109
118
 
110
119
  if (staticGenerate) {
111
120
  this.staticGenerate = staticGenerate;
@@ -207,18 +216,6 @@ export class ModernServer {
207
216
  return createServer(handler);
208
217
  }
209
218
 
210
- // warmup ssr function
211
- protected warmupSSRBundle() {
212
- const { distDir } = this;
213
- const bundles = this.router.getBundles();
214
-
215
- bundles.forEach(bundle => {
216
- const filepath = path.join(distDir, bundle!);
217
- // if error, just throw and let process die
218
- require(filepath);
219
- });
220
- }
221
-
222
219
  // read route spec from route.json
223
220
  protected readRouteSpec() {
224
221
  const file = path.join(this.distDir, ROUTE_SPEC_FILE);
@@ -272,13 +269,15 @@ export class ModernServer {
272
269
 
273
270
  // if use lambda/, mean framework style of writing, then discard user extension
274
271
  const apiExtension = mergeExtension(pluginAPIExt);
275
- this.frameAPIHandler = await this.prepareAPIHandler(mode, {
276
- ...apiExtension,
277
- modernJsConfig: this.conf,
278
- });
272
+ this.frameAPIHandler = await this.prepareAPIHandler(mode, apiExtension);
279
273
  }
280
274
  }
281
275
 
276
+ // Todo
277
+ protected async proxy() {
278
+ return null as any;
279
+ }
280
+
282
281
  /* —————————————————————— function will be overwrite —————————————————————— */
283
282
  protected async prepareWebHandler(
284
283
  extension: ReturnType<typeof mergeExtension>,
@@ -317,75 +316,93 @@ export class ModernServer {
317
316
  return routes;
318
317
  }
319
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
+
320
338
  protected async preServerInit() {
321
- const { conf } = this;
339
+ const { conf, runner } = this;
322
340
  const preMiddleware: ModernServerAsyncHandler[] =
323
- await this.runner.preServerInit(conf);
341
+ await runner.preServerInit(conf);
324
342
 
325
343
  preMiddleware.flat().forEach(mid => {
326
344
  this.addHandler(mid);
327
345
  });
328
346
  }
329
347
 
330
- private prepareFavicons(
331
- favicon: string | undefined,
332
- faviconByEntries?: Record<string, string | undefined>,
333
- ) {
334
- const faviconNames = [];
335
- if (favicon) {
336
- faviconNames.push(favicon.substring(favicon.lastIndexOf('/') + 1));
337
- }
338
- if (faviconByEntries) {
339
- Object.keys(faviconByEntries).forEach(f => {
340
- const curFavicon = faviconByEntries[f];
341
- if (curFavicon) {
342
- faviconNames.push(
343
- curFavicon.substring(curFavicon.lastIndexOf('/') + 1),
344
- );
345
- }
346
- });
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');
347
353
  }
348
- return faviconNames;
354
+
355
+ await this.frameAPIHandler(req, res);
349
356
  }
350
357
 
351
- /* —————————————————————— private function —————————————————————— */
358
+ protected async handleWeb(context: ModernServerContext, route: ModernRoute) {
359
+ return this.routeRenderHandler({
360
+ ctx: context,
361
+ route,
362
+ runner: this.runner,
363
+ });
364
+ }
365
+
366
+ protected verifyMatch(_c: ModernServerContext, _m: RouteMatcher) {
367
+ // empty
368
+ }
352
369
 
370
+ /* —————————————————————— private function —————————————————————— */
353
371
  // handler route.json, include api / csr / ssr
354
372
  // eslint-disable-next-line max-statements
355
373
  private async routeHandler(context: ModernServerContext) {
356
374
  const { req, res } = context;
357
375
 
358
- await this.runner.beforeMatch({ context }, { onLast: noop as any });
376
+ await this.emitRouteHook('beforeMatch', { context });
359
377
 
360
378
  // match routes in the route spec
361
379
  const matched = this.router.match(context.url);
362
380
  if (!matched) {
363
381
  this.render404(context);
364
382
  return;
383
+ } else {
384
+ this.verifyMatch(context, matched);
385
+ }
386
+
387
+ if (res.headersSent) {
388
+ return;
365
389
  }
366
390
 
367
391
  const routeAPI = createRouteAPI(matched, this.router);
368
- await this.runner.afterMatch(
369
- { context, routeAPI },
370
- { onLast: noop as any },
371
- );
392
+ await this.emitRouteHook('afterMatch', { context, routeAPI });
372
393
 
373
394
  if (res.headersSent) {
374
395
  return;
375
396
  }
376
397
 
377
398
  const { current } = routeAPI as any;
378
- const route = current.generate();
399
+ const route: ModernRoute = current.generate();
379
400
  const params = current.parseURLParams(context.url);
380
401
  context.setParams(params);
381
402
 
382
403
  // route is api service
383
404
  if (route.isApi) {
384
- if (!this.frameAPIHandler) {
385
- throw new Error('can not found api hanlder');
386
- }
387
-
388
- await this.frameAPIHandler(req, res);
405
+ this.handleAPI(context);
389
406
  return;
390
407
  }
391
408
 
@@ -398,8 +415,11 @@ export class ModernServer {
398
415
  return;
399
416
  }
400
417
 
401
- await this.runner.beforeRender({ context }, { onLast: noop as any });
402
- const file = await this.routeRenderHandler(context, route);
418
+ if (route.entryName) {
419
+ await this.emitRouteHook('beforeRender', { context });
420
+ }
421
+
422
+ const file = await this.handleWeb(context, route);
403
423
  if (!file) {
404
424
  this.render404(context);
405
425
  return;
@@ -415,10 +435,7 @@ export class ModernServer {
415
435
  let response = file.content;
416
436
  if (route.entryName) {
417
437
  const templateAPI = createTemplateAPI(file.content.toString());
418
- await this.runner.afterRender(
419
- { context, templateAPI },
420
- { onLast: noop as any },
421
- );
438
+ await this.emitRouteHook('afterRender', { context, templateAPI });
422
439
  await this.injectMicroFE(context, templateAPI);
423
440
  response = templateAPI.get();
424
441
  }
@@ -535,7 +552,7 @@ export class ModernServer {
535
552
  res.statusCode = 200;
536
553
  const context: ModernServerContext = createContext(req, res, {
537
554
  logger: this.logger,
538
- measure: this.measure,
555
+ metrics: this.metrics,
539
556
  });
540
557
 
541
558
  try {
@@ -581,5 +598,26 @@ export class ModernServer {
581
598
  const text = ERROR_PAGE_TEXT[status] || ERROR_PAGE_TEXT[500];
582
599
  res.end(createErrorDocument(status, text));
583
600
  }
601
+
602
+ private prepareFavicons(
603
+ favicon: string | undefined,
604
+ faviconByEntries?: Record<string, string | undefined>,
605
+ ) {
606
+ const faviconNames = [];
607
+ if (favicon) {
608
+ faviconNames.push(favicon.substring(favicon.lastIndexOf('/') + 1));
609
+ }
610
+ if (faviconByEntries) {
611
+ Object.keys(faviconByEntries).forEach(f => {
612
+ const curFavicon = faviconByEntries[f];
613
+ if (curFavicon) {
614
+ faviconNames.push(
615
+ curFavicon.substring(curFavicon.lastIndexOf('/') + 1),
616
+ );
617
+ }
618
+ });
619
+ }
620
+ return faviconNames;
621
+ }
584
622
  }
585
623
  /* 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' {
@@ -26,6 +26,8 @@ export type DevServerOptions = {
26
26
  dev: {
27
27
  writeToDisk: boolean | ((filename: string) => boolean);
28
28
  };
29
+ // 是否监听文件变化
30
+ watch: boolean;
29
31
  // 是否开启 hot reload
30
32
  hot: boolean | string;
31
33
  // 是否开启 page reload
@@ -39,17 +41,22 @@ export type ModernServerOptions = {
39
41
  pwd: string;
40
42
  config: NormalizedConfig;
41
43
  plugins?: any[];
42
- dev?: boolean | DevServerOptions;
44
+ dev?: boolean | Partial<DevServerOptions>;
43
45
  compiler?: Webpack.MultiCompiler | Webpack.Compiler;
44
46
  routes?: ModernRouteInterface[];
45
47
  staticGenerate?: boolean;
46
48
  customServer?: boolean;
47
49
  loggerOptions?: Record<string, string>;
48
- measureOptions?: Record<string, string>;
50
+ metricsOptions?: Record<string, string>;
49
51
  logger?: Logger;
50
- measure?: Measure;
52
+ metrics?: Metrics;
51
53
  apiOnly?: boolean;
54
+ ssrOnly?: boolean;
52
55
  webOnly?: boolean;
56
+ proxyTarget?: {
57
+ ssr?: string;
58
+ api?: string;
59
+ };
53
60
  };
54
61
 
55
62
  export type RenderResult = {
@@ -71,4 +78,4 @@ export type ServerHookRunner = Then<ReturnType<typeof serverManager.init>>;
71
78
 
72
79
  export type ReadyOptions = { routes?: ModernRouteInterface[] };
73
80
 
74
- export type { Measure, Logger, NextFunction };
81
+ export type { Metrics, Logger, NextFunction };
package/src/utils.ts CHANGED
@@ -49,3 +49,17 @@ export const createErrorDocument = (status: number, text: string) => {
49
49
  </html>
50
50
  `;
51
51
  };
52
+
53
+ // This can live anywhere in your codebase:
54
+ export function applyMixins(derivedCtor: any, constructors: any[]) {
55
+ constructors.forEach(baseCtor => {
56
+ Object.getOwnPropertyNames(baseCtor.prototype).forEach(name => {
57
+ Object.defineProperty(
58
+ derivedCtor.prototype,
59
+ name,
60
+ Object.getOwnPropertyDescriptor(baseCtor.prototype, name) ||
61
+ Object.create(null),
62
+ );
63
+ });
64
+ });
65
+ }
@@ -1,3 +0,0 @@
1
- import { Measure } from "../type.d";
2
- declare const measure: Measure;
3
- export { measure };