@modern-js/server 1.1.3 → 1.1.5-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 (67) hide show
  1. package/CHANGELOG.md +19 -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/index.js +6 -2
  11. package/dist/js/modern/libs/render/ssr.js +3 -2
  12. package/dist/js/modern/libs/route/route.js +1 -1
  13. package/dist/js/modern/server/dev-server/dev-server-split.js +2 -6
  14. package/dist/js/modern/server/dev-server/dev-server.js +11 -2
  15. package/dist/js/modern/server/dev-server/index.js +1 -1
  16. package/dist/js/modern/server/index.js +17 -15
  17. package/dist/js/modern/server/modern-server-split.js +55 -6
  18. package/dist/js/modern/server/modern-server.js +96 -56
  19. package/dist/js/modern/utils.js +9 -1
  20. package/dist/js/node/dev-tools/babel/register.js +2 -2
  21. package/dist/js/node/dev-tools/mock/getMockData.js +2 -2
  22. package/dist/js/node/libs/context/context.js +15 -7
  23. package/dist/js/node/libs/context/index.js +2 -2
  24. package/dist/js/node/libs/{measure.js → metrics.js} +3 -3
  25. package/dist/js/node/libs/proxy.js +2 -2
  26. package/dist/js/node/libs/render/cache/__tests__/cache.test.js +2 -2
  27. package/dist/js/node/libs/render/cache/index.js +2 -2
  28. package/dist/js/node/libs/render/index.js +6 -2
  29. package/dist/js/node/libs/render/ssr.js +3 -2
  30. package/dist/js/node/libs/route/route.js +1 -1
  31. package/dist/js/node/server/dev-server/dev-server-split.js +5 -9
  32. package/dist/js/node/server/dev-server/dev-server.js +11 -2
  33. package/dist/js/node/server/dev-server/index.js +4 -4
  34. package/dist/js/node/server/index.js +16 -14
  35. package/dist/js/node/server/modern-server-split.js +61 -9
  36. package/dist/js/node/server/modern-server.js +97 -57
  37. package/dist/js/node/utils.js +12 -2
  38. package/dist/types/libs/context/context.d.ts +5 -5
  39. package/dist/types/libs/context/index.d.ts +3 -3
  40. package/dist/types/libs/metrics.d.ts +3 -0
  41. package/dist/types/libs/render/index.d.ts +10 -1
  42. package/dist/types/libs/render/ssr.d.ts +2 -1
  43. package/dist/types/libs/render/type.d.ts +2 -21
  44. package/dist/types/libs/route/route.d.ts +2 -10
  45. package/dist/types/server/dev-server/dev-server-split.d.ts +3 -4
  46. package/dist/types/server/dev-server/index.d.ts +1 -1
  47. package/dist/types/server/modern-server-split.d.ts +15 -5
  48. package/dist/types/server/modern-server.d.ts +14 -7
  49. package/dist/types/type.d.ts +11 -5
  50. package/dist/types/utils.d.ts +2 -1
  51. package/package.json +5 -5
  52. package/src/libs/context/context.ts +12 -8
  53. package/src/libs/context/index.ts +3 -3
  54. package/src/libs/{measure.ts → metrics.ts} +3 -3
  55. package/src/libs/render/index.ts +21 -11
  56. package/src/libs/render/ssr.ts +5 -1
  57. package/src/libs/render/type.ts +3 -16
  58. package/src/libs/route/route.ts +4 -20
  59. package/src/server/dev-server/dev-server-split.ts +3 -7
  60. package/src/server/dev-server/dev-server.ts +14 -12
  61. package/src/server/dev-server/index.ts +1 -1
  62. package/src/server/index.ts +21 -14
  63. package/src/server/modern-server-split.ts +59 -7
  64. package/src/server/modern-server.ts +109 -64
  65. package/src/type.ts +12 -5
  66. package/src/utils.ts +14 -0
  67. 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);
@@ -276,6 +273,11 @@ export class ModernServer {
276
273
  }
277
274
  }
278
275
 
276
+ // Todo
277
+ protected async proxy() {
278
+ return null as any;
279
+ }
280
+
279
281
  /* —————————————————————— function will be overwrite —————————————————————— */
280
282
  protected async prepareWebHandler(
281
283
  extension: ReturnType<typeof mergeExtension>,
@@ -314,75 +316,93 @@ export class ModernServer {
314
316
  return routes;
315
317
  }
316
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
+
317
338
  protected async preServerInit() {
318
- const { conf } = this;
339
+ const { conf, runner } = this;
319
340
  const preMiddleware: ModernServerAsyncHandler[] =
320
- await this.runner.preServerInit(conf);
341
+ await runner.preServerInit(conf);
321
342
 
322
343
  preMiddleware.flat().forEach(mid => {
323
344
  this.addHandler(mid);
324
345
  });
325
346
  }
326
347
 
327
- private prepareFavicons(
328
- favicon: string | undefined,
329
- faviconByEntries?: Record<string, string | undefined>,
330
- ) {
331
- const faviconNames = [];
332
- if (favicon) {
333
- faviconNames.push(favicon.substring(favicon.lastIndexOf('/') + 1));
334
- }
335
- if (faviconByEntries) {
336
- Object.keys(faviconByEntries).forEach(f => {
337
- const curFavicon = faviconByEntries[f];
338
- if (curFavicon) {
339
- faviconNames.push(
340
- curFavicon.substring(curFavicon.lastIndexOf('/') + 1),
341
- );
342
- }
343
- });
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');
344
353
  }
345
- return faviconNames;
354
+
355
+ await this.frameAPIHandler(req, res);
346
356
  }
347
357
 
348
- /* —————————————————————— 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
+ }
349
369
 
370
+ /* —————————————————————— private function —————————————————————— */
350
371
  // handler route.json, include api / csr / ssr
351
372
  // eslint-disable-next-line max-statements
352
373
  private async routeHandler(context: ModernServerContext) {
353
374
  const { req, res } = context;
354
375
 
355
- await this.runner.beforeMatch({ context }, { onLast: noop as any });
376
+ await this.emitRouteHook('beforeMatch', { context });
356
377
 
357
378
  // match routes in the route spec
358
379
  const matched = this.router.match(context.url);
359
380
  if (!matched) {
360
381
  this.render404(context);
361
382
  return;
383
+ } else {
384
+ this.verifyMatch(context, matched);
385
+ }
386
+
387
+ if (res.headersSent) {
388
+ return;
362
389
  }
363
390
 
364
391
  const routeAPI = createRouteAPI(matched, this.router);
365
- await this.runner.afterMatch(
366
- { context, routeAPI },
367
- { onLast: noop as any },
368
- );
392
+ await this.emitRouteHook('afterMatch', { context, routeAPI });
369
393
 
370
394
  if (res.headersSent) {
371
395
  return;
372
396
  }
373
397
 
374
398
  const { current } = routeAPI as any;
375
- const route = current.generate();
399
+ const route: ModernRoute = current.generate();
376
400
  const params = current.parseURLParams(context.url);
377
401
  context.setParams(params);
378
402
 
379
403
  // route is api service
380
404
  if (route.isApi) {
381
- if (!this.frameAPIHandler) {
382
- throw new Error('can not found api hanlder');
383
- }
384
-
385
- await this.frameAPIHandler(req, res);
405
+ this.handleAPI(context);
386
406
  return;
387
407
  }
388
408
 
@@ -395,8 +415,11 @@ export class ModernServer {
395
415
  return;
396
416
  }
397
417
 
398
- await this.runner.beforeRender({ context }, { onLast: noop as any });
399
- 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);
400
423
  if (!file) {
401
424
  this.render404(context);
402
425
  return;
@@ -412,10 +435,7 @@ export class ModernServer {
412
435
  let response = file.content;
413
436
  if (route.entryName) {
414
437
  const templateAPI = createTemplateAPI(file.content.toString());
415
- await this.runner.afterRender(
416
- { context, templateAPI },
417
- { onLast: noop as any },
418
- );
438
+ await this.emitRouteHook('afterRender', { context, templateAPI });
419
439
  await this.injectMicroFE(context, templateAPI);
420
440
  response = templateAPI.get();
421
441
  }
@@ -532,7 +552,7 @@ export class ModernServer {
532
552
  res.statusCode = 200;
533
553
  const context: ModernServerContext = createContext(req, res, {
534
554
  logger: this.logger,
535
- measure: this.measure,
555
+ metrics: this.metrics,
536
556
  });
537
557
 
538
558
  try {
@@ -564,7 +584,11 @@ export class ModernServer {
564
584
  // check entryName, aviod matched '/' route
565
585
  if (entryName === status.toString() || entryName === '_error') {
566
586
  try {
567
- const file = await this.routeRenderHandler(context, route);
587
+ const file = await this.routeRenderHandler({
588
+ route,
589
+ ctx: context,
590
+ runner: this.runner,
591
+ });
568
592
  if (file) {
569
593
  context.res.end(file.content);
570
594
  return;
@@ -578,5 +602,26 @@ export class ModernServer {
578
602
  const text = ERROR_PAGE_TEXT[status] || ERROR_PAGE_TEXT[500];
579
603
  res.end(createErrorDocument(status, text));
580
604
  }
605
+
606
+ private prepareFavicons(
607
+ favicon: string | undefined,
608
+ faviconByEntries?: Record<string, string | undefined>,
609
+ ) {
610
+ const faviconNames = [];
611
+ if (favicon) {
612
+ faviconNames.push(favicon.substring(favicon.lastIndexOf('/') + 1));
613
+ }
614
+ if (faviconByEntries) {
615
+ Object.keys(faviconByEntries).forEach(f => {
616
+ const curFavicon = faviconByEntries[f];
617
+ if (curFavicon) {
618
+ faviconNames.push(
619
+ curFavicon.substring(curFavicon.lastIndexOf('/') + 1),
620
+ );
621
+ }
622
+ });
623
+ }
624
+ return faviconNames;
625
+ }
581
626
  }
582
627
  /* 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 };