@modern-js/prod-server 1.21.3 → 2.0.0-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 (31) hide show
  1. package/CHANGELOG.md +43 -3
  2. package/dist/js/modern/libs/hook-api/index.js +156 -0
  3. package/dist/js/modern/libs/hook-api/route.js +14 -29
  4. package/dist/js/modern/libs/hook-api/template.js +43 -4
  5. package/dist/js/modern/libs/render/cache/index.js +33 -16
  6. package/dist/js/modern/libs/render/measure.js +8 -1
  7. package/dist/js/modern/libs/render/ssr.js +20 -7
  8. package/dist/js/modern/libs/serve-file.js +8 -0
  9. package/dist/js/modern/server/index.js +9 -3
  10. package/dist/js/modern/server/modern-server-split.js +5 -44
  11. package/dist/js/modern/server/modern-server.js +140 -130
  12. package/dist/js/node/libs/hook-api/index.js +178 -0
  13. package/dist/js/node/libs/hook-api/route.js +14 -29
  14. package/dist/js/node/libs/hook-api/template.js +48 -4
  15. package/dist/js/node/libs/render/cache/index.js +34 -16
  16. package/dist/js/node/libs/render/measure.js +7 -0
  17. package/dist/js/node/libs/render/ssr.js +20 -7
  18. package/dist/js/node/libs/serve-file.js +12 -1
  19. package/dist/js/node/server/index.js +8 -2
  20. package/dist/js/node/server/modern-server-split.js +5 -45
  21. package/dist/js/node/server/modern-server.js +140 -132
  22. package/dist/types/libs/hook-api/index.d.ts +5 -0
  23. package/dist/types/libs/hook-api/route.d.ts +9 -14
  24. package/dist/types/libs/hook-api/template.d.ts +19 -9
  25. package/dist/types/libs/render/cache/index.d.ts +4 -2
  26. package/dist/types/libs/render/type.d.ts +3 -1
  27. package/dist/types/libs/serve-file.d.ts +2 -1
  28. package/dist/types/server/index.d.ts +2 -0
  29. package/dist/types/server/modern-server.d.ts +11 -11
  30. package/dist/types/type.d.ts +8 -10
  31. package/package.json +9 -32
@@ -13,10 +13,6 @@ var _path = _interopRequireDefault(require("path"));
13
13
 
14
14
  var _utils = require("@modern-js/utils");
15
15
 
16
- var _axios = _interopRequireDefault(require("axios"));
17
-
18
- var _lodash = require("@modern-js/utils/lodash");
19
-
20
16
  var _route = require("../libs/route");
21
17
 
22
18
  var _render = require("../libs/render");
@@ -31,11 +27,11 @@ var _proxy = require("../libs/proxy");
31
27
 
32
28
  var _context = require("../libs/context");
33
29
 
34
- var _constants = require("../constants");
35
-
36
30
  var _template = require("../libs/hook-api/template");
37
31
 
38
- var _route2 = require("../libs/hook-api/route");
32
+ var _constants = require("../constants");
33
+
34
+ var _hookApi = require("../libs/hook-api");
39
35
 
40
36
  const _excluded = ["getMiddlewares"];
41
37
 
@@ -104,6 +100,8 @@ class ModernServer {
104
100
 
105
101
  _defineProperty(this, "routeRenderHandler", void 0);
106
102
 
103
+ _defineProperty(this, "beforeRouteHandler", null);
104
+
107
105
  _defineProperty(this, "frameWebHandler", null);
108
106
 
109
107
  _defineProperty(this, "frameAPIHandler", null);
@@ -127,8 +125,7 @@ class ModernServer {
127
125
  this.presetRoutes = routes;
128
126
  this.proxyTarget = proxyTarget;
129
127
  this.staticGenerate = staticGenerate || false;
130
- this.runMode = runMode || _constants.RUN_MODE.TYPE;
131
- process.env.BUILD_TYPE = `${this.staticGenerate ? 'ssg' : 'ssr'}`;
128
+ this.runMode = runMode || _constants.RUN_MODE.FULL; // process.env.BUILD_TYPE = `${this.staticGenerate ? 'ssg' : 'ssr'}`;
132
129
  } // server prepare
133
130
 
134
131
 
@@ -161,7 +158,8 @@ class ModernServer {
161
158
  this.router.reset(usageRoutes); // warmup ssr bundle in production env
162
159
 
163
160
  this.warmupSSRBundle();
164
- await this.prepareFrameHandler(); // Only work when without setting `assetPrefix`.
161
+ await this.prepareFrameHandler();
162
+ await this.prepareBeforeRouteHandler(usageRoutes, distDir); // Only work when without setting `assetPrefix`.
165
163
  // Setting `assetPrefix` means these resources should be uploaded to CDN.
166
164
 
167
165
  const staticPathRegExp = (0, _utils2.getStaticReg)(this.conf.output || {});
@@ -174,7 +172,10 @@ class ModernServer {
174
172
  staticGenerate
175
173
  });
176
174
  await this.setupBeforeProdMiddleware();
177
- this.addHandler(this.staticFileHandler);
175
+ this.addHandler(this.staticFileHandler); // execute after staticFileHandler, can rename to staticFallbackHandler if needed.
176
+
177
+ this.addHandler(_serveFile.faviconFallbackHandler);
178
+ this.addBeforeRouteHandler();
178
179
  this.addHandler(this.routeHandler.bind(this)); // compose middlewares to http handler
179
180
 
180
181
  this.compose();
@@ -184,6 +185,21 @@ class ModernServer {
184
185
  onRepack(_) {// empty
185
186
  }
186
187
 
188
+ addBeforeRouteHandler() {
189
+ this.addHandler(async (context, next) => {
190
+ if (this.beforeRouteHandler) {
191
+ await this.beforeRouteHandler(context);
192
+
193
+ if (this.isSend(context.res)) {
194
+ return;
195
+ }
196
+ } // eslint-disable-next-line consistent-return
197
+
198
+
199
+ return next();
200
+ });
201
+ }
202
+
187
203
  onServerChange({
188
204
  filepath
189
205
  }) {
@@ -212,6 +228,26 @@ class ModernServer {
212
228
  return this.requestHandler.bind(this);
213
229
  }
214
230
 
231
+ async render(req, res, url) {
232
+ req.logger = this.logger;
233
+ req.metrics = this.metrics;
234
+ const context = (0, _context.createContext)(req, res);
235
+ const matched = this.router.match(url || context.path);
236
+
237
+ if (!matched) {
238
+ return null;
239
+ }
240
+
241
+ const route = matched.generate(context.url);
242
+ const result = await this.handleWeb(context, route);
243
+
244
+ if (!result) {
245
+ return null;
246
+ }
247
+
248
+ return result.content.toString();
249
+ }
250
+
215
251
  async createHTTPServer(handler) {
216
252
  return (0, _http.createServer)(handler);
217
253
  }
@@ -251,6 +287,19 @@ class ModernServer {
251
287
  render404(context) {
252
288
  context.error(_constants.ERROR_DIGEST.ENOTF, '404 Not Found');
253
289
  this.renderErrorPage(context, 404);
290
+ }
291
+
292
+ async prepareBeforeRouteHandler(specs, distDir) {
293
+ const {
294
+ runner
295
+ } = this;
296
+ const handler = await runner.preparebeforeRouteHandler({
297
+ serverRoutes: specs,
298
+ distDir
299
+ }, {
300
+ onLast: () => null
301
+ });
302
+ this.beforeRouteHandler = handler;
254
303
  } // gather frame extension and get framework handler
255
304
 
256
305
 
@@ -297,12 +346,13 @@ class ModernServer {
297
346
  workDir,
298
347
  runner
299
348
  } = this;
300
- return runner.prepareWebServer({
349
+ const handler = await runner.prepareWebServer({
301
350
  pwd: workDir,
302
351
  config: extension
303
352
  }, {
304
353
  onLast: () => null
305
354
  });
355
+ return handler;
306
356
  }
307
357
 
308
358
  async prepareAPIHandler(extension) {
@@ -328,13 +378,6 @@ class ModernServer {
328
378
  return routes;
329
379
  }
330
380
 
331
- async emitRouteHook(eventName, input) {
332
- input.context = (0, _lodash.clone)(input.context);
333
- return this.runner[eventName](input, {
334
- onLast: _utils2.noop
335
- });
336
- }
337
-
338
381
  async setupBeforeProdMiddleware() {
339
382
  const {
340
383
  conf,
@@ -394,51 +437,70 @@ class ModernServer {
394
437
 
395
438
  async routeHandler(context) {
396
439
  const {
397
- req,
398
440
  res
399
- } = context;
400
- await this.emitRouteHook('beforeMatch', {
401
- context
402
- }); // match routes in the route spec
441
+ } = context; // match routes in the route spec
403
442
 
404
443
  const matched = this.router.match(context.path);
405
444
 
406
445
  if (!matched) {
407
446
  this.render404(context);
408
447
  return;
409
- }
448
+ } // route is api service
410
449
 
411
- if (res.headersSent) {
450
+
451
+ let route = matched.generate(context.url);
452
+
453
+ if (route.isApi) {
454
+ await this.handleAPI(context);
412
455
  return;
413
456
  }
414
457
 
415
- const routeAPI = (0, _route2.createRouteAPI)(matched, this.router, context.url);
416
- await this.emitRouteHook('afterMatch', {
417
- context,
418
- routeAPI
419
- });
458
+ const afterMatchContext = (0, _hookApi.createAfterMatchContext)(context, route.entryName); // only full mode run server hook
459
+
460
+ if (this.runMode === _constants.RUN_MODE.FULL) {
461
+ await this.runner.afterMatch(afterMatchContext, {
462
+ onLast: _utils2.noop
463
+ });
464
+ }
420
465
 
421
466
  if (this.isSend(res)) {
422
467
  return;
423
468
  }
424
469
 
425
470
  const {
426
- current
427
- } = routeAPI;
428
- const route = current.generate(context.url);
471
+ current,
472
+ url,
473
+ status
474
+ } = afterMatchContext.router; // redirect to another url
475
+
476
+ if (url) {
477
+ this.redirect(res, url, status);
478
+ return;
479
+ } // rewrite to another entry
480
+
481
+
482
+ if (route.entryName !== current) {
483
+ const matched = this.router.matchEntry(current);
484
+
485
+ if (!matched) {
486
+ this.render404(context);
487
+ return;
488
+ }
489
+
490
+ route = matched.generate(context.url);
491
+ }
492
+
429
493
  context.setParams(route.params);
430
494
  context.setServerData('router', {
431
495
  baseUrl: route.urlPath,
432
496
  params: route.params
433
- }); // route is api service
434
-
435
- if (route.isApi) {
436
- await this.handleAPI(context);
437
- return;
438
- }
497
+ });
439
498
 
440
499
  if (this.frameWebHandler) {
441
- await this.frameWebHandler(req, res);
500
+ res.locals = res.locals || {};
501
+ const middlewareContext = (0, _hookApi.createMiddlewareContext)(context);
502
+ await this.frameWebHandler(middlewareContext);
503
+ res.locals = _objectSpread(_objectSpread({}, res.locals), middlewareContext.response.locals);
442
504
  } // frameWebHandler has process request
443
505
 
444
506
 
@@ -456,23 +518,16 @@ class ModernServer {
456
518
  });
457
519
  }
458
520
 
459
- if (route.entryName) {
460
- await this.emitRouteHook('beforeRender', {
461
- context
462
- });
463
- }
464
-
465
- const file = await this.handleWeb(context, route);
521
+ const renderResult = await this.handleWeb(context, route);
466
522
 
467
- if (!file) {
523
+ if (!renderResult) {
468
524
  this.render404(context);
469
525
  return;
470
- }
526
+ } // React Router navigation
471
527
 
472
- if (file.redirect) {
473
- res.statusCode = file.statusCode;
474
- res.setHeader('Location', file.content);
475
- res.end();
528
+
529
+ if (renderResult.redirect) {
530
+ this.redirect(res, renderResult.content, renderResult.statusCode);
476
531
  return;
477
532
  }
478
533
 
@@ -480,29 +535,42 @@ class ModernServer {
480
535
  return;
481
536
  }
482
537
 
483
- let response = file.content;
538
+ res.setHeader('content-type', renderResult.contentType);
539
+ const {
540
+ contentStream
541
+ } = renderResult;
542
+
543
+ if (contentStream) {
544
+ contentStream.pipe((0, _template.templateInjectableStream)({
545
+ prependHead: route.entryName ? `<script>window._SERVER_DATA=${JSON.stringify(context.serverData)}</script>` : undefined
546
+ })).pipe(res);
547
+ return;
548
+ }
549
+
550
+ let response = renderResult.content;
484
551
 
485
552
  if (route.entryName) {
486
- const templateAPI = (0, _template.createTemplateAPI)(file.content.toString());
487
- await this.emitRouteHook('afterRender', {
488
- context,
489
- templateAPI
490
- });
553
+ const afterRenderContext = (0, _hookApi.createAfterRenderContext)(context, response.toString()); // only full mode run server hook
554
+ // FIXME: how to run server hook in streaming
491
555
 
492
- if (this.isSend(res)) {
493
- return;
556
+ if (this.runMode === _constants.RUN_MODE.FULL) {
557
+ await this.runner.afterRender(afterRenderContext, {
558
+ onLast: _utils2.noop
559
+ });
494
560
  }
495
561
 
496
- await this.injectMicroFE(context, templateAPI); // It will inject _SERVER_DATA twice, when SSG mode.
562
+ if (this.isSend(res)) {
563
+ return;
564
+ } // It will inject _SERVER_DATA twice, when SSG mode.
497
565
  // The first time was in ssg html created, the seoncd time was in prod-server start.
498
566
  // but the second wound causes route error.
499
567
  // To ensure that the second injection fails, the _SERVER_DATA inject at the front of head,
500
568
 
501
- templateAPI.prependHead(`<script>window._SERVER_DATA=${JSON.stringify(context.serverData)}</script>`);
502
- response = templateAPI.get();
569
+
570
+ afterRenderContext.template.prependHead(`<script>window._SERVER_DATA=${JSON.stringify(context.serverData)}</script>`);
571
+ response = afterRenderContext.template.get();
503
572
  }
504
573
 
505
- res.setHeader('content-type', file.contentType);
506
574
  res.end(response);
507
575
  }
508
576
 
@@ -517,72 +585,6 @@ class ModernServer {
517
585
  }
518
586
 
519
587
  return false;
520
- }
521
-
522
- async injectMicroFE(context, templateAPI) {
523
- var _conf$runtime, _conf$server;
524
-
525
- const {
526
- conf
527
- } = this;
528
- const masterApp = (_conf$runtime = conf.runtime) === null || _conf$runtime === void 0 ? void 0 : _conf$runtime.masterApp; // no inject if not master App
529
-
530
- if (!masterApp) {
531
- return;
532
- }
533
-
534
- const manifest = masterApp.manifest || {};
535
- let modules = [];
536
- const {
537
- modules: configModules = []
538
- } = manifest; // while config modules is an string, fetch data from remote
539
-
540
- if (typeof configModules === 'string') {
541
- const moduleRequestUrl = configModules;
542
-
543
- try {
544
- const {
545
- data: remoteModules
546
- } = await _axios.default.get(moduleRequestUrl);
547
-
548
- if (Array.isArray(remoteModules)) {
549
- modules.push(...remoteModules);
550
- }
551
- } catch (e) {
552
- context.error(_constants.ERROR_DIGEST.EMICROINJ, e);
553
- }
554
- } else if (Array.isArray(configModules)) {
555
- modules.push(...configModules);
556
- }
557
-
558
- const {
559
- headers
560
- } = context.req;
561
- const debugName = headers['x-micro-frontend-module-name'] || context.query['__debug__micro-frontend-module-name'];
562
- const debugEntry = headers['x-micro-frontend-module-entry'] || context.query['__debug__micro-frontend-module-entry']; // add debug micro App to first
563
-
564
- if (debugName && debugEntry && (_conf$server = conf.server) !== null && _conf$server !== void 0 && _conf$server.enableMicroFrontendDebug) {
565
- modules = modules.map(m => {
566
- if (m.name === debugName) {
567
- return {
568
- name: debugName,
569
- entry: debugEntry
570
- };
571
- }
572
-
573
- return m;
574
- });
575
- }
576
-
577
- try {
578
- // Todo Safety xss
579
- const injection = JSON.stringify(_objectSpread(_objectSpread({}, manifest), {}, {
580
- modules
581
- }));
582
- templateAPI.appendHead(`<script>window.modern_manifest=${injection}</script>`);
583
- } catch (e) {
584
- context.error(_constants.ERROR_DIGEST.EMICROINJ, e);
585
- }
586
588
  } // compose handlers and create the final handler
587
589
 
588
590
 
@@ -649,6 +651,12 @@ class ModernServer {
649
651
  }
650
652
  }
651
653
 
654
+ redirect(res, url, status = 302) {
655
+ res.setHeader('Location', url);
656
+ res.statusCode = status;
657
+ res.end();
658
+ }
659
+
652
660
  onError(context, err) {
653
661
  context.error(_constants.ERROR_DIGEST.EINTER, err);
654
662
  this.renderErrorPage(context, 500);
@@ -0,0 +1,5 @@
1
+ import type { ModernServerContext, HookContext, AfterMatchContext, AfterRenderContext, MiddlewareContext } from '@modern-js/types';
2
+ export declare const base: (context: ModernServerContext) => HookContext;
3
+ export declare const createAfterMatchContext: (context: ModernServerContext, entryName: string) => AfterMatchContext;
4
+ export declare const createAfterRenderContext: (context: ModernServerContext, content: string) => AfterRenderContext;
5
+ export declare const createMiddlewareContext: (context: ModernServerContext) => MiddlewareContext;
@@ -1,14 +1,9 @@
1
- import { RouteMatchManager, RouteMatcher } from '../route';
2
-
3
- declare class RouteAPI {
4
- private readonly router;
5
- private current;
6
- private readonly url;
7
- constructor(matched: RouteMatcher, router: RouteMatchManager, url: string);
8
- cur(): import("../route").ModernRoute;
9
- get(entryName: string): import("../route").ModernRoute | null;
10
- use(entryName: string): boolean;
11
- }
12
-
13
- export declare const createRouteAPI: (matched: RouteMatcher, router: RouteMatchManager, url: string) => RouteAPI;
14
- export {};
1
+ export declare class RouteAPI {
2
+ current: string;
3
+ status: number;
4
+ url: string;
5
+ constructor(entryName: string);
6
+ redirect(url: string, status?: number): void;
7
+ rewrite(entryName: string): void;
8
+ use(entryName: string): void;
9
+ }
@@ -1,14 +1,24 @@
1
- declare class TemplateAPI {
1
+ /// <reference types="node" />
2
+ import { Transform } from 'stream';
3
+ export declare class TemplateAPI {
2
4
  private content;
3
5
  constructor(content: string);
4
6
  get(): string;
5
7
  set(content: string): void;
6
- prependHead(fragment: string): this;
7
- appendHead(fragment: string): this;
8
- prependBody(fragment: string): this;
9
- appendBody(fragment: string): this;
10
- replace(reg: RegExp | string, text: string): this;
8
+ prependHead(fragment: string): void;
9
+ appendHead(fragment: string): void;
10
+ prependBody(fragment: string): void;
11
+ appendBody(fragment: string): void;
12
+ private replace;
11
13
  }
12
-
13
- export declare const createTemplateAPI: (content: string) => TemplateAPI;
14
- export {};
14
+ export declare const templateInjectableStream: ({
15
+ prependHead,
16
+ appendHead,
17
+ prependBody,
18
+ appendBody
19
+ }: {
20
+ prependHead?: string | undefined;
21
+ appendHead?: string | undefined;
22
+ prependBody?: string | undefined;
23
+ appendBody?: string | undefined;
24
+ }) => Transform;
@@ -1,6 +1,8 @@
1
+ /// <reference types="node" />
2
+ import { Readable } from 'stream';
1
3
  import type { ModernServerContext } from '@modern-js/types';
2
- import { RenderFunction } from '../type';
4
+ import { RenderFunction, SSRServerContext } from '../type';
3
5
 
4
- declare const _default: (renderFn: RenderFunction, ctx: ModernServerContext) => RenderFunction;
6
+ declare const _default: (renderFn: RenderFunction, ctx: ModernServerContext) => (context: SSRServerContext) => Promise<string | Readable>;
5
7
 
6
8
  export default _default;
@@ -1,4 +1,6 @@
1
1
  /// <reference types="react" />
2
+ /// <reference types="node" />
3
+ import { Writable, Readable } from 'stream';
2
4
  import { BaseSSRServerContext } from '@modern-js/types';
3
5
  declare type MetaKeyMap = {
4
6
  header?: string[];
@@ -30,5 +32,5 @@ export declare type ModernSSRReactComponent = React.ComponentType<any> & {
30
32
  init: (context: SSRServerContext) => Promise<void>;
31
33
  prefetch: (context: SSRServerContext) => Promise<Record<string, any>>;
32
34
  };
33
- export declare type RenderFunction = (context: SSRServerContext) => Promise<string>;
35
+ export declare type RenderFunction = (context: SSRServerContext) => Promise<string | ((writable: Writable) => Promise<Readable>)>;
34
36
  export {};
@@ -1,9 +1,10 @@
1
1
  import { ServerOptions } from '@modern-js/server-core';
2
2
  import type { ModernServerContext } from '@modern-js/types';
3
- import { NextFunction } from '../type';
3
+ import { NextFunction, ModernServerHandler } from '../type';
4
4
  declare type Rule = {
5
5
  path: string | RegExp;
6
6
  target: string;
7
7
  };
8
+ export declare const faviconFallbackHandler: ModernServerHandler;
8
9
  export declare const createStaticFileHandler: (rules: Rule[], output?: ServerOptions['output']) => (context: ModernServerContext, next: NextFunction) => Promise<void>;
9
10
  export {};
@@ -1,4 +1,5 @@
1
1
  /// <reference types="node" />
2
+ /// <reference types="node" />
2
3
  import { IncomingMessage, ServerResponse } from 'http';
3
4
  import type { ListenOptions } from 'net';
4
5
  import { ModernServerOptions, ServerConstructor } from '../type';
@@ -44,6 +45,7 @@ export declare class Server {
44
45
  close(): Promise<void>;
45
46
  listen<T extends number | ListenOptions | undefined>(options: T, listener: any): void;
46
47
  getRequestHandler(): (req: IncomingMessage, res: ServerResponse, next?: () => void) => void;
48
+ render(req: IncomingMessage, res: ServerResponse, url?: string): Promise<string | null>;
47
49
  private createHookRunner;
48
50
  private injectContext;
49
51
  private initAppContext;
@@ -1,9 +1,9 @@
1
1
  /// <reference types="node" />
2
2
  import { IncomingMessage, ServerResponse, Server } from 'http';
3
- import { Adapter, APIServerStartInput, ServerOptions } from '@modern-js/server-core';
4
- import type { ModernServerContext } from '@modern-js/types';
3
+ import { Adapter, WebAdapter, APIServerStartInput, ServerOptions } from '@modern-js/server-core';
4
+ import type { ModernServerContext, ServerRoute } from '@modern-js/types';
5
5
  import type { ContextOptions } from '../libs/context';
6
- import { ModernServerOptions, NextFunction, ServerHookRunner, Metrics, Logger, ModernServerInterface, HookNames, BuildOptions, ModernServerHandler } from '../type';
6
+ import { ModernServerOptions, NextFunction, ServerHookRunner, Metrics, Logger, ModernServerInterface, BuildOptions, ModernServerHandler } from '../type';
7
7
  import { RouteMatchManager, ModernRouteInterface, ModernRoute } from '../libs/route';
8
8
  import { mergeExtension } from '../utils';
9
9
  import * as reader from '../libs/render/reader';
@@ -24,6 +24,7 @@ export declare class ModernServer implements ModernServerInterface {
24
24
  protected readonly proxyTarget: ModernServerOptions['proxyTarget'];
25
25
  private staticFileHandler;
26
26
  private routeRenderHandler;
27
+ private beforeRouteHandler;
27
28
  private frameWebHandler;
28
29
  private frameAPIHandler;
29
30
  private proxyHandler;
@@ -41,27 +42,26 @@ export declare class ModernServer implements ModernServerInterface {
41
42
  }: ModernServerOptions);
42
43
  onInit(runner: ServerHookRunner, app: Server): Promise<void>;
43
44
  onRepack(_: BuildOptions): void;
45
+ addBeforeRouteHandler(): void;
44
46
  protected onServerChange({
45
47
  filepath
46
48
  }: {
47
49
  filepath: string;
48
50
  }): void;
49
51
  getRequestHandler(): (req: IncomingMessage, res: ServerResponse, next?: () => void) => void | ServerResponse;
52
+ render(req: IncomingMessage, res: ServerResponse, url?: string): Promise<string | null>;
50
53
  createHTTPServer(handler: (req: IncomingMessage, res: ServerResponse, next?: () => void) => void): Promise<Server>;
51
- protected getRoutes(): ModernRouteInterface[];
54
+ protected getRoutes(): ServerRoute[];
52
55
  protected addHandler(handler: ModernServerHandler): void;
53
56
  protected render404(context: ModernServerContext): void;
57
+ protected prepareBeforeRouteHandler(specs: ServerRoute[], distDir: string): Promise<void>;
54
58
  protected prepareFrameHandler(options?: {
55
59
  onlyApi: boolean;
56
60
  onlyWeb: boolean;
57
61
  }): Promise<void>;
58
- protected prepareWebHandler(extension: ReturnType<typeof mergeExtension>): Promise<Adapter>;
62
+ protected prepareWebHandler(extension: ReturnType<typeof mergeExtension>): Promise<WebAdapter>;
59
63
  protected prepareAPIHandler(extension: APIServerStartInput['config']): Promise<Adapter>;
60
- protected filterRoutes(routes: ModernRouteInterface[]): ModernRouteInterface[];
61
- protected emitRouteHook(eventName: HookNames, input: {
62
- context: ModernServerContext;
63
- [propsName: string]: any;
64
- }): Promise<any>;
64
+ protected filterRoutes(routes: ModernRouteInterface[]): ServerRoute[];
65
65
  protected setupBeforeProdMiddleware(): Promise<void>;
66
66
  protected handleAPI(context: ModernServerContext): Promise<void>;
67
67
  protected handleWeb(context: ModernServerContext, route: ModernRoute): Promise<import("../type").RenderResult | null>;
@@ -70,9 +70,9 @@ export declare class ModernServer implements ModernServerInterface {
70
70
  protected createContext(req: IncomingMessage, res: ServerResponse, options?: ContextOptions): import("../libs/context").ModernServerContext;
71
71
  private routeHandler;
72
72
  private isSend;
73
- private injectMicroFE;
74
73
  private compose;
75
74
  private requestHandler;
75
+ private redirect;
76
76
  private onError;
77
77
  private renderErrorPage;
78
78
  }
@@ -1,9 +1,11 @@
1
1
  /// <reference types="node" />
2
2
  /// <reference types="node" />
3
+ /// <reference types="node" />
3
4
  import { IncomingMessage, Server, ServerResponse } from 'http';
5
+ import { Readable } from 'stream';
4
6
  import { serverManager, ServerOptions } from '@modern-js/server-core';
5
7
  import type { ServerPlugin } from '@modern-js/server-core';
6
- import type { Metrics, Logger, NextFunction, ModernServerContext } from '@modern-js/types';
8
+ import type { Metrics, Logger, NextFunction, ModernServerContext, InternalPlugins } from '@modern-js/types';
7
9
  import type { ModernRouteInterface } from './libs/route';
8
10
  declare module 'http' {
9
11
  interface IncomingMessage {
@@ -11,30 +13,25 @@ declare module 'http' {
11
13
  metrics: Metrics;
12
14
  }
13
15
  }
14
- declare type Plugin = string | [string, any] | ServerPlugin;
15
16
  export declare type ModernServerOptions = {
16
17
  pwd: string;
17
18
  config: ServerOptions;
18
- plugins?: Plugin[];
19
+ plugins?: ServerPlugin[];
20
+ internalPlugins?: InternalPlugins;
19
21
  routes?: ModernRouteInterface[];
20
22
  staticGenerate?: boolean;
21
- loggerOptions?: Record<string, string>;
22
- metricsOptions?: Record<string, string>;
23
23
  logger?: Logger;
24
24
  metrics?: Metrics;
25
25
  apiOnly?: boolean;
26
26
  ssrOnly?: boolean;
27
27
  webOnly?: boolean;
28
- proxyTarget?: {
29
- ssr?: string;
30
- api?: string;
31
- };
32
28
  runMode?: string;
33
29
  [propName: string]: any;
34
30
  };
35
31
  export declare type RenderResult = {
36
32
  content: string | Buffer;
37
33
  contentType: string;
34
+ contentStream?: Readable;
38
35
  statusCode?: number;
39
36
  redirect?: boolean;
40
37
  };
@@ -49,7 +46,7 @@ export declare type BuildOptions = {
49
46
  routes?: ModernRouteInterface[];
50
47
  };
51
48
  export type { Metrics, Logger, NextFunction };
52
- export declare type HookNames = 'beforeMatch' | 'afterMatch' | 'beforeRender' | 'afterRender';
49
+ export declare type HookNames = 'afterMatch' | 'afterRender';
53
50
  export interface ModernServerInterface {
54
51
  pwd: string;
55
52
  distDir: string;
@@ -57,6 +54,7 @@ export interface ModernServerInterface {
57
54
  onRepack: (options: BuildOptions) => void;
58
55
  getRequestHandler: () => (req: IncomingMessage, res: ServerResponse, next?: () => void) => void;
59
56
  createHTTPServer: (handler: (req: IncomingMessage, res: ServerResponse, next?: () => void) => void) => Promise<Server>;
57
+ render: (req: IncomingMessage, res: ServerResponse, url?: string) => Promise<string | null>;
60
58
  }
61
59
  export declare type ServerConstructor = (options: ModernServerOptions) => ModernServerInterface;
62
60
  export declare type ModernServerHandler = (context: ModernServerContext, next: NextFunction) => Promise<void> | void;