@modern-js/server 1.1.5-beta.1 → 1.2.1-beta.2
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.
- package/CHANGELOG.md +20 -0
- package/dist/js/modern/index.js +1 -7
- package/dist/js/modern/libs/context/context.js +3 -6
- package/dist/js/modern/libs/context/index.js +1 -7
- package/dist/js/modern/libs/hook-api/template.js +4 -4
- package/dist/js/modern/libs/proxy.js +1 -1
- package/dist/js/modern/libs/render/cache/__tests__/cache.test.js +1 -2
- package/dist/js/modern/libs/render/reader.js +8 -11
- package/dist/js/modern/libs/route/index.js +2 -1
- package/dist/js/modern/server/index.js +4 -2
- package/dist/js/modern/server/modern-server.js +11 -9
- package/dist/js/modern/utils.js +1 -9
- package/dist/js/node/index.js +1 -49
- package/dist/js/node/libs/context/context.js +3 -6
- package/dist/js/node/libs/context/index.js +1 -7
- package/dist/js/node/libs/hook-api/template.js +4 -4
- package/dist/js/node/libs/proxy.js +1 -1
- package/dist/js/node/libs/render/cache/__tests__/cache.test.js +1 -2
- package/dist/js/node/libs/render/reader.js +8 -11
- package/dist/js/node/libs/route/index.js +6 -0
- package/dist/js/node/server/index.js +4 -2
- package/dist/js/node/server/modern-server.js +11 -9
- package/dist/js/node/utils.js +2 -12
- package/dist/types/index.d.ts +1 -3
- package/dist/types/libs/context/context.d.ts +7 -7
- package/dist/types/libs/context/index.d.ts +1 -8
- package/dist/types/libs/hook-api/template.d.ts +4 -4
- package/dist/types/libs/route/index.d.ts +2 -1
- package/dist/types/server/modern-server.d.ts +1 -1
- package/dist/types/type.d.ts +6 -0
- package/dist/types/utils.d.ts +1 -2
- package/package.json +13 -10
- package/src/index.ts +2 -8
- package/src/libs/context/context.ts +8 -7
- package/src/libs/context/index.ts +2 -6
- package/src/libs/hook-api/template.ts +4 -4
- package/src/libs/proxy.ts +1 -1
- package/src/libs/render/cache/__tests__/cache.test.ts +2 -2
- package/src/libs/render/reader.ts +8 -8
- package/src/libs/render/type.ts +0 -2
- package/src/libs/route/index.ts +2 -1
- package/src/server/index.ts +2 -2
- package/src/server/modern-server.ts +10 -10
- package/src/type.ts +7 -0
- package/src/utils.ts +0 -14
- package/tests/.eslintrc.js +6 -0
- package/tests/context.test.ts +41 -0
- package/tests/fixtures/hosting-files/static/index.js +1 -0
- package/tests/fixtures/pure/modern.config.js +5 -0
- package/tests/fixtures/pure/package.json +21 -0
- package/tests/fixtures/pure/src/App.css +119 -0
- package/tests/fixtures/pure/src/App.tsx +43 -0
- package/tests/fixtures/pure/tsconfig.json +13 -0
- package/tests/fixtures/route-spec/index.json +29 -0
- package/tests/helper.ts +8 -0
- package/tests/hook.test.ts +44 -0
- package/tests/middleware.test.ts +178 -0
- package/tests/route.test.ts +54 -0
- package/tests/server.test.ts +89 -0
- package/tests/tsconfig.json +14 -0
- 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 };
|
|
@@ -3,10 +3,10 @@ declare class TemplateAPI {
|
|
|
3
3
|
constructor(content: string);
|
|
4
4
|
get(): string;
|
|
5
5
|
set(content: string): void;
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
prependHead(fragment: string): this;
|
|
7
|
+
appendHead(fragment: string): this;
|
|
8
|
+
prependBody(fragment: string): this;
|
|
9
|
+
appendBody(fragment: string): this;
|
|
10
10
|
replace(reg: RegExp | string, text: string): this;
|
|
11
11
|
}
|
|
12
12
|
|
|
@@ -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,
|
|
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,
|
package/dist/types/type.d.ts
CHANGED
|
@@ -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: {
|
package/dist/types/utils.d.ts
CHANGED
|
@@ -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.1
|
|
14
|
+
"version": "1.2.1-beta.2",
|
|
15
15
|
"jsnext:source": "./src/index.ts",
|
|
16
16
|
"types": "./dist/types/index.d.ts",
|
|
17
17
|
"main": "./dist/js/node/index.js",
|
|
@@ -33,12 +33,12 @@
|
|
|
33
33
|
"@babel/preset-typescript": "^7.15.0",
|
|
34
34
|
"@babel/register": "^7.15.3",
|
|
35
35
|
"@babel/runtime": "^7",
|
|
36
|
-
"@modern-js/core": "^1.
|
|
36
|
+
"@modern-js/core": "^1.2.0",
|
|
37
37
|
"@modern-js/hmr-client": "^1.1.1",
|
|
38
|
-
"@modern-js/server-plugin": "^1.1.
|
|
38
|
+
"@modern-js/server-plugin": "^1.1.3",
|
|
39
39
|
"@modern-js/server-utils": "^1.1.2",
|
|
40
40
|
"@modern-js/bff-utils": "^1.1.1",
|
|
41
|
-
"@modern-js/utils": "^1.1.
|
|
41
|
+
"@modern-js/utils": "^1.1.5",
|
|
42
42
|
"axios": "^0.21.4",
|
|
43
43
|
"babel-plugin-module-resolver": "^4.1.0",
|
|
44
44
|
"chokidar": "^3.5.2",
|
|
@@ -61,9 +61,9 @@
|
|
|
61
61
|
"ws": "^8.2.0"
|
|
62
62
|
},
|
|
63
63
|
"devDependencies": {
|
|
64
|
-
"@modern-js/module-tools": "^1.1.
|
|
65
|
-
"@modern-js/plugin-testing": "^1.
|
|
66
|
-
"@modern-js/types": "^1.1.
|
|
64
|
+
"@modern-js/module-tools": "^1.1.3",
|
|
65
|
+
"@modern-js/plugin-testing": "^1.2.0",
|
|
66
|
+
"@modern-js/types": "^1.1.4",
|
|
67
67
|
"@types/jest": "^26",
|
|
68
68
|
"@types/lru-cache": "^5.1.1",
|
|
69
69
|
"@types/mime-types": "^2.1.0",
|
|
@@ -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,6 +99,7 @@
|
|
|
97
99
|
"new": "modern new",
|
|
98
100
|
"build": "modern build",
|
|
99
101
|
"dev": "modern build --watch",
|
|
100
|
-
"test": "modern test
|
|
101
|
-
}
|
|
102
|
+
"test": "modern test"
|
|
103
|
+
},
|
|
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"
|
|
102
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
|
|
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 };
|
|
@@ -24,22 +24,22 @@ class TemplateAPI {
|
|
|
24
24
|
this.content = content;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
public
|
|
27
|
+
public prependHead(fragment: string) {
|
|
28
28
|
const { head } = RegList.before;
|
|
29
29
|
return this.replace(head, `${head}${fragment}`);
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
public
|
|
32
|
+
public appendHead(fragment: string) {
|
|
33
33
|
const { head } = RegList.after;
|
|
34
34
|
return this.replace(head, `${fragment}${head}`);
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
public
|
|
37
|
+
public prependBody(fragment: string) {
|
|
38
38
|
const { body } = RegList.before;
|
|
39
39
|
return this.replace(body, `${body}${fragment}`);
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
public
|
|
42
|
+
public appendBody(fragment: string) {
|
|
43
43
|
const { body } = RegList.after;
|
|
44
44
|
return this.replace(body, `${fragment}${body}`);
|
|
45
45
|
}
|
package/src/libs/proxy.ts
CHANGED
|
@@ -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();
|
|
@@ -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
|
-
|
|
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
|
-
|
|
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();
|
package/src/libs/render/type.ts
CHANGED
package/src/libs/route/index.ts
CHANGED
package/src/server/index.ts
CHANGED
|
@@ -68,7 +68,7 @@ export class Server {
|
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
public listen(port = 8080, listener: any) {
|
|
71
|
-
this.app.listen(port, () => {
|
|
71
|
+
this.app.listen(process.env.PORT || port, () => {
|
|
72
72
|
if (listener) {
|
|
73
73
|
listener();
|
|
74
74
|
}
|
|
@@ -135,7 +135,7 @@ export class Server {
|
|
|
135
135
|
...appContext,
|
|
136
136
|
distDirectory: path.join(
|
|
137
137
|
options.pwd,
|
|
138
|
-
options.config.output
|
|
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
|
|
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.
|
|
@@ -229,6 +229,7 @@ export class ModernServer {
|
|
|
229
229
|
}
|
|
230
230
|
|
|
231
231
|
// add promisify request handler to server
|
|
232
|
+
// handler should do not do more things after invoke next
|
|
232
233
|
protected addHandler(handler: ModernServerHandler) {
|
|
233
234
|
if ((handler as any)[Symbol.toStringTag] === 'AsyncFunction') {
|
|
234
235
|
this.handlers.push(handler as ModernServerAsyncHandler);
|
|
@@ -376,7 +377,7 @@ export class ModernServer {
|
|
|
376
377
|
await this.emitRouteHook('beforeMatch', { context });
|
|
377
378
|
|
|
378
379
|
// match routes in the route spec
|
|
379
|
-
const matched = this.router.match(context.
|
|
380
|
+
const matched = this.router.match(context.path);
|
|
380
381
|
if (!matched) {
|
|
381
382
|
this.render404(context);
|
|
382
383
|
return;
|
|
@@ -502,7 +503,7 @@ export class ModernServer {
|
|
|
502
503
|
try {
|
|
503
504
|
// Todo Safety xss
|
|
504
505
|
const injection = JSON.stringify({ ...manifest, modules });
|
|
505
|
-
templateAPI.
|
|
506
|
+
templateAPI.appendHead(
|
|
506
507
|
`<script>window.modern_manifest=${injection}</script>`,
|
|
507
508
|
);
|
|
508
509
|
} catch (e) {
|
|
@@ -550,10 +551,9 @@ export class ModernServer {
|
|
|
550
551
|
},
|
|
551
552
|
) {
|
|
552
553
|
res.statusCode = 200;
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
});
|
|
554
|
+
req.logger = req.logger || this.logger;
|
|
555
|
+
req.metrics = req.metrics || this.metrics;
|
|
556
|
+
const context: ModernServerContext = createContext(req, res);
|
|
557
557
|
|
|
558
558
|
try {
|
|
559
559
|
this._handler(context, next);
|
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,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,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
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
html,
|
|
2
|
+
body {
|
|
3
|
+
padding: 0;
|
|
4
|
+
margin: 0;
|
|
5
|
+
font-family: nunito_for_arco, Helvetica Neue, Helvetica, PingFang SC,
|
|
6
|
+
Hiragino Sans GB, Microsoft YaHei, 微软雅黑, Arial, sans-serif;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
* {
|
|
10
|
+
-webkit-font-smoothing: antialiased;
|
|
11
|
+
-moz-osx-font-smoothing: grayscale;
|
|
12
|
+
box-sizing: border-box;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.container {
|
|
16
|
+
min-height: 100vh;
|
|
17
|
+
max-width: 100%;
|
|
18
|
+
display: flex;
|
|
19
|
+
flex-direction: column;
|
|
20
|
+
justify-content: center;
|
|
21
|
+
align-items: center;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
main {
|
|
25
|
+
padding: 5rem 0;
|
|
26
|
+
flex: 1;
|
|
27
|
+
display: flex;
|
|
28
|
+
flex-direction: column;
|
|
29
|
+
justify-content: center;
|
|
30
|
+
align-items: center;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.footer {
|
|
34
|
+
width: 100%;
|
|
35
|
+
height: 80px;
|
|
36
|
+
border-top: 1px solid #eaeaea;
|
|
37
|
+
display: flex;
|
|
38
|
+
justify-content: center;
|
|
39
|
+
align-items: center;
|
|
40
|
+
background-color: #470000;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.footer a {
|
|
44
|
+
display: flex;
|
|
45
|
+
justify-content: center;
|
|
46
|
+
align-items: center;
|
|
47
|
+
flex-grow: 1;
|
|
48
|
+
color: #f4f4f4;
|
|
49
|
+
text-decoration: none;
|
|
50
|
+
font-size: 1.1rem;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.logo {
|
|
54
|
+
margin-bottom: 2rem;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.logo svg {
|
|
58
|
+
width: 450px;
|
|
59
|
+
height: 132px;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.description {
|
|
63
|
+
text-align: center;
|
|
64
|
+
line-height: 1.5;
|
|
65
|
+
font-size: 1.5rem;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.code {
|
|
69
|
+
background: #fafafa;
|
|
70
|
+
border-radius: 5px;
|
|
71
|
+
padding: 0.75rem;
|
|
72
|
+
font-size: 1.1rem;
|
|
73
|
+
font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono,
|
|
74
|
+
Bitstream Vera Sans Mono, Courier New, monospace;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
@media (max-width: 600px) {
|
|
78
|
+
.grid {
|
|
79
|
+
width: 100%;
|
|
80
|
+
flex-direction: column;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.grid {
|
|
85
|
+
display: flex;
|
|
86
|
+
align-items: center;
|
|
87
|
+
justify-content: center;
|
|
88
|
+
flex-wrap: wrap;
|
|
89
|
+
width: 800px;
|
|
90
|
+
margin-top: 3rem;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.card {
|
|
94
|
+
margin: 1rem;
|
|
95
|
+
padding: 1.5rem;
|
|
96
|
+
display: flex;
|
|
97
|
+
align-items: center;
|
|
98
|
+
justify-content: center;
|
|
99
|
+
height: 100px;
|
|
100
|
+
color: inherit;
|
|
101
|
+
text-decoration: none;
|
|
102
|
+
border: 1px solid #470000;
|
|
103
|
+
color: #470000;
|
|
104
|
+
transition: color 0.15s ease, border-color 0.15s ease;
|
|
105
|
+
width: 45%;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.card:hover,
|
|
109
|
+
.card:focus,
|
|
110
|
+
.card:active {
|
|
111
|
+
transform: scale(1.05);
|
|
112
|
+
transition: 0.1s ease-in-out;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.card h2 {
|
|
116
|
+
font-size: 1.5rem;
|
|
117
|
+
margin: 0;
|
|
118
|
+
padding: 0;
|
|
119
|
+
}
|