@modern-js/prod-server 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/LICENSE +21 -0
- package/README.md +30 -0
- package/dist/js/modern/constants.js +26 -0
- package/dist/js/modern/index.js +14 -0
- package/dist/js/modern/libs/context/context.js +180 -0
- package/dist/js/modern/libs/context/index.js +3 -0
- package/dist/js/modern/libs/hook-api/route.js +39 -0
- package/dist/js/modern/libs/hook-api/template.js +61 -0
- package/dist/js/modern/libs/metrics.js +12 -0
- package/dist/js/modern/libs/proxy.js +33 -0
- package/dist/js/modern/libs/render/cache/__tests__/cache.fun.test.js +70 -0
- package/dist/js/modern/libs/render/cache/__tests__/cache.test.js +233 -0
- package/dist/js/modern/libs/render/cache/__tests__/cacheable.js +53 -0
- package/dist/js/modern/libs/render/cache/__tests__/error-configuration.js +35 -0
- package/dist/js/modern/libs/render/cache/__tests__/matched-cache.js +121 -0
- package/dist/js/modern/libs/render/cache/index.js +74 -0
- package/dist/js/modern/libs/render/cache/page-caches/index.js +9 -0
- package/dist/js/modern/libs/render/cache/page-caches/lru.js +35 -0
- package/dist/js/modern/libs/render/cache/spr.js +280 -0
- package/dist/js/modern/libs/render/cache/type.js +1 -0
- package/dist/js/modern/libs/render/cache/util.js +79 -0
- package/dist/js/modern/libs/render/index.js +65 -0
- package/dist/js/modern/libs/render/modern/browser-list.js +7 -0
- package/dist/js/modern/libs/render/modern/index.js +42 -0
- package/dist/js/modern/libs/render/reader.js +112 -0
- package/dist/js/modern/libs/render/ssr.js +58 -0
- package/dist/js/modern/libs/render/static.js +46 -0
- package/dist/js/modern/libs/render/type.js +7 -0
- package/dist/js/modern/libs/route/index.js +68 -0
- package/dist/js/modern/libs/route/matcher.js +94 -0
- package/dist/js/modern/libs/route/route.js +24 -0
- package/dist/js/modern/libs/serve-file.js +28 -0
- package/dist/js/modern/server/index.js +120 -0
- package/dist/js/modern/server/modern-server-split.js +81 -0
- package/dist/js/modern/server/modern-server.js +576 -0
- package/dist/js/modern/type.js +1 -0
- package/dist/js/modern/utils.js +112 -0
- package/dist/js/node/constants.js +36 -0
- package/dist/js/node/index.js +74 -0
- package/dist/js/node/libs/context/context.js +194 -0
- package/dist/js/node/libs/context/index.js +18 -0
- package/dist/js/node/libs/hook-api/route.js +48 -0
- package/dist/js/node/libs/hook-api/template.js +69 -0
- package/dist/js/node/libs/metrics.js +18 -0
- package/dist/js/node/libs/proxy.js +44 -0
- package/dist/js/node/libs/render/cache/__tests__/cache.fun.test.js +77 -0
- package/dist/js/node/libs/render/cache/__tests__/cache.test.js +238 -0
- package/dist/js/node/libs/render/cache/__tests__/cacheable.js +60 -0
- package/dist/js/node/libs/render/cache/__tests__/error-configuration.js +42 -0
- package/dist/js/node/libs/render/cache/__tests__/matched-cache.js +128 -0
- package/dist/js/node/libs/render/cache/index.js +86 -0
- package/dist/js/node/libs/render/cache/page-caches/index.js +17 -0
- package/dist/js/node/libs/render/cache/page-caches/lru.js +47 -0
- package/dist/js/node/libs/render/cache/spr.js +298 -0
- package/dist/js/node/libs/render/cache/type.js +5 -0
- package/dist/js/node/libs/render/cache/util.js +105 -0
- package/dist/js/node/libs/render/index.js +91 -0
- package/dist/js/node/libs/render/modern/browser-list.js +14 -0
- package/dist/js/node/libs/render/modern/index.js +58 -0
- package/dist/js/node/libs/render/reader.js +139 -0
- package/dist/js/node/libs/render/ssr.js +76 -0
- package/dist/js/node/libs/render/static.js +62 -0
- package/dist/js/node/libs/render/type.js +14 -0
- package/dist/js/node/libs/route/index.js +83 -0
- package/dist/js/node/libs/route/matcher.js +108 -0
- package/dist/js/node/libs/route/route.js +33 -0
- package/dist/js/node/libs/serve-file.js +41 -0
- package/dist/js/node/server/index.js +142 -0
- package/dist/js/node/server/modern-server-split.js +97 -0
- package/dist/js/node/server/modern-server.js +614 -0
- package/dist/js/node/type.js +5 -0
- package/dist/js/node/utils.js +143 -0
- package/dist/js/styles/tsconfig.json +12 -0
- package/dist/types/constants.d.ts +20 -0
- package/dist/types/index.d.ts +11 -0
- package/dist/types/libs/context/context.d.ts +61 -0
- package/dist/types/libs/context/index.d.ts +4 -0
- package/dist/types/libs/hook-api/route.d.ts +14 -0
- package/dist/types/libs/hook-api/template.d.ts +14 -0
- package/dist/types/libs/metrics.d.ts +3 -0
- package/dist/types/libs/proxy.d.ts +4 -0
- package/dist/types/libs/render/cache/__tests__/cache.fun.test.d.ts +1 -0
- package/dist/types/libs/render/cache/__tests__/cache.test.d.ts +1 -0
- package/dist/types/libs/render/cache/__tests__/cacheable.d.ts +62 -0
- package/dist/types/libs/render/cache/__tests__/error-configuration.d.ts +28 -0
- package/dist/types/libs/render/cache/__tests__/matched-cache.d.ts +124 -0
- package/dist/types/libs/render/cache/index.d.ts +6 -0
- package/dist/types/libs/render/cache/page-caches/index.d.ts +2 -0
- package/dist/types/libs/render/cache/page-caches/lru.d.ts +15 -0
- package/dist/types/libs/render/cache/spr.d.ts +24 -0
- package/dist/types/libs/render/cache/type.d.ts +48 -0
- package/dist/types/libs/render/cache/util.d.ts +17 -0
- package/dist/types/libs/render/index.d.ts +18 -0
- package/dist/types/libs/render/modern/browser-list.d.ts +1 -0
- package/dist/types/libs/render/modern/index.d.ts +3 -0
- package/dist/types/libs/render/reader.d.ts +18 -0
- package/dist/types/libs/render/ssr.d.ts +10 -0
- package/dist/types/libs/render/static.d.ts +3 -0
- package/dist/types/libs/render/type.d.ts +33 -0
- package/dist/types/libs/route/index.d.ts +15 -0
- package/dist/types/libs/route/matcher.d.ts +15 -0
- package/dist/types/libs/route/route.d.ts +14 -0
- package/dist/types/libs/serve-file.d.ts +8 -0
- package/dist/types/server/index.d.ts +20 -0
- package/dist/types/server/modern-server-split.d.ts +26 -0
- package/dist/types/server/modern-server.d.ts +72 -0
- package/dist/types/type.d.ts +56 -0
- package/dist/types/utils.d.ts +19 -0
- package/jest.config.js +9 -0
- package/modern.config.js +2 -0
- package/package.json +82 -0
- package/src/constants.ts +26 -0
- package/src/index.ts +18 -0
- package/src/libs/context/context.ts +183 -0
- package/src/libs/context/index.ts +7 -0
- package/src/libs/hook-api/route.ts +42 -0
- package/src/libs/hook-api/template.ts +53 -0
- package/src/libs/metrics.ts +15 -0
- package/src/libs/proxy.ts +42 -0
- package/src/libs/render/cache/__tests__/cache.fun.test.ts +94 -0
- package/src/libs/render/cache/__tests__/cache.test.ts +240 -0
- package/src/libs/render/cache/__tests__/cacheable.ts +44 -0
- package/src/libs/render/cache/__tests__/error-configuration.ts +34 -0
- package/src/libs/render/cache/__tests__/matched-cache.ts +88 -0
- package/src/libs/render/cache/index.ts +75 -0
- package/src/libs/render/cache/page-caches/index.ts +11 -0
- package/src/libs/render/cache/page-caches/lru.ts +38 -0
- package/src/libs/render/cache/spr.ts +301 -0
- package/src/libs/render/cache/type.ts +59 -0
- package/src/libs/render/cache/util.ts +97 -0
- package/src/libs/render/index.ts +79 -0
- package/src/libs/render/modern/browser-list.ts +7 -0
- package/src/libs/render/modern/index.ts +41 -0
- package/src/libs/render/modern/module.d.ts +4 -0
- package/src/libs/render/reader.ts +119 -0
- package/src/libs/render/ssr.ts +67 -0
- package/src/libs/render/static.ts +52 -0
- package/src/libs/render/type.ts +38 -0
- package/src/libs/route/index.ts +76 -0
- package/src/libs/route/matcher.ts +108 -0
- package/src/libs/route/route.ts +34 -0
- package/src/libs/serve-file.ts +34 -0
- package/src/server/index.ts +147 -0
- package/src/server/modern-server-split.ts +97 -0
- package/src/server/modern-server.ts +613 -0
- package/src/tsconfig.json +12 -0
- package/src/type.ts +61 -0
- package/src/utils.ts +122 -0
- package/tests/.eslintrc.js +6 -0
- package/tests/context.test.ts +52 -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 +12 -0
- package/tests/fixtures/reader/index.ts +3 -0
- package/tests/fixtures/route-spec/dynamic.json +13 -0
- package/tests/fixtures/route-spec/index.json +29 -0
- package/tests/fixtures/ssr/bundle.js +5 -0
- package/tests/fixtures/static-dir/bar.html +11 -0
- package/tests/fixtures/static-dir/baz/index.html +11 -0
- package/tests/fixtures/static-dir/foo/index.html +11 -0
- package/tests/helper.ts +8 -0
- package/tests/hook.test.ts +44 -0
- package/tests/middleware.test.ts +179 -0
- package/tests/render.test.ts +102 -0
- package/tests/route.test.ts +77 -0
- package/tests/server.test.ts +101 -0
- package/tests/tsconfig.json +12 -0
- package/tests/utils.test.ts +106 -0
- package/tsconfig.json +11 -0
package/src/type.ts
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { Buffer } from 'buffer';
|
|
2
|
+
import { serverManager } from '@modern-js/server-core';
|
|
3
|
+
import type { NormalizedConfig } from '@modern-js/core';
|
|
4
|
+
import type { Metrics, Logger, NextFunction } from '@modern-js/types/server';
|
|
5
|
+
import { ModernRouteInterface } from './libs/route';
|
|
6
|
+
|
|
7
|
+
declare module 'http' {
|
|
8
|
+
interface IncomingMessage {
|
|
9
|
+
logger: Logger;
|
|
10
|
+
metrics: Metrics;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
declare module '@modern-js/core' {
|
|
15
|
+
interface UserConfig {
|
|
16
|
+
bff?: {
|
|
17
|
+
proxy: Record<string, any>;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export type ModernServerOptions = {
|
|
23
|
+
pwd: string;
|
|
24
|
+
config: NormalizedConfig;
|
|
25
|
+
plugins?: { pluginPath: string }[];
|
|
26
|
+
routes?: ModernRouteInterface[];
|
|
27
|
+
staticGenerate?: boolean;
|
|
28
|
+
loggerOptions?: Record<string, string>;
|
|
29
|
+
metricsOptions?: Record<string, string>;
|
|
30
|
+
logger?: Logger;
|
|
31
|
+
metrics?: Metrics;
|
|
32
|
+
apiOnly?: boolean;
|
|
33
|
+
ssrOnly?: boolean;
|
|
34
|
+
webOnly?: boolean;
|
|
35
|
+
proxyTarget?: {
|
|
36
|
+
ssr?: string;
|
|
37
|
+
api?: string;
|
|
38
|
+
};
|
|
39
|
+
[propName: string]: any;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export type RenderResult = {
|
|
43
|
+
content: string | Buffer;
|
|
44
|
+
contentType: string;
|
|
45
|
+
statusCode?: number;
|
|
46
|
+
redirect?: boolean;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export type ConfWithBFF = {
|
|
50
|
+
bff?: {
|
|
51
|
+
prefix: string;
|
|
52
|
+
};
|
|
53
|
+
} & NormalizedConfig;
|
|
54
|
+
|
|
55
|
+
export type Then<T> = T extends PromiseLike<infer U> ? U : T;
|
|
56
|
+
|
|
57
|
+
export type ServerHookRunner = Then<ReturnType<typeof serverManager.init>>;
|
|
58
|
+
|
|
59
|
+
export type ReadyOptions = { routes?: ModernRouteInterface[] };
|
|
60
|
+
|
|
61
|
+
export type { Metrics, Logger, NextFunction };
|
package/src/utils.ts
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import type { NormalizedConfig } from '@modern-js/core';
|
|
2
|
+
import { compile } from 'path-to-regexp';
|
|
3
|
+
|
|
4
|
+
export const mergeExtension = (users: any[]) => {
|
|
5
|
+
const output: any[] = [];
|
|
6
|
+
return { middleware: output.concat(users) };
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export const toMessage = (dig: string, e: Error | string): string => {
|
|
10
|
+
const message = e instanceof Error ? e.message : e;
|
|
11
|
+
if (message) {
|
|
12
|
+
return `${dig}: ${message}`;
|
|
13
|
+
} else {
|
|
14
|
+
return dig;
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export const noop = () => {
|
|
19
|
+
// noop
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export const createErrorDocument = (status: number, text: string) => {
|
|
23
|
+
const title = `${status}: ${text}`;
|
|
24
|
+
return `<!DOCTYPE html>
|
|
25
|
+
<html lang="en">
|
|
26
|
+
<head>
|
|
27
|
+
<meta charset="utf-8">
|
|
28
|
+
<meta name="viewport" content="width=device-width">
|
|
29
|
+
<title>${title}</title>
|
|
30
|
+
<style>
|
|
31
|
+
html,body {
|
|
32
|
+
margin: 0;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.page-container {
|
|
36
|
+
color: #000;
|
|
37
|
+
background: #fff;
|
|
38
|
+
height: 100vh;
|
|
39
|
+
text-align: center;
|
|
40
|
+
display: flex;
|
|
41
|
+
flex-direction: column;
|
|
42
|
+
align-items: center;
|
|
43
|
+
justify-content: center;
|
|
44
|
+
}
|
|
45
|
+
</style>
|
|
46
|
+
</head>
|
|
47
|
+
<body>
|
|
48
|
+
<div class="page-container">
|
|
49
|
+
<h1>${status}</h1>
|
|
50
|
+
<div>${text}</div>
|
|
51
|
+
</body>
|
|
52
|
+
</html>
|
|
53
|
+
`;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export type CollectMiddlewaresResult = {
|
|
57
|
+
web: any[];
|
|
58
|
+
api: any[];
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export const createMiddlewareCollecter = () => {
|
|
62
|
+
const webMiddlewares: any[] = [];
|
|
63
|
+
const apiMiddlewares: any[] = [];
|
|
64
|
+
|
|
65
|
+
const addWebMiddleware = (input: any) => {
|
|
66
|
+
webMiddlewares.push(input);
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const addAPIMiddleware = (input: any) => {
|
|
70
|
+
apiMiddlewares.push(input);
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const getMiddlewares = (): CollectMiddlewaresResult => ({
|
|
74
|
+
web: webMiddlewares,
|
|
75
|
+
api: apiMiddlewares,
|
|
76
|
+
});
|
|
77
|
+
return {
|
|
78
|
+
getMiddlewares,
|
|
79
|
+
addWebMiddleware,
|
|
80
|
+
addAPIMiddleware,
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export const toPath = (reg: string, params: Record<string, any>) => {
|
|
85
|
+
const fn = compile(reg, { encode: encodeURIComponent });
|
|
86
|
+
return fn(params);
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
export const getStaticReg = (output: NormalizedConfig['output'] = {}) => {
|
|
90
|
+
const { favicon, faviconByEntries, cssPath, jsPath, mediaPath } = output;
|
|
91
|
+
const favicons = prepareFavicons(favicon, faviconByEntries);
|
|
92
|
+
const staticFiles = [cssPath, jsPath, mediaPath].filter(v => Boolean(v));
|
|
93
|
+
|
|
94
|
+
const staticPathRegExp = new RegExp(
|
|
95
|
+
`^/(static/|upload/|favicon.ico|icon.png${
|
|
96
|
+
favicons.length > 0 ? `|${favicons.join('|')}` : ''
|
|
97
|
+
}|${staticFiles.join('|')})`,
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
return staticPathRegExp;
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
export const prepareFavicons = (
|
|
104
|
+
favicon: string | undefined,
|
|
105
|
+
faviconByEntries?: Record<string, string | undefined>,
|
|
106
|
+
) => {
|
|
107
|
+
const faviconNames = [];
|
|
108
|
+
if (favicon) {
|
|
109
|
+
faviconNames.push(favicon.substring(favicon.lastIndexOf('/') + 1));
|
|
110
|
+
}
|
|
111
|
+
if (faviconByEntries) {
|
|
112
|
+
Object.keys(faviconByEntries).forEach(f => {
|
|
113
|
+
const curFavicon = faviconByEntries[f];
|
|
114
|
+
if (curFavicon) {
|
|
115
|
+
faviconNames.push(
|
|
116
|
+
curFavicon.substring(curFavicon.lastIndexOf('/') + 1),
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
return faviconNames;
|
|
122
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
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 context = createContext(req, res);
|
|
18
|
+
const {
|
|
19
|
+
method,
|
|
20
|
+
url,
|
|
21
|
+
origin,
|
|
22
|
+
host,
|
|
23
|
+
path,
|
|
24
|
+
href,
|
|
25
|
+
query,
|
|
26
|
+
querystring,
|
|
27
|
+
protocol,
|
|
28
|
+
params,
|
|
29
|
+
} = context;
|
|
30
|
+
|
|
31
|
+
expect(method).toBe('GET');
|
|
32
|
+
expect(url).toBe('/pathname?foo=baz');
|
|
33
|
+
expect(origin).toBe('http://modernjs.com');
|
|
34
|
+
expect(host).toBe('modernjs.com');
|
|
35
|
+
expect(path).toBe('/pathname');
|
|
36
|
+
expect(href).toBe('http://modernjs.com/pathname?foo=baz');
|
|
37
|
+
expect(query).toEqual({ foo: 'baz' });
|
|
38
|
+
expect(querystring).toBe('foo=baz');
|
|
39
|
+
expect(protocol).toBe('http');
|
|
40
|
+
expect(params).toEqual({});
|
|
41
|
+
|
|
42
|
+
expect(context.serverData).toEqual({});
|
|
43
|
+
context.setServerData('foo', {
|
|
44
|
+
name: 'foo',
|
|
45
|
+
});
|
|
46
|
+
expect(context.serverData).toEqual({
|
|
47
|
+
foo: {
|
|
48
|
+
name: 'foo',
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
});
|
|
@@ -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
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import './App.css';
|
|
2
|
+
|
|
3
|
+
const App = () => (
|
|
4
|
+
<div className="container">
|
|
5
|
+
<main>
|
|
6
|
+
<div className="logo">
|
|
7
|
+
<img
|
|
8
|
+
src="https://lf3-static.bytednsdoc.com/obj/eden-cn/ylaelkeh7nuhfnuhf/modernjs-cover.png"
|
|
9
|
+
width="300"
|
|
10
|
+
alt="Modern.js Logo"
|
|
11
|
+
/>
|
|
12
|
+
</div>
|
|
13
|
+
<p className="description">
|
|
14
|
+
Get started by editing <code className="code">src/home/App.tsx</code>
|
|
15
|
+
</p>
|
|
16
|
+
<div className="grid">
|
|
17
|
+
<a href="https://modernjs.dev/docs/start" className="card">
|
|
18
|
+
<h2>Quick Start Tencent</h2>
|
|
19
|
+
</a>
|
|
20
|
+
<a href="https://modernjs.dev/docs/guides" className="card">
|
|
21
|
+
<h2>Handbook</h2>
|
|
22
|
+
</a>
|
|
23
|
+
<a href="https://modernjs.dev/docs/apis" className="card">
|
|
24
|
+
<h2>API Reference </h2>
|
|
25
|
+
</a>
|
|
26
|
+
<a
|
|
27
|
+
href="https://modernjs.dev/coming-soon"
|
|
28
|
+
target="_blank"
|
|
29
|
+
rel="noopener noreferrer"
|
|
30
|
+
className="card">
|
|
31
|
+
<h2>Community </h2>
|
|
32
|
+
</a>
|
|
33
|
+
</div>
|
|
34
|
+
</main>
|
|
35
|
+
<footer className="footer">
|
|
36
|
+
<a href="https://modernjs.dev" target="_blank" rel="noopener noreferrer">
|
|
37
|
+
Powered by Modern.js
|
|
38
|
+
</a>
|
|
39
|
+
</footer>
|
|
40
|
+
</div>
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
export default App;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"routes": [
|
|
3
|
+
{
|
|
4
|
+
"urlPath": "/entry",
|
|
5
|
+
"entryName": "entry",
|
|
6
|
+
"entryPath": "html/entry/index.html",
|
|
7
|
+
"isSPA": true,
|
|
8
|
+
"isSSR": true,
|
|
9
|
+
"enableModernMode": false,
|
|
10
|
+
"bundle": "bundles/entry.js"
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"urlPath": "/home",
|
|
14
|
+
"entryName": "home",
|
|
15
|
+
"entryPath": "html/home/index.html",
|
|
16
|
+
"isSPA": true,
|
|
17
|
+
"isSSR": true,
|
|
18
|
+
"enableModernMode": false,
|
|
19
|
+
"bundle": "bundles/home.js"
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"urlPath": "/api",
|
|
23
|
+
"isApi": true,
|
|
24
|
+
"entryPath": "",
|
|
25
|
+
"isSPA": false,
|
|
26
|
+
"isSSR": false
|
|
27
|
+
}
|
|
28
|
+
]
|
|
29
|
+
}
|
package/tests/helper.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { createRouteAPI } from '../src/libs/hook-api/route';
|
|
2
|
+
import { createTemplateAPI } from '../src/libs/hook-api/template';
|
|
3
|
+
import { RouteMatchManager } from '../src/libs/route';
|
|
4
|
+
import { createDoc } from './helper';
|
|
5
|
+
import spec from './fixtures/route-spec/index.json';
|
|
6
|
+
|
|
7
|
+
describe('test hook api', () => {
|
|
8
|
+
test('should route api work correctly', () => {
|
|
9
|
+
const manager = new RouteMatchManager();
|
|
10
|
+
manager.reset(spec.routes);
|
|
11
|
+
const matcher = manager.match('/home');
|
|
12
|
+
|
|
13
|
+
const routeAPI = createRouteAPI(matcher!, manager, '');
|
|
14
|
+
expect(routeAPI.cur().entryName).toBe('home');
|
|
15
|
+
expect(routeAPI.get('entry')?.entryPath).toBe('html/entry/index.html');
|
|
16
|
+
|
|
17
|
+
expect(routeAPI.use('home')).toBeTruthy();
|
|
18
|
+
expect(routeAPI.cur().entryName).toBe('home');
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test('should template api work correctly', () => {
|
|
22
|
+
const content = createDoc();
|
|
23
|
+
const templateAPI = createTemplateAPI(content);
|
|
24
|
+
|
|
25
|
+
expect(templateAPI.get()).toMatch(content);
|
|
26
|
+
|
|
27
|
+
templateAPI.replace('mock', 'replace');
|
|
28
|
+
expect(templateAPI.get()).toMatch('replace');
|
|
29
|
+
|
|
30
|
+
templateAPI.appendBody('after body');
|
|
31
|
+
templateAPI.prependBody('before body');
|
|
32
|
+
templateAPI.appendHead('after head');
|
|
33
|
+
templateAPI.prependHead('before head');
|
|
34
|
+
|
|
35
|
+
const newContent = templateAPI.get();
|
|
36
|
+
expect(newContent).toMatch('<head>before head');
|
|
37
|
+
expect(newContent).toMatch('<body>before body');
|
|
38
|
+
expect(newContent).toMatch('after head</head>');
|
|
39
|
+
expect(newContent).toMatch('after body</body>');
|
|
40
|
+
|
|
41
|
+
templateAPI.set('<div>empty</div>');
|
|
42
|
+
expect(templateAPI.get()).toBe('<div>empty</div>');
|
|
43
|
+
});
|
|
44
|
+
});
|