@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.
Files changed (173) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/LICENSE +21 -0
  3. package/README.md +30 -0
  4. package/dist/js/modern/constants.js +26 -0
  5. package/dist/js/modern/index.js +14 -0
  6. package/dist/js/modern/libs/context/context.js +180 -0
  7. package/dist/js/modern/libs/context/index.js +3 -0
  8. package/dist/js/modern/libs/hook-api/route.js +39 -0
  9. package/dist/js/modern/libs/hook-api/template.js +61 -0
  10. package/dist/js/modern/libs/metrics.js +12 -0
  11. package/dist/js/modern/libs/proxy.js +33 -0
  12. package/dist/js/modern/libs/render/cache/__tests__/cache.fun.test.js +70 -0
  13. package/dist/js/modern/libs/render/cache/__tests__/cache.test.js +233 -0
  14. package/dist/js/modern/libs/render/cache/__tests__/cacheable.js +53 -0
  15. package/dist/js/modern/libs/render/cache/__tests__/error-configuration.js +35 -0
  16. package/dist/js/modern/libs/render/cache/__tests__/matched-cache.js +121 -0
  17. package/dist/js/modern/libs/render/cache/index.js +74 -0
  18. package/dist/js/modern/libs/render/cache/page-caches/index.js +9 -0
  19. package/dist/js/modern/libs/render/cache/page-caches/lru.js +35 -0
  20. package/dist/js/modern/libs/render/cache/spr.js +280 -0
  21. package/dist/js/modern/libs/render/cache/type.js +1 -0
  22. package/dist/js/modern/libs/render/cache/util.js +79 -0
  23. package/dist/js/modern/libs/render/index.js +65 -0
  24. package/dist/js/modern/libs/render/modern/browser-list.js +7 -0
  25. package/dist/js/modern/libs/render/modern/index.js +42 -0
  26. package/dist/js/modern/libs/render/reader.js +112 -0
  27. package/dist/js/modern/libs/render/ssr.js +58 -0
  28. package/dist/js/modern/libs/render/static.js +46 -0
  29. package/dist/js/modern/libs/render/type.js +7 -0
  30. package/dist/js/modern/libs/route/index.js +68 -0
  31. package/dist/js/modern/libs/route/matcher.js +94 -0
  32. package/dist/js/modern/libs/route/route.js +24 -0
  33. package/dist/js/modern/libs/serve-file.js +28 -0
  34. package/dist/js/modern/server/index.js +120 -0
  35. package/dist/js/modern/server/modern-server-split.js +81 -0
  36. package/dist/js/modern/server/modern-server.js +576 -0
  37. package/dist/js/modern/type.js +1 -0
  38. package/dist/js/modern/utils.js +112 -0
  39. package/dist/js/node/constants.js +36 -0
  40. package/dist/js/node/index.js +74 -0
  41. package/dist/js/node/libs/context/context.js +194 -0
  42. package/dist/js/node/libs/context/index.js +18 -0
  43. package/dist/js/node/libs/hook-api/route.js +48 -0
  44. package/dist/js/node/libs/hook-api/template.js +69 -0
  45. package/dist/js/node/libs/metrics.js +18 -0
  46. package/dist/js/node/libs/proxy.js +44 -0
  47. package/dist/js/node/libs/render/cache/__tests__/cache.fun.test.js +77 -0
  48. package/dist/js/node/libs/render/cache/__tests__/cache.test.js +238 -0
  49. package/dist/js/node/libs/render/cache/__tests__/cacheable.js +60 -0
  50. package/dist/js/node/libs/render/cache/__tests__/error-configuration.js +42 -0
  51. package/dist/js/node/libs/render/cache/__tests__/matched-cache.js +128 -0
  52. package/dist/js/node/libs/render/cache/index.js +86 -0
  53. package/dist/js/node/libs/render/cache/page-caches/index.js +17 -0
  54. package/dist/js/node/libs/render/cache/page-caches/lru.js +47 -0
  55. package/dist/js/node/libs/render/cache/spr.js +298 -0
  56. package/dist/js/node/libs/render/cache/type.js +5 -0
  57. package/dist/js/node/libs/render/cache/util.js +105 -0
  58. package/dist/js/node/libs/render/index.js +91 -0
  59. package/dist/js/node/libs/render/modern/browser-list.js +14 -0
  60. package/dist/js/node/libs/render/modern/index.js +58 -0
  61. package/dist/js/node/libs/render/reader.js +139 -0
  62. package/dist/js/node/libs/render/ssr.js +76 -0
  63. package/dist/js/node/libs/render/static.js +62 -0
  64. package/dist/js/node/libs/render/type.js +14 -0
  65. package/dist/js/node/libs/route/index.js +83 -0
  66. package/dist/js/node/libs/route/matcher.js +108 -0
  67. package/dist/js/node/libs/route/route.js +33 -0
  68. package/dist/js/node/libs/serve-file.js +41 -0
  69. package/dist/js/node/server/index.js +142 -0
  70. package/dist/js/node/server/modern-server-split.js +97 -0
  71. package/dist/js/node/server/modern-server.js +614 -0
  72. package/dist/js/node/type.js +5 -0
  73. package/dist/js/node/utils.js +143 -0
  74. package/dist/js/styles/tsconfig.json +12 -0
  75. package/dist/types/constants.d.ts +20 -0
  76. package/dist/types/index.d.ts +11 -0
  77. package/dist/types/libs/context/context.d.ts +61 -0
  78. package/dist/types/libs/context/index.d.ts +4 -0
  79. package/dist/types/libs/hook-api/route.d.ts +14 -0
  80. package/dist/types/libs/hook-api/template.d.ts +14 -0
  81. package/dist/types/libs/metrics.d.ts +3 -0
  82. package/dist/types/libs/proxy.d.ts +4 -0
  83. package/dist/types/libs/render/cache/__tests__/cache.fun.test.d.ts +1 -0
  84. package/dist/types/libs/render/cache/__tests__/cache.test.d.ts +1 -0
  85. package/dist/types/libs/render/cache/__tests__/cacheable.d.ts +62 -0
  86. package/dist/types/libs/render/cache/__tests__/error-configuration.d.ts +28 -0
  87. package/dist/types/libs/render/cache/__tests__/matched-cache.d.ts +124 -0
  88. package/dist/types/libs/render/cache/index.d.ts +6 -0
  89. package/dist/types/libs/render/cache/page-caches/index.d.ts +2 -0
  90. package/dist/types/libs/render/cache/page-caches/lru.d.ts +15 -0
  91. package/dist/types/libs/render/cache/spr.d.ts +24 -0
  92. package/dist/types/libs/render/cache/type.d.ts +48 -0
  93. package/dist/types/libs/render/cache/util.d.ts +17 -0
  94. package/dist/types/libs/render/index.d.ts +18 -0
  95. package/dist/types/libs/render/modern/browser-list.d.ts +1 -0
  96. package/dist/types/libs/render/modern/index.d.ts +3 -0
  97. package/dist/types/libs/render/reader.d.ts +18 -0
  98. package/dist/types/libs/render/ssr.d.ts +10 -0
  99. package/dist/types/libs/render/static.d.ts +3 -0
  100. package/dist/types/libs/render/type.d.ts +33 -0
  101. package/dist/types/libs/route/index.d.ts +15 -0
  102. package/dist/types/libs/route/matcher.d.ts +15 -0
  103. package/dist/types/libs/route/route.d.ts +14 -0
  104. package/dist/types/libs/serve-file.d.ts +8 -0
  105. package/dist/types/server/index.d.ts +20 -0
  106. package/dist/types/server/modern-server-split.d.ts +26 -0
  107. package/dist/types/server/modern-server.d.ts +72 -0
  108. package/dist/types/type.d.ts +56 -0
  109. package/dist/types/utils.d.ts +19 -0
  110. package/jest.config.js +9 -0
  111. package/modern.config.js +2 -0
  112. package/package.json +82 -0
  113. package/src/constants.ts +26 -0
  114. package/src/index.ts +18 -0
  115. package/src/libs/context/context.ts +183 -0
  116. package/src/libs/context/index.ts +7 -0
  117. package/src/libs/hook-api/route.ts +42 -0
  118. package/src/libs/hook-api/template.ts +53 -0
  119. package/src/libs/metrics.ts +15 -0
  120. package/src/libs/proxy.ts +42 -0
  121. package/src/libs/render/cache/__tests__/cache.fun.test.ts +94 -0
  122. package/src/libs/render/cache/__tests__/cache.test.ts +240 -0
  123. package/src/libs/render/cache/__tests__/cacheable.ts +44 -0
  124. package/src/libs/render/cache/__tests__/error-configuration.ts +34 -0
  125. package/src/libs/render/cache/__tests__/matched-cache.ts +88 -0
  126. package/src/libs/render/cache/index.ts +75 -0
  127. package/src/libs/render/cache/page-caches/index.ts +11 -0
  128. package/src/libs/render/cache/page-caches/lru.ts +38 -0
  129. package/src/libs/render/cache/spr.ts +301 -0
  130. package/src/libs/render/cache/type.ts +59 -0
  131. package/src/libs/render/cache/util.ts +97 -0
  132. package/src/libs/render/index.ts +79 -0
  133. package/src/libs/render/modern/browser-list.ts +7 -0
  134. package/src/libs/render/modern/index.ts +41 -0
  135. package/src/libs/render/modern/module.d.ts +4 -0
  136. package/src/libs/render/reader.ts +119 -0
  137. package/src/libs/render/ssr.ts +67 -0
  138. package/src/libs/render/static.ts +52 -0
  139. package/src/libs/render/type.ts +38 -0
  140. package/src/libs/route/index.ts +76 -0
  141. package/src/libs/route/matcher.ts +108 -0
  142. package/src/libs/route/route.ts +34 -0
  143. package/src/libs/serve-file.ts +34 -0
  144. package/src/server/index.ts +147 -0
  145. package/src/server/modern-server-split.ts +97 -0
  146. package/src/server/modern-server.ts +613 -0
  147. package/src/tsconfig.json +12 -0
  148. package/src/type.ts +61 -0
  149. package/src/utils.ts +122 -0
  150. package/tests/.eslintrc.js +6 -0
  151. package/tests/context.test.ts +52 -0
  152. package/tests/fixtures/hosting-files/static/index.js +1 -0
  153. package/tests/fixtures/pure/modern.config.js +5 -0
  154. package/tests/fixtures/pure/package.json +21 -0
  155. package/tests/fixtures/pure/src/App.css +119 -0
  156. package/tests/fixtures/pure/src/App.tsx +43 -0
  157. package/tests/fixtures/pure/tsconfig.json +12 -0
  158. package/tests/fixtures/reader/index.ts +3 -0
  159. package/tests/fixtures/route-spec/dynamic.json +13 -0
  160. package/tests/fixtures/route-spec/index.json +29 -0
  161. package/tests/fixtures/ssr/bundle.js +5 -0
  162. package/tests/fixtures/static-dir/bar.html +11 -0
  163. package/tests/fixtures/static-dir/baz/index.html +11 -0
  164. package/tests/fixtures/static-dir/foo/index.html +11 -0
  165. package/tests/helper.ts +8 -0
  166. package/tests/hook.test.ts +44 -0
  167. package/tests/middleware.test.ts +179 -0
  168. package/tests/render.test.ts +102 -0
  169. package/tests/route.test.ts +77 -0
  170. package/tests/server.test.ts +101 -0
  171. package/tests/tsconfig.json +12 -0
  172. package/tests/utils.test.ts +106 -0
  173. 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,6 @@
1
+ module.exports = {
2
+ extends: ['@modern-js'],
3
+ parserOptions: {
4
+ project: require.resolve('./tsconfig.json'),
5
+ },
6
+ };
@@ -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,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
+ }
@@ -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,12 @@
1
+ {
2
+ "extends": "@modern-js/tsconfig/base",
3
+ "compilerOptions": {
4
+ "declaration": false,
5
+ "jsx": "preserve",
6
+ "baseUrl": "./",
7
+ "paths": {
8
+ "@shared/*": ["./shared/*"]
9
+ }
10
+ },
11
+ "include": ["src", "shared", "config"]
12
+ }
@@ -0,0 +1,3 @@
1
+ export default {
2
+ name: 'modern',
3
+ };
@@ -0,0 +1,13 @@
1
+ {
2
+ "routes": [
3
+ {
4
+ "urlPath": "/entry/:id",
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
+ }
@@ -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
+ }
@@ -0,0 +1,5 @@
1
+ const { SERVER_RENDER_FUNCTION_NAME } = require('@modern-js/utils');
2
+
3
+ module.exports = {
4
+ [SERVER_RENDER_FUNCTION_NAME]: () => '<div>Modern.js</div>',
5
+ };
@@ -0,0 +1,11 @@
1
+ <html lang="en">
2
+ <head>
3
+ <meta charset="UTF-8">
4
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>bar</title>
7
+ </head>
8
+ <body>
9
+
10
+ </body>
11
+ </html>
@@ -0,0 +1,11 @@
1
+ <html lang="en">
2
+ <head>
3
+ <meta charset="UTF-8">
4
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>baz</title>
7
+ </head>
8
+ <body>
9
+
10
+ </body>
11
+ </html>
@@ -0,0 +1,11 @@
1
+ <html lang="en">
2
+ <head>
3
+ <meta charset="UTF-8">
4
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>foo</title>
7
+ </head>
8
+ <body>
9
+
10
+ </body>
11
+ </html>
@@ -0,0 +1,8 @@
1
+ export const createDoc = () => `<html>
2
+ <head>
3
+ <title>mock</title>
4
+ </head>
5
+ <body>
6
+ <div>hello</div>
7
+ </body>
8
+ </html>`;
@@ -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
+ });