@modern-js/server 1.1.4 → 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.
- package/CHANGELOG.md +20 -0
- package/dist/js/modern/index.js +1 -7
- package/dist/js/modern/libs/context/context.js +16 -11
- package/dist/js/modern/libs/context/index.js +1 -7
- package/dist/js/modern/libs/{measure.js → metrics.js} +2 -2
- 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/index.js +6 -2
- package/dist/js/modern/libs/render/reader.js +8 -11
- package/dist/js/modern/libs/render/ssr.js +3 -2
- package/dist/js/modern/libs/route/index.js +2 -1
- package/dist/js/modern/libs/route/route.js +1 -1
- package/dist/js/modern/server/dev-server/dev-server.js +11 -2
- package/dist/js/modern/server/index.js +5 -3
- package/dist/js/modern/server/modern-server.js +22 -13
- package/dist/js/modern/utils.js +1 -9
- package/dist/js/node/index.js +1 -49
- package/dist/js/node/libs/context/context.js +16 -11
- package/dist/js/node/libs/context/index.js +1 -7
- package/dist/js/node/libs/{measure.js → metrics.js} +3 -3
- 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/index.js +6 -2
- package/dist/js/node/libs/render/reader.js +8 -11
- package/dist/js/node/libs/render/ssr.js +3 -2
- package/dist/js/node/libs/route/index.js +6 -0
- package/dist/js/node/libs/route/route.js +1 -1
- package/dist/js/node/server/dev-server/dev-server.js +11 -2
- package/dist/js/node/server/index.js +5 -3
- package/dist/js/node/server/modern-server.js +22 -13
- package/dist/js/node/utils.js +2 -12
- package/dist/types/index.d.ts +1 -3
- package/dist/types/libs/context/context.d.ts +10 -10
- package/dist/types/libs/context/index.d.ts +1 -8
- package/dist/types/libs/metrics.d.ts +3 -0
- package/dist/types/libs/render/index.d.ts +10 -1
- package/dist/types/libs/render/ssr.d.ts +2 -1
- package/dist/types/libs/render/type.d.ts +2 -21
- package/dist/types/libs/route/index.d.ts +2 -1
- package/dist/types/libs/route/route.d.ts +2 -10
- package/dist/types/server/modern-server.d.ts +4 -4
- package/dist/types/type.d.ts +12 -5
- package/dist/types/utils.d.ts +1 -2
- package/package.json +11 -9
- package/src/index.ts +2 -8
- package/src/libs/context/context.ts +18 -13
- package/src/libs/context/index.ts +2 -6
- package/src/libs/{measure.ts → metrics.ts} +3 -3
- package/src/libs/proxy.ts +1 -1
- package/src/libs/render/cache/__tests__/cache.test.ts +2 -2
- package/src/libs/render/index.ts +21 -11
- package/src/libs/render/reader.ts +8 -8
- package/src/libs/render/ssr.ts +5 -1
- package/src/libs/render/type.ts +2 -17
- package/src/libs/route/index.ts +2 -1
- package/src/libs/route/route.ts +4 -20
- package/src/server/dev-server/dev-server.ts +8 -2
- package/src/server/index.ts +3 -3
- package/src/server/modern-server.ts +22 -15
- package/src/type.ts +14 -5
- 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
- package/dist/types/libs/measure.d.ts +0 -3
|
@@ -3,11 +3,16 @@ import { URL } from 'url';
|
|
|
3
3
|
import qs from 'querystring';
|
|
4
4
|
import type {
|
|
5
5
|
ModernServerContext as ModernServerContextInterface,
|
|
6
|
-
|
|
6
|
+
Metrics,
|
|
7
7
|
Logger,
|
|
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
|
|
@@ -26,17 +31,21 @@ export class ModernServerContext implements ModernServerContextInterface {
|
|
|
26
31
|
|
|
27
32
|
public logger: Logger;
|
|
28
33
|
|
|
29
|
-
public
|
|
34
|
+
public metrics?: Metrics;
|
|
30
35
|
|
|
31
|
-
constructor(
|
|
32
|
-
req: IncomingMessage,
|
|
33
|
-
res: ServerResponse,
|
|
34
|
-
{ logger, measure }: { logger: Logger; measure: Measure },
|
|
35
|
-
) {
|
|
36
|
+
constructor(req: IncomingMessage, res: ServerResponse) {
|
|
36
37
|
this.req = req;
|
|
37
38
|
this.res = res;
|
|
38
|
-
this.logger = logger;
|
|
39
|
-
this.
|
|
39
|
+
this.logger = req.logger;
|
|
40
|
+
this.metrics = req.metrics;
|
|
41
|
+
|
|
42
|
+
this.bind();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
private bind() {
|
|
46
|
+
const { req, res } = this as any;
|
|
47
|
+
req.get = (key: string) => this.getReqHeader(key);
|
|
48
|
+
res.set = (key: string, value: any) => this.res.setHeader(key, value);
|
|
40
49
|
}
|
|
41
50
|
|
|
42
51
|
public setParams(params: Record<string, string>) {
|
|
@@ -60,10 +69,6 @@ export class ModernServerContext implements ModernServerContextInterface {
|
|
|
60
69
|
return this.req.headers;
|
|
61
70
|
}
|
|
62
71
|
|
|
63
|
-
public set headers(val) {
|
|
64
|
-
this.req.headers = val;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
72
|
public get method(): string {
|
|
68
73
|
return this.req.method!;
|
|
69
74
|
}
|
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
import { IncomingMessage, ServerResponse } from 'http';
|
|
2
|
-
import { Measure, Logger } from '../../type';
|
|
3
2
|
import { ModernServerContext } from './context';
|
|
4
3
|
|
|
5
|
-
export const createContext = (
|
|
6
|
-
req
|
|
7
|
-
res: ServerResponse,
|
|
8
|
-
{ logger, measure }: { logger: Logger; measure: Measure },
|
|
9
|
-
) => new ModernServerContext(req, res, { logger, measure });
|
|
4
|
+
export const createContext = (req: IncomingMessage, res: ServerResponse) =>
|
|
5
|
+
new ModernServerContext(req, res);
|
|
10
6
|
|
|
11
7
|
export { ModernServerContext };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Metrics } from '@/type';
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const metrics: Metrics = {
|
|
4
4
|
gauges() {
|
|
5
5
|
// no impl
|
|
6
6
|
},
|
|
@@ -12,4 +12,4 @@ const measure: Measure = {
|
|
|
12
12
|
},
|
|
13
13
|
};
|
|
14
14
|
|
|
15
|
-
export {
|
|
15
|
+
export { metrics };
|
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();
|
package/src/libs/render/index.ts
CHANGED
|
@@ -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
|
|
22
|
-
route
|
|
23
|
-
|
|
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(
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
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
|
-
|
|
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/ssr.ts
CHANGED
|
@@ -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;
|
|
@@ -34,9 +36,11 @@ export const render = async (
|
|
|
34
36
|
distDir,
|
|
35
37
|
staticGenerate,
|
|
36
38
|
logger: ctx.logger,
|
|
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);
|
package/src/libs/render/type.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Measure, 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
|
-
measure?: Measure;
|
|
43
|
-
loadableManifest?: string;
|
|
28
|
+
export type SSRServerContext = BaseSSRServerContext & {
|
|
44
29
|
cacheConfig?: CacheConfig;
|
|
45
30
|
staticGenerate?: boolean;
|
|
46
31
|
};
|
package/src/libs/route/index.ts
CHANGED
package/src/libs/route/route.ts
CHANGED
|
@@ -1,22 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
// the url path for request match
|
|
5
|
-
urlPath: string;
|
|
6
|
-
// the default resource file to response to route
|
|
7
|
-
entryPath?: string;
|
|
8
|
-
// if route is spa page
|
|
9
|
-
isSPA?: boolean;
|
|
10
|
-
// if route is ssr page
|
|
11
|
-
isSSR?: boolean;
|
|
12
|
-
// if route is api service
|
|
13
|
-
isApi?: boolean;
|
|
14
|
-
// ssr js bundle for ssr page
|
|
15
|
-
bundle?: string;
|
|
16
|
-
// if route has modern product
|
|
17
|
-
enableModernMode?: boolean;
|
|
18
|
-
// specialHeader?: SpecialHeader[];
|
|
19
|
-
}
|
|
1
|
+
import { ServerRoute as ModernRouteInterface } from '@modern-js/types';
|
|
2
|
+
|
|
3
|
+
export type { ModernRouteInterface };
|
|
20
4
|
|
|
21
5
|
export class ModernRoute implements ModernRouteInterface {
|
|
22
6
|
public entryName: string;
|
|
@@ -36,7 +20,7 @@ export class ModernRoute implements ModernRouteInterface {
|
|
|
36
20
|
public enableModernMode?: boolean;
|
|
37
21
|
|
|
38
22
|
constructor(routeSpec: ModernRouteInterface) {
|
|
39
|
-
this.entryName = routeSpec.entryName;
|
|
23
|
+
this.entryName = routeSpec.entryName || '';
|
|
40
24
|
this.urlPath = routeSpec.urlPath;
|
|
41
25
|
this.entryPath = routeSpec.entryPath || '';
|
|
42
26
|
this.isSSR = routeSpec.isSSR || false;
|
|
@@ -43,9 +43,11 @@ const DEFAULT_DEV_OPTIONS: DevServerOptions = {
|
|
|
43
43
|
},
|
|
44
44
|
https: false,
|
|
45
45
|
dev: { writeToDisk: true },
|
|
46
|
+
watch: true,
|
|
46
47
|
hot: true,
|
|
47
48
|
liveReload: true,
|
|
48
49
|
};
|
|
50
|
+
|
|
49
51
|
export class ModernDevServer extends ModernServer {
|
|
50
52
|
private devProxyHandler: ReturnType<typeof createProxyHandler> = null;
|
|
51
53
|
|
|
@@ -72,7 +74,9 @@ export class ModernDevServer extends ModernServer {
|
|
|
72
74
|
|
|
73
75
|
// set dev server options, like webpack-dev-server
|
|
74
76
|
this.dev =
|
|
75
|
-
typeof options.dev === 'boolean'
|
|
77
|
+
typeof options.dev === 'boolean'
|
|
78
|
+
? DEFAULT_DEV_OPTIONS
|
|
79
|
+
: { ...DEFAULT_DEV_OPTIONS, ...options.dev };
|
|
76
80
|
|
|
77
81
|
enableRegister(this.pwd, this.conf);
|
|
78
82
|
}
|
|
@@ -120,7 +124,9 @@ export class ModernDevServer extends ModernServer {
|
|
|
120
124
|
await super.init(runner);
|
|
121
125
|
|
|
122
126
|
// watch mock/ server/ api/ dir file change
|
|
123
|
-
this.
|
|
127
|
+
if (this.dev.watch) {
|
|
128
|
+
this.startWatcher();
|
|
129
|
+
}
|
|
124
130
|
}
|
|
125
131
|
|
|
126
132
|
public ready(options: ReadyOptions = {}) {
|
package/src/server/index.ts
CHANGED
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
ModernWebServer,
|
|
19
19
|
} from './modern-server-split';
|
|
20
20
|
import { ModernServerOptions, ServerHookRunner, ReadyOptions } from '@/type';
|
|
21
|
-
import {
|
|
21
|
+
import { metrics as defaultMetrics } from '@/libs/metrics';
|
|
22
22
|
|
|
23
23
|
export class Server {
|
|
24
24
|
public options: ModernServerOptions;
|
|
@@ -48,7 +48,7 @@ export class Server {
|
|
|
48
48
|
const { options } = this;
|
|
49
49
|
|
|
50
50
|
options.logger = options.logger || defaultLogger;
|
|
51
|
-
options.
|
|
51
|
+
options.metrics = options.metrics || defaultMetrics;
|
|
52
52
|
|
|
53
53
|
// initialize server
|
|
54
54
|
if (options.dev) {
|
|
@@ -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
|
});
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
ModernServerOptions,
|
|
13
13
|
NextFunction,
|
|
14
14
|
ServerHookRunner,
|
|
15
|
-
|
|
15
|
+
Metrics,
|
|
16
16
|
Logger,
|
|
17
17
|
ReadyOptions,
|
|
18
18
|
ConfWithBFF,
|
|
@@ -73,7 +73,7 @@ export class ModernServer {
|
|
|
73
73
|
|
|
74
74
|
protected readonly logger: Logger;
|
|
75
75
|
|
|
76
|
-
protected readonly
|
|
76
|
+
protected readonly metrics: Metrics;
|
|
77
77
|
|
|
78
78
|
protected readonly proxyTarget: ModernServerOptions['proxyTarget'];
|
|
79
79
|
|
|
@@ -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,
|
|
@@ -100,18 +100,18 @@ export class ModernServer {
|
|
|
100
100
|
routes,
|
|
101
101
|
staticGenerate,
|
|
102
102
|
logger,
|
|
103
|
-
|
|
103
|
+
metrics,
|
|
104
104
|
proxyTarget,
|
|
105
105
|
}: ModernServerOptions) {
|
|
106
106
|
require('ignore-styles');
|
|
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!;
|
|
114
|
-
this.
|
|
114
|
+
this.metrics = metrics!;
|
|
115
115
|
this.router = new RouteMatchManager();
|
|
116
116
|
this.presetRoutes = routes;
|
|
117
117
|
this.proxyTarget = proxyTarget;
|
|
@@ -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(
|
|
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.
|
|
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
|
-
|
|
550
|
-
|
|
551
|
-
|
|
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(
|
|
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
|
@@ -2,9 +2,16 @@ 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 {
|
|
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: {
|
|
@@ -26,6 +33,8 @@ export type DevServerOptions = {
|
|
|
26
33
|
dev: {
|
|
27
34
|
writeToDisk: boolean | ((filename: string) => boolean);
|
|
28
35
|
};
|
|
36
|
+
// 是否监听文件变化
|
|
37
|
+
watch: boolean;
|
|
29
38
|
// 是否开启 hot reload
|
|
30
39
|
hot: boolean | string;
|
|
31
40
|
// 是否开启 page reload
|
|
@@ -39,15 +48,15 @@ export type ModernServerOptions = {
|
|
|
39
48
|
pwd: string;
|
|
40
49
|
config: NormalizedConfig;
|
|
41
50
|
plugins?: any[];
|
|
42
|
-
dev?: boolean | DevServerOptions
|
|
51
|
+
dev?: boolean | Partial<DevServerOptions>;
|
|
43
52
|
compiler?: Webpack.MultiCompiler | Webpack.Compiler;
|
|
44
53
|
routes?: ModernRouteInterface[];
|
|
45
54
|
staticGenerate?: boolean;
|
|
46
55
|
customServer?: boolean;
|
|
47
56
|
loggerOptions?: Record<string, string>;
|
|
48
|
-
|
|
57
|
+
metricsOptions?: Record<string, string>;
|
|
49
58
|
logger?: Logger;
|
|
50
|
-
|
|
59
|
+
metrics?: Metrics;
|
|
51
60
|
apiOnly?: boolean;
|
|
52
61
|
ssrOnly?: boolean;
|
|
53
62
|
webOnly?: boolean;
|
|
@@ -76,4 +85,4 @@ export type ServerHookRunner = Then<ReturnType<typeof serverManager.init>>;
|
|
|
76
85
|
|
|
77
86
|
export type ReadyOptions = { routes?: ModernRouteInterface[] };
|
|
78
87
|
|
|
79
|
-
export type {
|
|
88
|
+
export type { Metrics, Logger, NextFunction };
|
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
|
+
}
|