@modern-js/plugin-ssg 1.0.0 → 1.1.2-rc.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/.eslintrc.js +6 -0
- package/CHANGELOG.md +42 -0
- package/README.md +1 -4
- package/dist/js/modern/index.js +97 -58
- package/dist/js/modern/libs/make.js +37 -0
- package/dist/js/modern/libs/output.js +2 -1
- package/dist/js/modern/libs/replace.js +5 -4
- package/dist/js/modern/libs/util.js +39 -22
- package/dist/js/modern/server/index.js +4 -3
- package/dist/js/modern/server/prerender.js +2 -2
- package/dist/js/modern/server/process.js +8 -7
- package/dist/js/node/index.js +97 -56
- package/dist/js/node/libs/make.js +50 -0
- package/dist/js/node/libs/output.js +7 -3
- package/dist/js/node/libs/replace.js +5 -4
- package/dist/js/node/libs/util.js +43 -30
- package/dist/js/node/server/index.js +5 -3
- package/dist/js/node/server/prerender.js +2 -2
- package/dist/js/node/server/process.js +7 -6
- package/dist/types/libs/make.d.ts +5 -0
- package/dist/types/libs/replace.d.ts +1 -1
- package/dist/types/libs/util.d.ts +4 -8
- package/dist/types/types.d.ts +13 -17
- package/package.json +10 -11
- package/src/index.ts +85 -89
- package/src/libs/make.ts +45 -0
- package/src/libs/output.ts +3 -2
- package/src/libs/replace.ts +7 -4
- package/src/libs/util.ts +40 -27
- package/src/server/index.ts +3 -2
- package/src/server/process.ts +7 -5
- package/src/types.ts +26 -20
- package/tests/.eslintrc.js +6 -0
- package/tests/lib.test.ts +49 -170
- package/tests/util.test.ts +71 -32
- package/dist/js/modern/libs/createPage.js +0 -46
- package/dist/js/modern/libs/invoker.js +0 -55
- package/dist/js/modern/libs/render.js +0 -15
- package/dist/js/modern/loader/index.js +0 -105
- package/dist/js/modern/manifest-op.js +0 -100
- package/dist/js/node/libs/createPage.js +0 -57
- package/dist/js/node/libs/invoker.js +0 -66
- package/dist/js/node/libs/render.js +0 -22
- package/dist/js/node/loader/index.js +0 -115
- package/dist/js/node/manifest-op.js +0 -120
- package/dist/types/libs/createPage.d.ts +0 -2
- package/dist/types/libs/invoker.d.ts +0 -5
- package/dist/types/libs/render.d.ts +0 -3
- package/dist/types/loader/index.d.ts +0 -4
- package/dist/types/manifest-op.d.ts +0 -18
- package/src/libs/createPage.ts +0 -42
- package/src/libs/invoker.ts +0 -55
- package/src/libs/render.ts +0 -16
- package/src/loader/index.ts +0 -99
- package/src/manifest-op.ts +0 -110
- package/tests/operate.test.ts +0 -39
package/src/index.ts
CHANGED
|
@@ -1,76 +1,36 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
INTERNAL_SRC_ALIAS,
|
|
4
|
-
logger,
|
|
5
|
-
upath,
|
|
6
|
-
PLUGIN_SCHEMAS,
|
|
7
|
-
} from '@modern-js/utils';
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import { logger, PLUGIN_SCHEMAS } from '@modern-js/utils';
|
|
8
3
|
import {
|
|
9
4
|
createPlugin,
|
|
10
5
|
useAppContext,
|
|
11
6
|
useResolvedConfigContext,
|
|
12
7
|
} from '@modern-js/core';
|
|
13
|
-
import {
|
|
14
|
-
import { LoaderManifest } from './manifest-op';
|
|
8
|
+
import { generatePath } from 'react-router-dom';
|
|
15
9
|
import {
|
|
16
10
|
AgreedRoute,
|
|
17
11
|
AgreedRouteMap,
|
|
18
|
-
CreatePageListener,
|
|
19
12
|
EntryPoint,
|
|
20
13
|
ExtendOutputConfig,
|
|
21
|
-
|
|
14
|
+
SSG,
|
|
22
15
|
SsgRoute,
|
|
23
16
|
} from './types';
|
|
24
17
|
import {
|
|
25
18
|
formatOutput,
|
|
26
|
-
|
|
27
|
-
getSSGRenderLevel,
|
|
28
|
-
getUrlPrefix,
|
|
29
|
-
parsedSSGConfig,
|
|
19
|
+
isDynamicUrl,
|
|
30
20
|
readJSONSpec,
|
|
31
|
-
|
|
21
|
+
standardOptions,
|
|
32
22
|
writeJSONSpec,
|
|
33
23
|
} from './libs/util';
|
|
34
|
-
import { invoker } from './libs/invoker';
|
|
35
24
|
import { createServer } from './server';
|
|
36
25
|
import { writeHtmlFile } from './libs/output';
|
|
37
26
|
import { replaceRoute } from './libs/replace';
|
|
38
|
-
|
|
39
|
-
const listStaticFiles = (
|
|
40
|
-
pwd: string,
|
|
41
|
-
entriesDir: string,
|
|
42
|
-
useSSG: string | boolean,
|
|
43
|
-
) => {
|
|
44
|
-
const absEntriesDir = path.join(pwd, entriesDir);
|
|
45
|
-
|
|
46
|
-
const staticRenderLevel = getSSGRenderLevel(useSSG);
|
|
47
|
-
|
|
48
|
-
const staticFiles = new LoaderManifest().get(
|
|
49
|
-
absEntriesDir,
|
|
50
|
-
staticRenderLevel,
|
|
51
|
-
);
|
|
52
|
-
|
|
53
|
-
// 将绝对路径转换成 alias,因为获取到的约定路由也是使用别名的
|
|
54
|
-
const staticAlias = staticFiles.map(filepath =>
|
|
55
|
-
replaceWithAlias(path.join(pwd, 'src'), filepath, INTERNAL_SRC_ALIAS),
|
|
56
|
-
);
|
|
57
|
-
return staticAlias;
|
|
58
|
-
};
|
|
27
|
+
import { makeRoute } from './libs/make';
|
|
59
28
|
|
|
60
29
|
export default createPlugin(
|
|
61
30
|
(() => {
|
|
62
31
|
const agreedRouteMap: AgreedRouteMap = {};
|
|
63
32
|
|
|
64
33
|
return {
|
|
65
|
-
config() {
|
|
66
|
-
return {
|
|
67
|
-
tools: {
|
|
68
|
-
babel(config: any, { chain }: { chain: BabelChain }) {
|
|
69
|
-
chain.plugin('./loader').use(upath.normalizeSafe(require.resolve('./loader')));
|
|
70
|
-
},
|
|
71
|
-
},
|
|
72
|
-
};
|
|
73
|
-
},
|
|
74
34
|
validateSchema() {
|
|
75
35
|
return PLUGIN_SCHEMAS['@modern-js/plugin-ssg'];
|
|
76
36
|
},
|
|
@@ -93,25 +53,19 @@ export default createPlugin(
|
|
|
93
53
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
94
54
|
const appContext = useAppContext();
|
|
95
55
|
|
|
96
|
-
const { appDirectory } = appContext;
|
|
97
|
-
const {
|
|
98
|
-
output,
|
|
99
|
-
server: { baseUrl },
|
|
100
|
-
source: { entriesDir },
|
|
101
|
-
} = resolvedConfig;
|
|
56
|
+
const { appDirectory, entrypoints } = appContext;
|
|
57
|
+
const { output } = resolvedConfig;
|
|
102
58
|
const { ssg, path: outputPath } = output as typeof output &
|
|
103
59
|
ExtendOutputConfig;
|
|
104
60
|
|
|
105
|
-
const ssgOptions = Array.isArray(ssg) ? ssg.pop() : ssg;
|
|
61
|
+
const ssgOptions: SSG = Array.isArray(ssg) ? ssg.pop() : ssg;
|
|
106
62
|
// no ssg configuration, skip ssg render.
|
|
107
63
|
if (!ssgOptions) {
|
|
108
64
|
return;
|
|
109
65
|
}
|
|
110
66
|
|
|
111
|
-
const { useSSG, userHook } = parsedSSGConfig(ssgOptions);
|
|
112
67
|
const buildDir = path.join(appDirectory, outputPath as string);
|
|
113
68
|
const routes = readJSONSpec(buildDir);
|
|
114
|
-
const staticAlias = listStaticFiles(appDirectory, entriesDir!, useSSG);
|
|
115
69
|
|
|
116
70
|
// filter all routes not web
|
|
117
71
|
const pageRoutes = routes.filter(route => !route.isApi);
|
|
@@ -122,42 +76,83 @@ export default createPlugin(
|
|
|
122
76
|
return;
|
|
123
77
|
}
|
|
124
78
|
|
|
79
|
+
const intermediateOptions = standardOptions(ssgOptions, entrypoints);
|
|
80
|
+
|
|
81
|
+
if (!intermediateOptions) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
|
|
125
85
|
const ssgRoutes: SsgRoute[] = [];
|
|
86
|
+
// each route will try to match the configuration
|
|
87
|
+
pageRoutes.forEach(pageRoute => {
|
|
88
|
+
const { entryName, entryPath } = pageRoute;
|
|
89
|
+
const agreedRoutes = agreedRouteMap[entryName];
|
|
90
|
+
let entryOptions = intermediateOptions[entryName];
|
|
91
|
+
|
|
92
|
+
if (!agreedRoutes) {
|
|
93
|
+
// default behavior for non-agreed route
|
|
94
|
+
if (!entryOptions) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
126
97
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
98
|
+
// only add entry route if entryOptions is true
|
|
99
|
+
if (entryOptions === true) {
|
|
100
|
+
ssgRoutes.push({ ...pageRoute, output: entryPath });
|
|
101
|
+
} else if (entryOptions.routes?.length > 0) {
|
|
102
|
+
// if entryOptions is object and has routes options
|
|
103
|
+
// add every route in options
|
|
104
|
+
const { routes: enrtyRoutes, headers } = entryOptions;
|
|
105
|
+
enrtyRoutes.forEach(route => {
|
|
106
|
+
ssgRoutes.push(makeRoute(pageRoute, route, headers));
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
} else {
|
|
110
|
+
// Unless entryOptions is set to false
|
|
111
|
+
// the default behavior is to add all file-based routes
|
|
112
|
+
if (entryOptions === false) {
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (!entryOptions || entryOptions === true) {
|
|
117
|
+
entryOptions = { preventDefault: [], routes: [], headers: {} };
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const {
|
|
121
|
+
preventDefault = [],
|
|
122
|
+
routes: userRoutes = [],
|
|
123
|
+
headers,
|
|
124
|
+
} = entryOptions;
|
|
125
|
+
// if the user sets the routes, then only add them
|
|
126
|
+
if (userRoutes.length > 0) {
|
|
127
|
+
userRoutes.forEach(route => {
|
|
128
|
+
if (typeof route === 'string') {
|
|
129
|
+
ssgRoutes.push(makeRoute(pageRoute, route, headers));
|
|
130
|
+
} else if (Array.isArray(route.params)) {
|
|
131
|
+
route.params.forEach(param => {
|
|
132
|
+
ssgRoutes.push(
|
|
133
|
+
makeRoute(
|
|
134
|
+
pageRoute,
|
|
135
|
+
{ ...route, url: generatePath(route.url, param) },
|
|
136
|
+
headers,
|
|
137
|
+
),
|
|
138
|
+
);
|
|
139
|
+
});
|
|
140
|
+
} else {
|
|
141
|
+
ssgRoutes.push(makeRoute(pageRoute, route, headers));
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
} else {
|
|
145
|
+
// otherwith add all except dynamic routes
|
|
146
|
+
agreedRoutes
|
|
147
|
+
.filter(route => !preventDefault.includes(route.path))
|
|
148
|
+
.forEach(route => {
|
|
149
|
+
if (!isDynamicUrl(route.path)) {
|
|
150
|
+
ssgRoutes.push(makeRoute(pageRoute, route.path, headers));
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
}
|
|
147
154
|
}
|
|
148
|
-
|
|
149
|
-
return !ssgRoutes.some(
|
|
150
|
-
ssgRoute => ssgRoute.urlPath === context.route.path,
|
|
151
|
-
);
|
|
152
|
-
};
|
|
153
|
-
|
|
154
|
-
await invoker(
|
|
155
|
-
pageRoutes,
|
|
156
|
-
agreedRouteMap,
|
|
157
|
-
userHook,
|
|
158
|
-
autoAddAgreed,
|
|
159
|
-
listener,
|
|
160
|
-
);
|
|
155
|
+
});
|
|
161
156
|
|
|
162
157
|
if (ssgRoutes.length === 0) {
|
|
163
158
|
return;
|
|
@@ -183,6 +178,7 @@ export default createPlugin(
|
|
|
183
178
|
);
|
|
184
179
|
}
|
|
185
180
|
ssgRoute.isSSR = false;
|
|
181
|
+
ssgRoute.output = formatOutput(ssgRoute.output);
|
|
186
182
|
});
|
|
187
183
|
|
|
188
184
|
const htmlAry = await createServer(
|
package/src/libs/make.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import { ModernRoute } from '@modern-js/server';
|
|
3
|
+
import normalize from 'normalize-path';
|
|
4
|
+
import { compile } from '../server/prerender';
|
|
5
|
+
import { RouteOptions, SsgRoute } from '../types';
|
|
6
|
+
|
|
7
|
+
export function makeRender(
|
|
8
|
+
ssgRoutes: SsgRoute[],
|
|
9
|
+
render: ReturnType<typeof compile>,
|
|
10
|
+
port: number,
|
|
11
|
+
): Promise<string>[] {
|
|
12
|
+
return ssgRoutes.map((ssgRoute: SsgRoute) =>
|
|
13
|
+
render({
|
|
14
|
+
url: ssgRoute.urlPath,
|
|
15
|
+
headers: { host: `localhost:${port}`, ...ssgRoute.headers },
|
|
16
|
+
connection: {},
|
|
17
|
+
}),
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function makeRoute(
|
|
22
|
+
baseRoute: ModernRoute,
|
|
23
|
+
route: string | RouteOptions,
|
|
24
|
+
headers: Record<string, any> = {},
|
|
25
|
+
): SsgRoute {
|
|
26
|
+
const { urlPath, entryPath } = baseRoute;
|
|
27
|
+
|
|
28
|
+
if (typeof route === 'string') {
|
|
29
|
+
return {
|
|
30
|
+
...baseRoute,
|
|
31
|
+
urlPath: normalize(`${urlPath}${route}`) || '/',
|
|
32
|
+
headers,
|
|
33
|
+
output: path.join(entryPath, `..${route}`),
|
|
34
|
+
};
|
|
35
|
+
} else {
|
|
36
|
+
return {
|
|
37
|
+
...baseRoute,
|
|
38
|
+
urlPath: normalize(`${urlPath}${route.url}`) || '/',
|
|
39
|
+
headers: { ...headers, ...route.headers },
|
|
40
|
+
output: route.output
|
|
41
|
+
? path.normalize(route.output)
|
|
42
|
+
: path.join(entryPath, `..${route.url}`),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
}
|
package/src/libs/output.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import { fs } from '@modern-js/utils';
|
|
2
3
|
import { SsgRoute } from '../types';
|
|
3
4
|
|
|
4
5
|
export function writeHtmlFile(
|
|
@@ -8,7 +9,7 @@ export function writeHtmlFile(
|
|
|
8
9
|
) {
|
|
9
10
|
htmlAry.forEach((html: any, index: number) => {
|
|
10
11
|
const ssgRoute = ssgRoutes[index];
|
|
11
|
-
const filepath = path.join(baseDir, ssgRoute.output
|
|
12
|
+
const filepath = path.join(baseDir, ssgRoute.output);
|
|
12
13
|
if (!fs.existsSync(path.dirname(filepath))) {
|
|
13
14
|
fs.ensureDirSync(path.dirname(filepath));
|
|
14
15
|
}
|
package/src/libs/replace.ts
CHANGED
|
@@ -2,7 +2,7 @@ import normalize from 'normalize-path';
|
|
|
2
2
|
import { ModernRoute } from '@modern-js/server';
|
|
3
3
|
import { SsgRoute } from '../types';
|
|
4
4
|
|
|
5
|
-
export function exist(route:
|
|
5
|
+
export function exist(route: ModernRoute, pageRoutes: ModernRoute[]): number {
|
|
6
6
|
return pageRoutes.slice().findIndex(pageRoute => {
|
|
7
7
|
const urlEqual = normalize(pageRoute.urlPath) === normalize(route.urlPath);
|
|
8
8
|
const entryEqual = pageRoute.entryName === route.entryName;
|
|
@@ -16,12 +16,15 @@ export function exist(route: SsgRoute, pageRoutes: ModernRoute[]): number {
|
|
|
16
16
|
export function replaceRoute(ssgRoutes: SsgRoute[], pageRoutes: ModernRoute[]) {
|
|
17
17
|
// remove redundant fields and replace rendered entryPath
|
|
18
18
|
const cleanSsgRoutes = ssgRoutes.map(ssgRoute => {
|
|
19
|
-
const { output, ...cleanSsgRoute } = ssgRoute;
|
|
20
|
-
return Object.assign(
|
|
19
|
+
const { output, headers, ...cleanSsgRoute } = ssgRoute;
|
|
20
|
+
return Object.assign(
|
|
21
|
+
cleanSsgRoute,
|
|
22
|
+
output ? { entryPath: output } : {},
|
|
23
|
+
) as ModernRoute;
|
|
21
24
|
});
|
|
22
25
|
|
|
23
26
|
// all routes that need to be added and replaced
|
|
24
|
-
const freshRoutes:
|
|
27
|
+
const freshRoutes: ModernRoute[] = [];
|
|
25
28
|
cleanSsgRoutes.forEach(ssgRoute => {
|
|
26
29
|
const index = exist(ssgRoute, pageRoutes);
|
|
27
30
|
|
package/src/libs/util.ts
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import { ROUTE_SPEC_FILE, fs, isSingleEntry } from '@modern-js/utils';
|
|
2
3
|
import { ModernRoute } from '@modern-js/server';
|
|
3
|
-
import {
|
|
4
|
-
import { MODE } from '@/manifest-op';
|
|
4
|
+
import { EntryPoint, MultiEntryOptions, SSG, SsgRoute } from '../types';
|
|
5
5
|
|
|
6
|
-
export function formatOutput(
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
export function formatOutput(filename: string) {
|
|
7
|
+
const outputPath = path.extname(filename)
|
|
8
|
+
? filename
|
|
9
|
+
: `${filename}/index.html`;
|
|
10
|
+
return outputPath;
|
|
10
11
|
}
|
|
11
12
|
|
|
12
13
|
export function formatPath(str: string) {
|
|
@@ -88,27 +89,39 @@ export const writeJSONSpec = (dir: string, routes: ModernRoute[]) => {
|
|
|
88
89
|
fs.writeJSONSync(routeJSONPath, { routes }, { spaces: 2 });
|
|
89
90
|
};
|
|
90
91
|
|
|
91
|
-
export const getSSGRenderLevel = (key: boolean | string) => {
|
|
92
|
-
const level = typeof key === 'boolean' ? MODE.LOOSE : MODE[key.toUpperCase()];
|
|
93
|
-
// currently only MODE.STRICT and MODE.LOOSE are supported
|
|
94
|
-
if (!level || level > 2 || level < 1) {
|
|
95
|
-
throw new Error(
|
|
96
|
-
`[SSG Render Fail] SSG 不支持当前 Mode,useSSG: ${key.toString()}, Level: ${level}`,
|
|
97
|
-
);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
return level;
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
export const parsedSSGConfig = (ssg: SSGConfig) => {
|
|
104
|
-
const useSSG = Boolean(ssg);
|
|
105
|
-
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
106
|
-
const userHook = typeof ssg === 'function' ? ssg : () => {};
|
|
107
|
-
return { useSSG, userHook };
|
|
108
|
-
};
|
|
109
|
-
|
|
110
92
|
export const replaceWithAlias = (
|
|
111
93
|
base: string,
|
|
112
94
|
filePath: string,
|
|
113
95
|
alias: string,
|
|
114
|
-
) => path.join(alias, path.relative(base, filePath));
|
|
96
|
+
) => path.posix.join(alias, path.posix.relative(base, filePath));
|
|
97
|
+
|
|
98
|
+
export const standardOptions = (ssgOptions: SSG, entrypoints: EntryPoint[]) => {
|
|
99
|
+
if (ssgOptions === false) {
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (ssgOptions === true) {
|
|
104
|
+
return entrypoints.reduce((opt, entry) => {
|
|
105
|
+
opt[entry.entryName] = ssgOptions;
|
|
106
|
+
return opt;
|
|
107
|
+
}, {} as MultiEntryOptions);
|
|
108
|
+
} else if (typeof ssgOptions === 'object') {
|
|
109
|
+
const isSingle = isSingleEntry(entrypoints);
|
|
110
|
+
|
|
111
|
+
if (isSingle && typeof (ssgOptions as any).main === 'undefined') {
|
|
112
|
+
return { main: ssgOptions } as MultiEntryOptions;
|
|
113
|
+
} else {
|
|
114
|
+
return ssgOptions as MultiEntryOptions;
|
|
115
|
+
}
|
|
116
|
+
} else if (typeof ssgOptions === 'function') {
|
|
117
|
+
const intermediateOptions: MultiEntryOptions = {};
|
|
118
|
+
for (const entrypoint of entrypoints) {
|
|
119
|
+
const { entryName } = entrypoint;
|
|
120
|
+
// Todo may be async function
|
|
121
|
+
intermediateOptions[entryName] = ssgOptions(entryName);
|
|
122
|
+
}
|
|
123
|
+
return intermediateOptions;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return false;
|
|
127
|
+
};
|
package/src/server/index.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import childProcess from 'child_process';
|
|
2
|
-
import
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { logger, SERVER_BUNDLE_DIRECTORY } from '@modern-js/utils';
|
|
3
4
|
import { NormalizedConfig, useAppContext } from '@modern-js/core';
|
|
4
5
|
import { ModernRoute } from '@modern-js/server';
|
|
5
6
|
import { SsgRoute } from '../types';
|
|
@@ -14,7 +15,7 @@ export const createServer = (
|
|
|
14
15
|
new Promise((resolve, reject) => {
|
|
15
16
|
// this side of the shallow copy of a route for subsequent render processing, to prevent the modification of the current field
|
|
16
17
|
// manually enable the server-side rendering configuration for all routes that require SSG
|
|
17
|
-
const backup = ssgRoutes.map(ssgRoute => ({
|
|
18
|
+
const backup: ModernRoute[] = ssgRoutes.map(ssgRoute => ({
|
|
18
19
|
...ssgRoute,
|
|
19
20
|
isSSR: true,
|
|
20
21
|
bundle: `${SERVER_BUNDLE_DIRECTORY}/${ssgRoute.entryName}.js`,
|
package/src/server/process.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import Server, { ModernRoute } from '@modern-js/server';
|
|
2
2
|
import portfinder from 'portfinder';
|
|
3
3
|
import { NormalizedConfig } from '@modern-js/core';
|
|
4
|
-
import { compatRequire
|
|
5
|
-
import { makeRender } from '../libs/
|
|
4
|
+
import { compatRequire } from '@modern-js/utils';
|
|
5
|
+
import { makeRender } from '../libs/make';
|
|
6
6
|
import { compile as createRender } from './prerender';
|
|
7
7
|
import { CLOSE_SIGN } from './consts';
|
|
8
|
+
import { SsgRoute } from '@/types';
|
|
8
9
|
|
|
9
10
|
type Then<T> = T extends PromiseLike<infer U> ? U : T;
|
|
10
11
|
|
|
@@ -13,10 +14,10 @@ type ModernServer = Then<ReturnType<typeof Server>>;
|
|
|
13
14
|
const safetyRequire = (filename: string, base: string) => {
|
|
14
15
|
try {
|
|
15
16
|
return compatRequire(
|
|
16
|
-
|
|
17
|
+
require.resolve(`${filename}/server`, { paths: [base] }),
|
|
17
18
|
);
|
|
18
19
|
} catch (e) {
|
|
19
|
-
return compatRequire(
|
|
20
|
+
return compatRequire(require.resolve(filename, { paths: [base] }));
|
|
20
21
|
}
|
|
21
22
|
};
|
|
22
23
|
|
|
@@ -67,11 +68,12 @@ process.on('message', async (chunk: string) => {
|
|
|
67
68
|
// get server handler, render to ssr
|
|
68
69
|
const render = createRender(modernServer!.getRequestHandler());
|
|
69
70
|
const renderPromiseAry = makeRender(
|
|
70
|
-
routes.filter(route => !route.isApi),
|
|
71
|
+
routes.filter(route => !route.isApi) as SsgRoute[],
|
|
71
72
|
render,
|
|
72
73
|
port,
|
|
73
74
|
);
|
|
74
75
|
|
|
76
|
+
// eslint-disable-next-line promise/no-promise-in-callback
|
|
75
77
|
const htmlAry = await Promise.all(renderPromiseAry);
|
|
76
78
|
htmlAry.forEach((html: string) => {
|
|
77
79
|
process.send!(html);
|
package/src/types.ts
CHANGED
|
@@ -16,30 +16,36 @@ export type AgreedRouteMap = {
|
|
|
16
16
|
[propNames: string]: AgreedRoute[];
|
|
17
17
|
};
|
|
18
18
|
|
|
19
|
-
export type
|
|
20
|
-
|
|
21
|
-
output?: string;
|
|
22
|
-
params?: Record<string, string | number>;
|
|
19
|
+
export type SsgRoute = ModernRoute & {
|
|
20
|
+
output: string;
|
|
23
21
|
headers?: Record<string, string>;
|
|
24
22
|
};
|
|
25
|
-
export type UserInterfaceRoute = ModernRoute & {
|
|
26
|
-
path: string;
|
|
27
|
-
agreed?: boolean;
|
|
28
|
-
};
|
|
29
23
|
|
|
30
|
-
export type
|
|
31
|
-
|
|
24
|
+
export type RouteOptions =
|
|
25
|
+
| string
|
|
26
|
+
| {
|
|
27
|
+
url: string;
|
|
28
|
+
output?: string;
|
|
29
|
+
params?: Record<string, any>[];
|
|
30
|
+
headers?: Record<string, any>;
|
|
31
|
+
};
|
|
32
32
|
|
|
33
|
-
export type
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
33
|
+
export type SingleEntryOptions =
|
|
34
|
+
| boolean
|
|
35
|
+
| {
|
|
36
|
+
preventDefault?: string[];
|
|
37
|
+
headers?: Record<string, any>;
|
|
38
|
+
routes: RouteOptions[];
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export type MultiEntryOptions = Record<string, SingleEntryOptions>;
|
|
42
|
+
|
|
43
|
+
export type SSG =
|
|
44
|
+
| boolean
|
|
45
|
+
| SingleEntryOptions
|
|
46
|
+
| MultiEntryOptions
|
|
47
|
+
| ((entryName: string) => SingleEntryOptions);
|
|
41
48
|
|
|
42
|
-
export type SSGConfig = boolean | ((context: any) => void);
|
|
43
49
|
export type ExtendOutputConfig = {
|
|
44
|
-
ssg:
|
|
50
|
+
ssg: SSG;
|
|
45
51
|
};
|