@modern-js/server 1.2.0 → 1.2.1-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 (65) hide show
  1. package/dist/js/modern/index.js +1 -7
  2. package/dist/js/modern/libs/context/context.js +3 -6
  3. package/dist/js/modern/libs/context/index.js +1 -7
  4. package/dist/js/modern/libs/proxy.js +1 -1
  5. package/dist/js/modern/libs/render/cache/__tests__/cache.test.js +1 -2
  6. package/dist/js/modern/libs/render/index.js +6 -2
  7. package/dist/js/modern/libs/render/reader.js +8 -11
  8. package/dist/js/modern/libs/render/ssr.js +2 -1
  9. package/dist/js/modern/libs/route/index.js +2 -1
  10. package/dist/js/modern/server/index.js +3 -1
  11. package/dist/js/modern/server/modern-server.js +19 -10
  12. package/dist/js/modern/utils.js +1 -9
  13. package/dist/js/node/index.js +1 -49
  14. package/dist/js/node/libs/context/context.js +3 -6
  15. package/dist/js/node/libs/context/index.js +1 -7
  16. package/dist/js/node/libs/proxy.js +1 -1
  17. package/dist/js/node/libs/render/cache/__tests__/cache.test.js +1 -2
  18. package/dist/js/node/libs/render/index.js +6 -2
  19. package/dist/js/node/libs/render/reader.js +8 -11
  20. package/dist/js/node/libs/render/ssr.js +2 -1
  21. package/dist/js/node/libs/route/index.js +6 -0
  22. package/dist/js/node/server/index.js +3 -1
  23. package/dist/js/node/server/modern-server.js +19 -10
  24. package/dist/js/node/utils.js +2 -12
  25. package/dist/types/index.d.ts +1 -3
  26. package/dist/types/libs/context/context.d.ts +7 -7
  27. package/dist/types/libs/context/index.d.ts +1 -8
  28. package/dist/types/libs/render/index.d.ts +10 -1
  29. package/dist/types/libs/render/ssr.d.ts +2 -1
  30. package/dist/types/libs/render/type.d.ts +2 -21
  31. package/dist/types/libs/route/index.d.ts +2 -1
  32. package/dist/types/server/modern-server.d.ts +1 -1
  33. package/dist/types/type.d.ts +6 -0
  34. package/dist/types/utils.d.ts +1 -2
  35. package/package.json +7 -5
  36. package/src/index.ts +2 -8
  37. package/src/libs/context/context.ts +8 -7
  38. package/src/libs/context/index.ts +2 -6
  39. package/src/libs/proxy.ts +1 -1
  40. package/src/libs/render/cache/__tests__/cache.test.ts +2 -2
  41. package/src/libs/render/index.ts +21 -11
  42. package/src/libs/render/reader.ts +8 -8
  43. package/src/libs/render/ssr.ts +4 -0
  44. package/src/libs/render/type.ts +2 -17
  45. package/src/libs/route/index.ts +2 -1
  46. package/src/server/index.ts +1 -1
  47. package/src/server/modern-server.ts +18 -11
  48. package/src/type.ts +7 -0
  49. package/src/utils.ts +0 -14
  50. package/tests/.eslintrc.js +6 -0
  51. package/tests/context.test.ts +41 -0
  52. package/tests/fixtures/hosting-files/static/index.js +1 -0
  53. package/tests/fixtures/pure/modern.config.js +5 -0
  54. package/tests/fixtures/pure/package.json +21 -0
  55. package/tests/fixtures/pure/src/App.css +119 -0
  56. package/tests/fixtures/pure/src/App.tsx +43 -0
  57. package/tests/fixtures/pure/tsconfig.json +13 -0
  58. package/tests/fixtures/route-spec/index.json +29 -0
  59. package/tests/helper.ts +8 -0
  60. package/tests/hook.test.ts +44 -0
  61. package/tests/middleware.test.ts +178 -0
  62. package/tests/route.test.ts +54 -0
  63. package/tests/server.test.ts +89 -0
  64. package/tests/tsconfig.json +14 -0
  65. package/tests/utils.test.ts +40 -0
@@ -1,8 +1,14 @@
1
+ /// <reference path="../../type.d.ts" />
1
2
  /// <reference types="node" />
3
+ /// <reference types="node/http" />
2
4
  import { IncomingMessage, ServerResponse } from 'http';
3
5
  import { URL } from 'url';
4
6
  import qs from 'querystring';
5
7
  import type { ModernServerContext as ModernServerContextInterface, Metrics, Logger } from '@modern-js/types/server';
8
+ export declare type ContextOptions = {
9
+ logger?: Logger;
10
+ metrics?: Metrics;
11
+ };
6
12
  export declare class ModernServerContext implements ModernServerContextInterface {
7
13
  /**
8
14
  * http request
@@ -20,13 +26,7 @@ export declare class ModernServerContext implements ModernServerContextInterface
20
26
  params: Record<string, string>;
21
27
  logger: Logger;
22
28
  metrics?: Metrics;
23
- constructor(req: IncomingMessage, res: ServerResponse, {
24
- logger,
25
- metrics
26
- }: {
27
- logger: Logger;
28
- metrics: Metrics;
29
- });
29
+ constructor(req: IncomingMessage, res: ServerResponse);
30
30
  private bind;
31
31
  setParams(params: Record<string, string>): void;
32
32
  getReqHeader(key: string): string | string[];
@@ -1,11 +1,4 @@
1
1
  import { IncomingMessage, ServerResponse } from 'http';
2
- import { Metrics, Logger } from '../../type';
3
2
  import { ModernServerContext } from './context';
4
- export declare const createContext: (req: IncomingMessage, res: ServerResponse, {
5
- logger,
6
- metrics
7
- }: {
8
- logger: Logger;
9
- metrics: Metrics;
10
- }) => ModernServerContext;
3
+ export declare const createContext: (req: IncomingMessage, res: ServerResponse) => ModernServerContext;
11
4
  export { ModernServerContext };
@@ -1,10 +1,19 @@
1
1
  import { RenderResult } from '../../type';
2
2
  import { ModernRoute } from '../route';
3
3
  import { ModernServerContext } from '../context';
4
+ import { ServerHookRunner } from "../../type.d";
4
5
  export declare const createRenderHandler: ({
5
6
  distDir,
6
7
  staticGenerate
7
8
  }: {
8
9
  distDir: string;
9
10
  staticGenerate: boolean;
10
- }) => (ctx: ModernServerContext, route: ModernRoute) => Promise<RenderResult | null>;
11
+ }) => ({
12
+ ctx,
13
+ route,
14
+ runner
15
+ }: {
16
+ ctx: ModernServerContext;
17
+ route: ModernRoute;
18
+ runner: ServerHookRunner;
19
+ }) => Promise<RenderResult | null>;
@@ -1,9 +1,10 @@
1
1
  import { ModernServerContext } from '../context';
2
2
  import { RenderResult } from '../../type';
3
+ import { ServerHookRunner } from "../../type.d";
3
4
  export declare const render: (ctx: ModernServerContext, renderOptions: {
4
5
  distDir: string;
5
6
  bundle: string;
6
7
  template: string;
7
8
  entryName: string;
8
9
  staticGenerate: boolean;
9
- }) => Promise<RenderResult>;
10
+ }, runner: ServerHookRunner) => Promise<RenderResult>;
@@ -1,7 +1,5 @@
1
- /// <reference types="node" />
2
1
  /// <reference types="react" />
3
- import { IncomingHttpHeaders } from 'http';
4
- import { Metrics, Logger } from '../../type';
2
+ import { BaseSSRServerContext } from '@modern-js/types/server';
5
3
  declare type MetaKeyMap = {
6
4
  header?: string[];
7
5
  query?: string[];
@@ -24,24 +22,7 @@ export declare enum RenderLevel {
24
22
  SERVER_PREFETCH = 1,
25
23
  SERVER_RENDER = 2,
26
24
  }
27
- export declare type SSRServerContext = {
28
- request: {
29
- params: Record<string, string>;
30
- pathname: string;
31
- query: Record<string, string>;
32
- headers: IncomingHttpHeaders;
33
- cookie?: string;
34
- };
35
- redirection: {
36
- url?: string;
37
- status?: number;
38
- };
39
- distDir: string;
40
- template: string;
41
- entryName: string;
42
- logger: Logger;
43
- metrics?: Metrics;
44
- loadableManifest?: string;
25
+ export declare type SSRServerContext = BaseSSRServerContext & {
45
26
  cacheConfig?: CacheConfig;
46
27
  staticGenerate?: boolean;
47
28
  };
@@ -11,4 +11,5 @@ export declare class RouteMatchManager {
11
11
  matchEntry(entryname: string): RouteMatcher | undefined;
12
12
  getBundles(): (string | undefined)[];
13
13
  }
14
- export type { ModernRouteInterface, RouteMatcher, ModernRoute };
14
+ export type { ModernRouteInterface, ModernRoute };
15
+ export { RouteMatcher };
@@ -26,9 +26,9 @@ export declare class ModernServer {
26
26
  private routeRenderHandler;
27
27
  private frameWebHandler;
28
28
  private frameAPIHandler;
29
+ private proxyHandler;
29
30
  private _handler;
30
31
  private readonly staticGenerate;
31
- private proxyHandler;
32
32
  constructor({
33
33
  pwd,
34
34
  config,
@@ -4,6 +4,12 @@ import { serverManager } from '@modern-js/server-plugin';
4
4
  import type { NormalizedConfig } from '@modern-js/core';
5
5
  import type { Metrics, Logger, NextFunction } from '@modern-js/types/server';
6
6
  import { ModernRouteInterface } from './libs/route';
7
+ declare module 'http' {
8
+ interface IncomingMessage {
9
+ logger: Logger;
10
+ metrics: Metrics;
11
+ }
12
+ }
7
13
  declare module '@modern-js/core' {
8
14
  interface UserConfig {
9
15
  bff: {
@@ -3,5 +3,4 @@ export declare const mergeExtension: (users: any[]) => {
3
3
  };
4
4
  export declare const toMessage: (dig: string, e: Error | string) => string;
5
5
  export declare const noop: () => void;
6
- export declare const createErrorDocument: (status: number, text: string) => string;
7
- export declare function applyMixins(derivedCtor: any, constructors: any[]): void;
6
+ export declare const createErrorDocument: (status: number, text: string) => string;
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  "modern",
12
12
  "modern.js"
13
13
  ],
14
- "version": "1.2.0",
14
+ "version": "1.2.1-beta.0",
15
15
  "jsnext:source": "./src/index.ts",
16
16
  "types": "./dist/types/index.d.ts",
17
17
  "main": "./dist/js/node/index.js",
@@ -61,8 +61,8 @@
61
61
  "ws": "^8.2.0"
62
62
  },
63
63
  "devDependencies": {
64
- "@modern-js/module-tools": "^1.1.2",
65
- "@modern-js/plugin-testing": "^1.1.1",
64
+ "@modern-js/module-tools": "^1.1.3",
65
+ "@modern-js/plugin-testing": "^1.2.0",
66
66
  "@modern-js/types": "^1.1.4",
67
67
  "@types/jest": "^26",
68
68
  "@types/lru-cache": "^5.1.1",
@@ -78,7 +78,9 @@
78
78
  "@types/webpack-dev-middleware": "^5.0.2",
79
79
  "@types/ws": "^7.4.7",
80
80
  "typescript": "^4",
81
- "webpack": "^5.54.0"
81
+ "webpack": "^5.54.0",
82
+ "node-mocks-http": "^1.11.0",
83
+ "portfinder": "^1.0.28"
82
84
  },
83
85
  "peerDependencies": {
84
86
  "webpack": "^5.54.0"
@@ -97,7 +99,7 @@
97
99
  "new": "modern new",
98
100
  "build": "modern build",
99
101
  "dev": "modern build --watch",
100
- "test": "modern test --passWithNoTests"
102
+ "test": "modern test"
101
103
  },
102
104
  "readme": "\n<p align=\"center\">\n <a href=\"https://modernjs.dev\" target=\"blank\"><img src=\"https://lf3-static.bytednsdoc.com/obj/eden-cn/ylaelkeh7nuhfnuhf/modernjs-cover.png\" width=\"300\" alt=\"Modern.js Logo\" /></a>\n</p>\n<p align=\"center\">\n现代 Web 工程体系\n <br/>\n <a href=\"https://modernjs.dev\" target=\"blank\">\n modernjs.dev\n </a>\n</p>\n<p align=\"center\">\n The meta-framework suite designed from scratch for frontend-focused modern web development\n</p>\n\n# Introduction\n\n> The doc site ([modernjs.dev](https://modernjs.dev)) and articles are only available in Chinese for now, we are planning to add English versions soon.\n\n- [Modern.js: Hello, World!](https://zhuanlan.zhihu.com/p/426707646)\n\n## Getting Started\n\n- [Quick Start](https://modernjs.dev/docs/start)\n- [Guides](https://modernjs.dev/docs/guides)\n- [API References](https://modernjs.dev/docs/apis)\n\n## Contributing\n\n- [Contributing Guide](https://github.com/modern-js-dev/modern.js/blob/main/CONTRIBUTING.md)\n"
103
105
  }
package/src/index.ts CHANGED
@@ -1,19 +1,13 @@
1
1
  import { ModernServerOptions } from './type';
2
-
3
2
  import { Server } from './server';
4
3
 
5
- export * from './type';
6
- export * from './libs/context';
7
- export * from './libs/route';
8
4
  export type { SSRServerContext } from './libs/render/type';
9
5
  export { Server };
6
+ export type { ModernServerOptions };
10
7
 
11
8
  export default (options: ModernServerOptions): Promise<Server> => {
12
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
13
- const allowEnvs = ['production', 'development', 'test'];
14
-
15
9
  if (options == null) {
16
- throw new Error();
10
+ throw new Error('can not start mserver without options');
17
11
  }
18
12
 
19
13
  const server = new Server(options);
@@ -8,6 +8,11 @@ import type {
8
8
  } from '@modern-js/types/server';
9
9
  import { toMessage } from '../../utils';
10
10
 
11
+ export type ContextOptions = {
12
+ logger?: Logger;
13
+ metrics?: Metrics;
14
+ };
15
+
11
16
  export class ModernServerContext implements ModernServerContextInterface {
12
17
  /**
13
18
  * http request
@@ -28,15 +33,11 @@ export class ModernServerContext implements ModernServerContextInterface {
28
33
 
29
34
  public metrics?: Metrics;
30
35
 
31
- constructor(
32
- req: IncomingMessage,
33
- res: ServerResponse,
34
- { logger, metrics }: { logger: Logger; metrics: Metrics },
35
- ) {
36
+ constructor(req: IncomingMessage, res: ServerResponse) {
36
37
  this.req = req;
37
38
  this.res = res;
38
- this.logger = logger;
39
- this.metrics = metrics;
39
+ this.logger = req.logger;
40
+ this.metrics = req.metrics;
40
41
 
41
42
  this.bind();
42
43
  }
@@ -1,11 +1,7 @@
1
1
  import { IncomingMessage, ServerResponse } from 'http';
2
- import { Metrics, Logger } from '../../type';
3
2
  import { ModernServerContext } from './context';
4
3
 
5
- export const createContext = (
6
- req: IncomingMessage,
7
- res: ServerResponse,
8
- { logger, metrics }: { logger: Logger; metrics: Metrics },
9
- ) => new ModernServerContext(req, res, { logger, metrics });
4
+ export const createContext = (req: IncomingMessage, res: ServerResponse) =>
5
+ new ModernServerContext(req, res);
10
6
 
11
7
  export { ModernServerContext };
package/src/libs/proxy.ts CHANGED
@@ -54,7 +54,7 @@ export const createProxyHandler = (proxyOptions: ProxyOptions) => {
54
54
  );
55
55
  }
56
56
  } else {
57
- formatedProxy.concat(proxyOptions);
57
+ formatedProxy.push(...proxyOptions);
58
58
  }
59
59
 
60
60
  const middlewares = formatedProxy.map(option => {
@@ -15,6 +15,8 @@ const createCacheConfig = (config: any = {}) => ({
15
15
  ...config,
16
16
  });
17
17
 
18
+ jest.setTimeout(60000);
19
+
18
20
  describe('cache', () => {
19
21
  it('should cache correctly', async () => {
20
22
  destroyCache();
@@ -179,7 +181,6 @@ describe('cache', () => {
179
181
  }
180
182
  });
181
183
 
182
- jest.setTimeout(1000 * 10);
183
184
  it('should stale cache correctly', async () => {
184
185
  destroyCache();
185
186
  const cache = createCache();
@@ -207,7 +208,6 @@ describe('cache', () => {
207
208
  expect(staleResult?.isStale).toBe(true);
208
209
  });
209
210
 
210
- jest.setTimeout(1000 * 15);
211
211
  it('should garbage cache correctly', async () => {
212
212
  destroyCache();
213
213
  const cache = createCache();
@@ -9,6 +9,7 @@ import { readFile } from './reader';
9
9
  import * as ssr from './ssr';
10
10
  import { supportModern, getModernEntry } from './modern';
11
11
  import { ERROR_DIGEST } from '@/constants';
12
+ import { ServerHookRunner } from '@/type';
12
13
 
13
14
  export const createRenderHandler = ({
14
15
  distDir,
@@ -17,10 +18,15 @@ export const createRenderHandler = ({
17
18
  distDir: string;
18
19
  staticGenerate: boolean;
19
20
  }) =>
20
- async function render(
21
- ctx: ModernServerContext,
22
- route: ModernRoute,
23
- ): Promise<RenderResult | null> {
21
+ async function render({
22
+ ctx,
23
+ route,
24
+ runner,
25
+ }: {
26
+ ctx: ModernServerContext;
27
+ route: ModernRoute;
28
+ runner: ServerHookRunner;
29
+ }): Promise<RenderResult | null> {
24
30
  if (ctx.resHasHandled()) {
25
31
  return null;
26
32
  }
@@ -43,13 +49,17 @@ export const createRenderHandler = ({
43
49
  // handles ssr first
44
50
  if (route.isSSR) {
45
51
  try {
46
- const result = await ssr.render(ctx, {
47
- distDir,
48
- entryName: route.entryName,
49
- bundle: route.bundle,
50
- template: templateHTML,
51
- staticGenerate,
52
- });
52
+ const result = await ssr.render(
53
+ ctx,
54
+ {
55
+ distDir,
56
+ entryName: route.entryName,
57
+ bundle: route.bundle,
58
+ template: templateHTML,
59
+ staticGenerate,
60
+ },
61
+ runner,
62
+ );
53
63
  return result;
54
64
  } catch (err) {
55
65
  ctx.error(ERROR_DIGEST.ERENDER, (err as Error).stack);
@@ -24,7 +24,7 @@ const createCacheItem = async (filepath: string, mtime: Date) => {
24
24
  class LruReader {
25
25
  private readonly cache: LRU<string, FileCache>;
26
26
 
27
- private timer?: NodeJS.Timeout;
27
+ // private timer?: NodeJS.Timeout;
28
28
 
29
29
  constructor() {
30
30
  this.cache = new LRU({
@@ -35,13 +35,13 @@ class LruReader {
35
35
  }
36
36
 
37
37
  public init() {
38
- this.timeTask();
38
+ // this.timeTask();
39
39
  }
40
40
 
41
41
  public close() {
42
- if (this.timer) {
43
- clearInterval(this.timer);
44
- }
42
+ // if (this.timer) {
43
+ // clearInterval(this.timer);
44
+ // }
45
45
  }
46
46
 
47
47
  public async read(filepath: string) {
@@ -94,9 +94,9 @@ class LruReader {
94
94
  }
95
95
  }
96
96
 
97
- private timeTask() {
98
- this.timer = setInterval(() => this.update, 5 * 60 * 1000).unref();
99
- }
97
+ // private timeTask() {
98
+ // this.timer = setInterval(() => this.update, 5 * 60 * 1000).unref();
99
+ // }
100
100
  }
101
101
 
102
102
  const reader = new LruReader();
@@ -5,6 +5,7 @@ import { ModernServerContext } from '../context';
5
5
  import { RenderResult } from '../../type';
6
6
  import cache from './cache';
7
7
  import { SSRServerContext } from './type';
8
+ import { ServerHookRunner } from '@/type';
8
9
 
9
10
  export const render = async (
10
11
  ctx: ModernServerContext,
@@ -15,6 +16,7 @@ export const render = async (
15
16
  entryName: string;
16
17
  staticGenerate: boolean;
17
18
  },
19
+ runner: ServerHookRunner,
18
20
  ): Promise<RenderResult> => {
19
21
  const { bundle, distDir, template, entryName, staticGenerate } =
20
22
  renderOptions;
@@ -37,6 +39,8 @@ export const render = async (
37
39
  metrics: ctx.metrics,
38
40
  };
39
41
 
42
+ runner.extendSSRContext(context);
43
+
40
44
  const serverRender = require(bundleJS)[SERVER_RENDER_FUNCTION_NAME];
41
45
 
42
46
  const html = await cache(serverRender, ctx)(context);
@@ -1,5 +1,4 @@
1
- import { IncomingHttpHeaders } from 'http';
2
- import { Metrics, Logger } from '../../type';
1
+ import { BaseSSRServerContext } from '@modern-js/types/server';
3
2
 
4
3
  type MetaKeyMap = {
5
4
  header?: string[];
@@ -26,21 +25,7 @@ export enum RenderLevel {
26
25
  SERVER_RENDER,
27
26
  }
28
27
 
29
- export type SSRServerContext = {
30
- request: {
31
- params: Record<string, string>;
32
- pathname: string;
33
- query: Record<string, string>;
34
- headers: IncomingHttpHeaders;
35
- cookie?: string;
36
- };
37
- redirection: { url?: string; status?: number };
38
- distDir: string;
39
- template: string;
40
- entryName: string;
41
- logger: Logger;
42
- metrics?: Metrics;
43
- loadableManifest?: string;
28
+ export type SSRServerContext = BaseSSRServerContext & {
44
29
  cacheConfig?: CacheConfig;
45
30
  staticGenerate?: boolean;
46
31
  };
@@ -73,4 +73,5 @@ export class RouteMatchManager {
73
73
  }
74
74
  }
75
75
 
76
- export type { ModernRouteInterface, RouteMatcher, ModernRoute };
76
+ export type { ModernRouteInterface, ModernRoute };
77
+ export { RouteMatcher };
@@ -135,7 +135,7 @@ export class Server {
135
135
  ...appContext,
136
136
  distDirectory: path.join(
137
137
  options.pwd,
138
- options.config.output.path || 'dist',
138
+ options.config.output?.path || 'dist',
139
139
  ),
140
140
  });
141
141
  });
@@ -87,12 +87,12 @@ export class ModernServer {
87
87
 
88
88
  private frameAPIHandler: Adapter | null = null;
89
89
 
90
+ private proxyHandler: ReturnType<typeof createProxyHandler> = null;
91
+
90
92
  private _handler!: (context: ModernServerContext, next: NextFunction) => void;
91
93
 
92
94
  private readonly staticGenerate: boolean = false;
93
95
 
94
- private proxyHandler: ReturnType<typeof createProxyHandler> = null;
95
-
96
96
  constructor({
97
97
  pwd,
98
98
  config,
@@ -107,7 +107,7 @@ export class ModernServer {
107
107
  this.isDev = Boolean(dev);
108
108
 
109
109
  this.pwd = pwd;
110
- this.distDir = path.join(pwd, config.output.path || 'dist');
110
+ this.distDir = path.join(pwd, config.output?.path || 'dist');
111
111
  this.workDir = this.isDev ? pwd : this.distDir;
112
112
  this.conf = config;
113
113
  this.logger = logger!;
@@ -162,7 +162,7 @@ export class ModernServer {
162
162
 
163
163
  await this.prepareFrameHandler();
164
164
 
165
- const { favicon, faviconByEntries } = this.conf.output;
165
+ const { favicon, faviconByEntries } = this.conf.output || {};
166
166
  const favicons = this.prepareFavicons(favicon, faviconByEntries);
167
167
  // Only work when without setting `assetPrefix`.
168
168
  // Setting `assetPrefix` means these resources should be uploaded to CDN.
@@ -356,7 +356,11 @@ export class ModernServer {
356
356
  }
357
357
 
358
358
  protected async handleWeb(context: ModernServerContext, route: ModernRoute) {
359
- return this.routeRenderHandler(context, route);
359
+ return this.routeRenderHandler({
360
+ ctx: context,
361
+ route,
362
+ runner: this.runner,
363
+ });
360
364
  }
361
365
 
362
366
  protected verifyMatch(_c: ModernServerContext, _m: RouteMatcher) {
@@ -372,7 +376,7 @@ export class ModernServer {
372
376
  await this.emitRouteHook('beforeMatch', { context });
373
377
 
374
378
  // match routes in the route spec
375
- const matched = this.router.match(context.url);
379
+ const matched = this.router.match(context.path);
376
380
  if (!matched) {
377
381
  this.render404(context);
378
382
  return;
@@ -546,10 +550,9 @@ export class ModernServer {
546
550
  },
547
551
  ) {
548
552
  res.statusCode = 200;
549
- const context: ModernServerContext = createContext(req, res, {
550
- logger: this.logger,
551
- metrics: this.metrics,
552
- });
553
+ req.logger = req.logger || this.logger;
554
+ req.metrics = req.metrics || this.metrics;
555
+ const context: ModernServerContext = createContext(req, res);
553
556
 
554
557
  try {
555
558
  this._handler(context, next);
@@ -580,7 +583,11 @@ export class ModernServer {
580
583
  // check entryName, aviod matched '/' route
581
584
  if (entryName === status.toString() || entryName === '_error') {
582
585
  try {
583
- const file = await this.routeRenderHandler(context, route);
586
+ const file = await this.routeRenderHandler({
587
+ route,
588
+ ctx: context,
589
+ runner: this.runner,
590
+ });
584
591
  if (file) {
585
592
  context.res.end(file.content);
586
593
  return;
package/src/type.ts CHANGED
@@ -5,6 +5,13 @@ import type { NormalizedConfig } from '@modern-js/core';
5
5
  import type { Metrics, Logger, NextFunction } from '@modern-js/types/server';
6
6
  import { ModernRouteInterface } from './libs/route';
7
7
 
8
+ declare module 'http' {
9
+ interface IncomingMessage {
10
+ logger: Logger;
11
+ metrics: Metrics;
12
+ }
13
+ }
14
+
8
15
  declare module '@modern-js/core' {
9
16
  interface UserConfig {
10
17
  bff: {
package/src/utils.ts CHANGED
@@ -49,17 +49,3 @@ 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
- }
@@ -0,0 +1,6 @@
1
+ module.exports = {
2
+ extends: ['@modern-js'],
3
+ parserOptions: {
4
+ project: require.resolve('./tsconfig.json'),
5
+ },
6
+ };
@@ -0,0 +1,41 @@
1
+ import EventEmitter from 'events';
2
+ import { Readable } from 'stream';
3
+ import httpMocks from 'node-mocks-http';
4
+ import { createContext } from '../src/libs/context';
5
+
6
+ describe('test server context', () => {
7
+ test('should route api work correctly', () => {
8
+ const req = httpMocks.createRequest({
9
+ url: '/pathname?foo=baz',
10
+ headers: {
11
+ host: 'modernjs.com',
12
+ },
13
+ eventEmitter: Readable,
14
+ method: 'GET',
15
+ });
16
+ const res = httpMocks.createResponse({ eventEmitter: EventEmitter });
17
+ const {
18
+ method,
19
+ url,
20
+ origin,
21
+ host,
22
+ path,
23
+ href,
24
+ query,
25
+ querystring,
26
+ protocol,
27
+ params,
28
+ } = createContext(req, res);
29
+
30
+ expect(method).toBe('GET');
31
+ expect(url).toBe('/pathname?foo=baz');
32
+ expect(origin).toBe('http://modernjs.com');
33
+ expect(host).toBe('modernjs.com');
34
+ expect(path).toBe('/pathname');
35
+ expect(href).toBe('http://modernjs.com/pathname?foo=baz');
36
+ expect(query).toEqual({ foo: 'baz' });
37
+ expect(querystring).toBe('foo=baz');
38
+ expect(protocol).toBe('http');
39
+ expect(params).toEqual({});
40
+ });
41
+ });
@@ -0,0 +1 @@
1
+ console.info('index.js');
@@ -0,0 +1,5 @@
1
+ module.exports = {
2
+ server: {
3
+ ssr: true,
4
+ },
5
+ };
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "deploy",
3
+ "version": "0.1.0",
4
+ "scripts": {
5
+ "reset": "del-cli node_modules",
6
+ "dev": "modern dev",
7
+ "build": "modern build",
8
+ "start": "modern start",
9
+ "new": "modern new",
10
+ "lint": "modern lint",
11
+ "deploy": "modern deploy"
12
+ },
13
+ "dependencies": {},
14
+ "devDependencies": {},
15
+ "modernConfig": {
16
+ "runtime": {
17
+ "router": true,
18
+ "state": true
19
+ }
20
+ }
21
+ }