@modern-js/app-tools 2.39.1 → 2.39.2-alpha.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/dist/cjs/analyze/getBundleEntry.js +9 -1
- package/dist/cjs/config/initialize/inits.js +39 -43
- package/dist/esm/analyze/getBundleEntry.js +9 -1
- package/dist/esm/config/initialize/inits.js +44 -49
- package/dist/esm-node/analyze/getBundleEntry.js +9 -1
- package/dist/esm-node/config/initialize/inits.js +38 -43
- package/dist/js/modern/analyze/constants.js +15 -0
- package/dist/js/modern/analyze/generateCode.js +179 -0
- package/dist/js/modern/analyze/getBundleEntry.js +75 -0
- package/dist/js/modern/analyze/getClientRoutes.js +219 -0
- package/dist/js/modern/analyze/getFileSystemEntry.js +74 -0
- package/dist/js/modern/analyze/getHtmlTemplate.js +82 -0
- package/dist/js/modern/analyze/getServerRoutes.js +192 -0
- package/dist/js/modern/analyze/index.js +148 -0
- package/dist/js/modern/analyze/isDefaultExportFunction.js +32 -0
- package/dist/js/modern/analyze/makeLegalIdentifier.js +16 -0
- package/dist/js/modern/analyze/templates.js +88 -0
- package/dist/js/modern/analyze/utils.js +92 -0
- package/dist/js/modern/commands/build.js +154 -0
- package/dist/js/modern/commands/deploy.js +5 -0
- package/dist/js/modern/commands/dev.js +95 -0
- package/dist/js/modern/commands/index.js +3 -0
- package/dist/js/modern/commands/inspect.js +69 -0
- package/dist/js/modern/commands/start.js +31 -0
- package/dist/js/modern/exports/server.js +1 -0
- package/dist/js/modern/hooks.js +21 -0
- package/dist/js/modern/index.js +109 -0
- package/dist/js/modern/locale/en.js +35 -0
- package/dist/js/modern/locale/index.js +9 -0
- package/dist/js/modern/locale/zh.js +35 -0
- package/dist/js/modern/utils/config.js +78 -0
- package/dist/js/modern/utils/createCompiler.js +61 -0
- package/dist/js/modern/utils/createServer.js +18 -0
- package/dist/js/modern/utils/getSpecifiedEntries.js +36 -0
- package/dist/js/modern/utils/language.js +5 -0
- package/dist/js/modern/utils/printInstructions.js +11 -0
- package/dist/js/modern/utils/routes.js +15 -0
- package/dist/js/modern/utils/types.js +0 -0
- package/dist/js/node/analyze/constants.js +36 -0
- package/dist/js/node/analyze/generateCode.js +208 -0
- package/dist/js/node/analyze/getBundleEntry.js +89 -0
- package/dist/js/node/analyze/getClientRoutes.js +241 -0
- package/dist/js/node/analyze/getFileSystemEntry.js +90 -0
- package/dist/js/node/analyze/getHtmlTemplate.js +106 -0
- package/dist/js/node/analyze/getServerRoutes.js +208 -0
- package/dist/js/node/analyze/index.js +178 -0
- package/dist/js/node/analyze/isDefaultExportFunction.js +50 -0
- package/dist/js/node/analyze/makeLegalIdentifier.js +24 -0
- package/dist/js/node/analyze/templates.js +106 -0
- package/dist/js/node/analyze/utils.js +113 -0
- package/dist/js/node/commands/build.js +174 -0
- package/dist/js/node/commands/deploy.js +14 -0
- package/dist/js/node/commands/dev.js +120 -0
- package/dist/js/node/commands/index.js +44 -0
- package/dist/js/node/commands/inspect.js +98 -0
- package/dist/js/node/commands/start.js +47 -0
- package/dist/js/node/exports/server.js +13 -0
- package/dist/js/node/hooks.js +39 -0
- package/dist/js/node/index.js +141 -0
- package/dist/js/node/locale/en.js +42 -0
- package/dist/js/node/locale/index.js +20 -0
- package/dist/js/node/locale/zh.js +42 -0
- package/dist/js/node/utils/config.js +103 -0
- package/dist/js/node/utils/createCompiler.js +81 -0
- package/dist/js/node/utils/createServer.js +35 -0
- package/dist/js/node/utils/getSpecifiedEntries.js +46 -0
- package/dist/js/node/utils/language.js +13 -0
- package/dist/js/node/utils/printInstructions.js +22 -0
- package/dist/js/node/utils/routes.js +25 -0
- package/dist/js/node/utils/types.js +0 -0
- package/dist/types/config/initialize/inits.d.ts +2 -1
- package/package.json +6 -6
@@ -0,0 +1,219 @@
|
|
1
|
+
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
2
|
+
|
3
|
+
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
4
|
+
|
5
|
+
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
6
|
+
|
7
|
+
import path from 'path';
|
8
|
+
import { fs, createDebugger, findExists, normalizeToPosixPath } from '@modern-js/utils';
|
9
|
+
import { makeLegalIdentifier } from "./makeLegalIdentifier";
|
10
|
+
import { FILE_SYSTEM_ROUTES_COMPONENTS_DIR, FILE_SYSTEM_ROUTES_DYNAMIC_REGEXP, FILE_SYSTEM_ROUTES_GLOBAL_LAYOUT, FILE_SYSTEM_ROUTES_IGNORED_REGEX, FILE_SYSTEM_ROUTES_INDEX, FILE_SYSTEM_ROUTES_LAYOUT, JS_EXTENSIONS } from "./constants";
|
11
|
+
const debug = createDebugger('get-client-routes');
|
12
|
+
|
13
|
+
const findLayout = dir => findExists(JS_EXTENSIONS.map(ext => path.resolve(dir, `${FILE_SYSTEM_ROUTES_LAYOUT}${ext}`)));
|
14
|
+
|
15
|
+
const shouldSkip = file => {
|
16
|
+
// should not skip directory.
|
17
|
+
if (fs.statSync(file).isDirectory()) {
|
18
|
+
return false;
|
19
|
+
}
|
20
|
+
|
21
|
+
const ext = path.extname(file);
|
22
|
+
|
23
|
+
if (FILE_SYSTEM_ROUTES_IGNORED_REGEX.test(file) || !JS_EXTENSIONS.includes(ext) || FILE_SYSTEM_ROUTES_GLOBAL_LAYOUT === path.basename(file, ext)) {
|
24
|
+
return true;
|
25
|
+
}
|
26
|
+
|
27
|
+
return false;
|
28
|
+
};
|
29
|
+
|
30
|
+
const replaceWithAlias = (base, filePath, alias) => normalizeToPosixPath(path.join(alias, path.relative(base, filePath)));
|
31
|
+
|
32
|
+
const compName = (srcDirectory, filePath) => {
|
33
|
+
const legalCompName = makeLegalIdentifier(path.relative(srcDirectory, filePath));
|
34
|
+
return `Comp_${legalCompName}`;
|
35
|
+
};
|
36
|
+
|
37
|
+
const layoutNameAbbr = filePath => {
|
38
|
+
const prefix = 'L_';
|
39
|
+
const dirName = path.dirname(filePath).split('/').pop() || '';
|
40
|
+
return `${prefix}${makeLegalIdentifier(dirName)}`;
|
41
|
+
};
|
42
|
+
|
43
|
+
const parents = [];
|
44
|
+
/* eslint-disable no-param-reassign */
|
45
|
+
|
46
|
+
const recursiveReadDir = ({
|
47
|
+
dir,
|
48
|
+
routes,
|
49
|
+
basePath: _basePath = '/',
|
50
|
+
srcDirectory,
|
51
|
+
srcAlias
|
52
|
+
}) => {
|
53
|
+
let hasDynamicRoute = false;
|
54
|
+
let resetParent = false;
|
55
|
+
let parent = parents[parents.length - 1];
|
56
|
+
const layout = findLayout(dir);
|
57
|
+
|
58
|
+
if (layout) {
|
59
|
+
if (_basePath === '/') {
|
60
|
+
throw new Error(`should use _app instead of _layout in ${dir}`);
|
61
|
+
} else {
|
62
|
+
const alias = replaceWithAlias(srcDirectory, layout, srcAlias);
|
63
|
+
const componentName = compName(srcDirectory, layout);
|
64
|
+
const route = {
|
65
|
+
path: `${_basePath.substring(0, _basePath.length - 1)}`,
|
66
|
+
exact: false,
|
67
|
+
routes: [],
|
68
|
+
_component: alias,
|
69
|
+
component: componentName,
|
70
|
+
parent
|
71
|
+
};
|
72
|
+
parent = route;
|
73
|
+
resetParent = true;
|
74
|
+
routes.push(route);
|
75
|
+
parents.push(route);
|
76
|
+
routes = route.routes;
|
77
|
+
}
|
78
|
+
}
|
79
|
+
|
80
|
+
for (const relative of fs.readdirSync(dir)) {
|
81
|
+
const filePath = path.join(dir, relative);
|
82
|
+
|
83
|
+
if (!shouldSkip(filePath)) {
|
84
|
+
const filename = path.basename(filePath, path.extname(filePath));
|
85
|
+
const alias = replaceWithAlias(srcDirectory, filePath, srcAlias);
|
86
|
+
const componentName = compName(srcDirectory, filePath);
|
87
|
+
const dynamicRouteMatched = FILE_SYSTEM_ROUTES_DYNAMIC_REGEXP.exec(filename);
|
88
|
+
|
89
|
+
if (dynamicRouteMatched) {
|
90
|
+
if (hasDynamicRoute) {
|
91
|
+
throw new Error(`Can't set two dynamic route in one directory: ${dir}`);
|
92
|
+
} else {
|
93
|
+
hasDynamicRoute = true;
|
94
|
+
}
|
95
|
+
}
|
96
|
+
|
97
|
+
const route = {
|
98
|
+
path: `${_basePath}${dynamicRouteMatched ? `:${dynamicRouteMatched[1]}${dynamicRouteMatched[2]}` : filename}`,
|
99
|
+
_component: alias,
|
100
|
+
component: componentName,
|
101
|
+
exact: true,
|
102
|
+
parent
|
103
|
+
};
|
104
|
+
|
105
|
+
if (fs.statSync(filePath).isDirectory()) {
|
106
|
+
recursiveReadDir({
|
107
|
+
dir: filePath,
|
108
|
+
routes,
|
109
|
+
basePath: `${route.path}/`,
|
110
|
+
srcDirectory,
|
111
|
+
srcAlias
|
112
|
+
});
|
113
|
+
continue;
|
114
|
+
}
|
115
|
+
|
116
|
+
if (filename === FILE_SYSTEM_ROUTES_LAYOUT) {
|
117
|
+
continue;
|
118
|
+
}
|
119
|
+
|
120
|
+
if (filename === FILE_SYSTEM_ROUTES_INDEX) {
|
121
|
+
route.path = _basePath === '/' ? _basePath : `${_basePath.substring(0, _basePath.length - 1)}`;
|
122
|
+
}
|
123
|
+
|
124
|
+
if (filename === '404' && _basePath === '/') {
|
125
|
+
route.path = '*';
|
126
|
+
route.exact = false;
|
127
|
+
}
|
128
|
+
|
129
|
+
routes.push(route);
|
130
|
+
}
|
131
|
+
}
|
132
|
+
|
133
|
+
if (resetParent) {
|
134
|
+
parents.pop();
|
135
|
+
}
|
136
|
+
};
|
137
|
+
/* eslint-enable no-param-reassign */
|
138
|
+
|
139
|
+
|
140
|
+
const normalizeNestedRoutes = (nested, internalComponentsDir, internalDirectory, internalDirAlias) => {
|
141
|
+
const flat = routes => routes.reduce((memo, route) => memo.concat(Array.isArray(route.routes) ? flat(route.routes) : [route]), []);
|
142
|
+
|
143
|
+
const generate = route => {
|
144
|
+
const codes = [];
|
145
|
+
let lastComponent = route.component;
|
146
|
+
const imports = [`import React from 'react';`, `import ${lastComponent} from '${route._component}'`]; // eslint-disable-next-line no-param-reassign, no-cond-assign
|
147
|
+
|
148
|
+
while (route = route.parent) {
|
149
|
+
const layoutComponent = route.component;
|
150
|
+
const layoutComponentAbbr = layoutNameAbbr(route._component);
|
151
|
+
imports.push(`import ${layoutComponent} from '${route._component}';`);
|
152
|
+
const currentComponent = `${layoutComponentAbbr}_${lastComponent}`;
|
153
|
+
codes.push(`const ${currentComponent} = props => <${layoutComponent} Component={${lastComponent}} {...props} />;`);
|
154
|
+
lastComponent = currentComponent;
|
155
|
+
}
|
156
|
+
|
157
|
+
const file = path.resolve(internalComponentsDir, `${lastComponent}.jsx`);
|
158
|
+
fs.outputFileSync(file, `${imports.join('\n')}\n${codes.join('\n')}\nexport default ${lastComponent}`);
|
159
|
+
return {
|
160
|
+
component: lastComponent,
|
161
|
+
_component: replaceWithAlias(internalDirectory, file, internalDirAlias)
|
162
|
+
};
|
163
|
+
};
|
164
|
+
|
165
|
+
const normalized = flat(nested).map(route => route.parent ? _objectSpread(_objectSpread(_objectSpread({}, route), generate(route)), {}, {
|
166
|
+
parent: undefined
|
167
|
+
}) : _objectSpread(_objectSpread({}, route), {}, {
|
168
|
+
parent: undefined
|
169
|
+
}));
|
170
|
+
return normalized;
|
171
|
+
};
|
172
|
+
|
173
|
+
const getRouteWeight = route => route === '*' ? 999 : route.split(':').length - 1;
|
174
|
+
|
175
|
+
export const getClientRoutes = ({
|
176
|
+
entrypoint,
|
177
|
+
srcDirectory,
|
178
|
+
srcAlias,
|
179
|
+
internalDirectory,
|
180
|
+
internalDirAlias
|
181
|
+
}) => {
|
182
|
+
const {
|
183
|
+
entry,
|
184
|
+
entryName
|
185
|
+
} = entrypoint;
|
186
|
+
|
187
|
+
if (!fs.existsSync(entry)) {
|
188
|
+
throw new Error(`generate file system routes error, ${entry} directory not found.`);
|
189
|
+
}
|
190
|
+
|
191
|
+
if (!(fs.existsSync(entry) && fs.statSync(entry).isDirectory())) {
|
192
|
+
throw new Error(`generate file system routes error, ${entry} should be directory.`);
|
193
|
+
}
|
194
|
+
|
195
|
+
let routes = [];
|
196
|
+
recursiveReadDir({
|
197
|
+
dir: entry,
|
198
|
+
routes,
|
199
|
+
basePath: '/',
|
200
|
+
srcDirectory,
|
201
|
+
srcAlias
|
202
|
+
});
|
203
|
+
const internalComponentsDir = path.resolve(internalDirectory, `${entryName}/${FILE_SYSTEM_ROUTES_COMPONENTS_DIR}`);
|
204
|
+
fs.emptyDirSync(internalComponentsDir);
|
205
|
+
routes = normalizeNestedRoutes(routes, internalComponentsDir, internalDirectory, internalDirAlias);
|
206
|
+
parents.length = 0; // FIXME: support more situations
|
207
|
+
|
208
|
+
routes.sort((a, b) => {
|
209
|
+
const delta = getRouteWeight(a.path) - getRouteWeight(b.path);
|
210
|
+
|
211
|
+
if (delta === 0) {
|
212
|
+
return a.path.length - b.path.length;
|
213
|
+
}
|
214
|
+
|
215
|
+
return delta;
|
216
|
+
});
|
217
|
+
debug(`fileSystem routes: %o`, routes);
|
218
|
+
return routes;
|
219
|
+
};
|
@@ -0,0 +1,74 @@
|
|
1
|
+
import fs from 'fs';
|
2
|
+
import path from 'path';
|
3
|
+
import { findExists, ensureAbsolutePath } from '@modern-js/utils';
|
4
|
+
import { isDefaultExportFunction } from "./isDefaultExportFunction";
|
5
|
+
import { JS_EXTENSIONS, INDEX_FILE_NAME, APP_FILE_NAME, PAGES_DIR_NAME, FILE_SYSTEM_ROUTES_GLOBAL_LAYOUT } from "./constants";
|
6
|
+
|
7
|
+
const hasIndex = dir => findExists(JS_EXTENSIONS.map(ext => path.resolve(dir, `${INDEX_FILE_NAME}${ext}`)));
|
8
|
+
|
9
|
+
const hasApp = dir => findExists(JS_EXTENSIONS.map(ext => path.resolve(dir, `${APP_FILE_NAME}${ext}`)));
|
10
|
+
|
11
|
+
const hasPages = dir => fs.existsSync(path.join(dir, PAGES_DIR_NAME));
|
12
|
+
|
13
|
+
const isBundleEntry = dir => hasApp(dir) || hasPages(dir) || hasIndex(dir);
|
14
|
+
|
15
|
+
const scanDir = dirs => dirs.map(dir => {
|
16
|
+
const indexFile = hasIndex(dir);
|
17
|
+
const customBootstrap = isDefaultExportFunction(indexFile) ? indexFile : false;
|
18
|
+
const entryName = path.basename(dir);
|
19
|
+
|
20
|
+
if (indexFile && !customBootstrap) {
|
21
|
+
return {
|
22
|
+
entryName,
|
23
|
+
entry: indexFile,
|
24
|
+
isAutoMount: false
|
25
|
+
};
|
26
|
+
}
|
27
|
+
|
28
|
+
if (hasApp(dir)) {
|
29
|
+
return {
|
30
|
+
entryName,
|
31
|
+
entry: path.join(dir, APP_FILE_NAME),
|
32
|
+
isAutoMount: true,
|
33
|
+
customBootstrap
|
34
|
+
};
|
35
|
+
} else if (hasPages(dir)) {
|
36
|
+
return {
|
37
|
+
entryName,
|
38
|
+
entry: path.join(dir, PAGES_DIR_NAME),
|
39
|
+
fileSystemRoutes: {
|
40
|
+
globalApp: findExists(JS_EXTENSIONS.map(ext => path.resolve(dir, `./${PAGES_DIR_NAME}/${FILE_SYSTEM_ROUTES_GLOBAL_LAYOUT}${ext}`)))
|
41
|
+
},
|
42
|
+
isAutoMount: true,
|
43
|
+
customBootstrap
|
44
|
+
};
|
45
|
+
} else {
|
46
|
+
return {
|
47
|
+
entryName,
|
48
|
+
entry: indexFile,
|
49
|
+
isAutoMount: false
|
50
|
+
};
|
51
|
+
}
|
52
|
+
});
|
53
|
+
|
54
|
+
export const getFileSystemEntry = (appContext, config) => {
|
55
|
+
const {
|
56
|
+
appDirectory
|
57
|
+
} = appContext;
|
58
|
+
const {
|
59
|
+
source: {
|
60
|
+
entriesDir
|
61
|
+
}
|
62
|
+
} = config;
|
63
|
+
const src = ensureAbsolutePath(appDirectory, entriesDir);
|
64
|
+
|
65
|
+
if (fs.existsSync(src)) {
|
66
|
+
if (fs.statSync(src).isDirectory()) {
|
67
|
+
return scanDir(isBundleEntry(src) ? [src] : fs.readdirSync(src).map(file => path.join(src, file)).filter(file => fs.statSync(file).isDirectory() && isBundleEntry(file)));
|
68
|
+
} else {
|
69
|
+
throw Error(`source.entriesDir accept a directory.`);
|
70
|
+
}
|
71
|
+
} else {
|
72
|
+
throw Error(`src dir ${entriesDir} not found.`);
|
73
|
+
}
|
74
|
+
};
|
@@ -0,0 +1,82 @@
|
|
1
|
+
import path from 'path';
|
2
|
+
import { fs, findExists, MAIN_ENTRY_NAME } from '@modern-js/utils';
|
3
|
+
import { HTML_PARTIALS_EXTENSIONS, HTML_PARTIALS_FOLDER } from "./constants";
|
4
|
+
import * as templates from "./templates";
|
5
|
+
var PartialPosition;
|
6
|
+
|
7
|
+
(function (PartialPosition) {
|
8
|
+
PartialPosition["TOP"] = "top";
|
9
|
+
PartialPosition["HEAD"] = "head";
|
10
|
+
PartialPosition["BODY"] = "body";
|
11
|
+
PartialPosition["BOTTOM"] = "bottom";
|
12
|
+
PartialPosition["INDEX"] = "index";
|
13
|
+
})(PartialPosition || (PartialPosition = {}));
|
14
|
+
|
15
|
+
const findPartials = (dir, entryName, position) => {
|
16
|
+
if (fs.existsSync(dir)) {
|
17
|
+
const base = findExists(HTML_PARTIALS_EXTENSIONS.map(ext => path.resolve(dir, `${position}${ext}`)));
|
18
|
+
const file = entryName ? findExists(HTML_PARTIALS_EXTENSIONS.map(ext => path.resolve(dir, entryName, `${position}${ext}`))) || base : base;
|
19
|
+
return file ? {
|
20
|
+
file,
|
21
|
+
content: fs.readFileSync(file, 'utf8')
|
22
|
+
} : null;
|
23
|
+
}
|
24
|
+
|
25
|
+
return null;
|
26
|
+
}; // generate html template for
|
27
|
+
|
28
|
+
|
29
|
+
export const getHtmlTemplate = async (entrypoints, api, {
|
30
|
+
appContext,
|
31
|
+
config
|
32
|
+
}) => {
|
33
|
+
const {
|
34
|
+
appDirectory,
|
35
|
+
internalDirectory
|
36
|
+
} = appContext;
|
37
|
+
const {
|
38
|
+
source: {
|
39
|
+
configDir
|
40
|
+
}
|
41
|
+
} = config;
|
42
|
+
const htmlDir = path.resolve(appDirectory, configDir, HTML_PARTIALS_FOLDER);
|
43
|
+
const htmlTemplates = {};
|
44
|
+
|
45
|
+
for (const entrypoint of entrypoints) {
|
46
|
+
const {
|
47
|
+
entryName
|
48
|
+
} = entrypoint;
|
49
|
+
const name = entrypoints.length === 1 && entryName === MAIN_ENTRY_NAME ? '' : entryName;
|
50
|
+
const customIndexTemplate = findPartials(htmlDir, name, PartialPosition.INDEX);
|
51
|
+
|
52
|
+
if (customIndexTemplate) {
|
53
|
+
htmlTemplates[entryName] = customIndexTemplate.file;
|
54
|
+
} else {
|
55
|
+
const hookRunners = api.useHookRunners();
|
56
|
+
const {
|
57
|
+
partials
|
58
|
+
} = await hookRunners.htmlPartials({
|
59
|
+
entrypoint,
|
60
|
+
partials: [PartialPosition.TOP, PartialPosition.HEAD, PartialPosition.BODY].reduce((previous, position) => {
|
61
|
+
const found = findPartials(htmlDir, name, position);
|
62
|
+
previous[position] = found ? [found.content] : [];
|
63
|
+
return previous;
|
64
|
+
}, {
|
65
|
+
top: [],
|
66
|
+
head: [],
|
67
|
+
body: []
|
68
|
+
})
|
69
|
+
});
|
70
|
+
const templatePath = path.resolve(internalDirectory, entryName, 'index.html');
|
71
|
+
fs.outputFileSync(templatePath, templates.html(partials), 'utf8');
|
72
|
+
htmlTemplates[entryName] = templatePath;
|
73
|
+
const bottomTemplate = findPartials(htmlDir, name, PartialPosition.BOTTOM);
|
74
|
+
|
75
|
+
if (bottomTemplate) {
|
76
|
+
htmlTemplates[`__${entryName}-bottom__`] = bottomTemplate.content;
|
77
|
+
}
|
78
|
+
}
|
79
|
+
}
|
80
|
+
|
81
|
+
return htmlTemplates;
|
82
|
+
};
|
@@ -0,0 +1,192 @@
|
|
1
|
+
const _excluded = ["path"],
|
2
|
+
_excluded2 = ["path"];
|
3
|
+
|
4
|
+
function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
|
5
|
+
|
6
|
+
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
|
7
|
+
|
8
|
+
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
9
|
+
|
10
|
+
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
11
|
+
|
12
|
+
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
13
|
+
|
14
|
+
import path from 'path';
|
15
|
+
import fs from 'fs';
|
16
|
+
import { urlJoin, isPlainObject, removeLeadingSlash, getEntryOptions, SERVER_BUNDLE_DIRECTORY, MAIN_ENTRY_NAME, removeTailSlash } from '@modern-js/utils';
|
17
|
+
import { walkDirectory } from "./utils";
|
18
|
+
/**
|
19
|
+
* Add base url for each server route.
|
20
|
+
* @param baseUrl - Base url from server.baseUrl
|
21
|
+
* @param routes - Server routes.
|
22
|
+
* @returns Server routes with baseUrl prefixed.
|
23
|
+
*/
|
24
|
+
|
25
|
+
const applyBaseUrl = (baseUrl, routes) => {
|
26
|
+
if (baseUrl) {
|
27
|
+
if (Array.isArray(baseUrl)) {
|
28
|
+
return baseUrl.reduce((previous, current) => [...previous, ...applyBaseUrl(current, routes)], []);
|
29
|
+
} else {
|
30
|
+
return routes.map(route => {
|
31
|
+
const urlPath = urlJoin(baseUrl, route.urlPath);
|
32
|
+
return _objectSpread(_objectSpread({}, route), {}, {
|
33
|
+
urlPath: urlPath === '/' ? urlPath : removeTailSlash(urlPath)
|
34
|
+
});
|
35
|
+
});
|
36
|
+
}
|
37
|
+
}
|
38
|
+
|
39
|
+
return routes;
|
40
|
+
};
|
41
|
+
/**
|
42
|
+
*
|
43
|
+
* @param original - Original entrypoint route info.
|
44
|
+
* @param routeOptions - Custom entrypoint route config from server.routes.
|
45
|
+
* @returns
|
46
|
+
*/
|
47
|
+
|
48
|
+
|
49
|
+
const applyRouteOptions = (original, routeOptions) => {
|
50
|
+
const {
|
51
|
+
route,
|
52
|
+
disableSpa
|
53
|
+
} = routeOptions;
|
54
|
+
original.isSPA = !disableSpa; // set entryPath as dir
|
55
|
+
|
56
|
+
!original.isSPA && (original.entryPath = path.dirname(original.entryPath));
|
57
|
+
let routes;
|
58
|
+
|
59
|
+
if (route) {
|
60
|
+
if (Array.isArray(route)) {
|
61
|
+
routes = route.map(url => {
|
62
|
+
if (isPlainObject(url)) {
|
63
|
+
const _ref = url,
|
64
|
+
{
|
65
|
+
path: urlPath
|
66
|
+
} = _ref,
|
67
|
+
other = _objectWithoutProperties(_ref, _excluded);
|
68
|
+
|
69
|
+
return _objectSpread(_objectSpread(_objectSpread({}, original), other), {}, {
|
70
|
+
urlPath
|
71
|
+
});
|
72
|
+
} else {
|
73
|
+
return _objectSpread(_objectSpread({}, original), {}, {
|
74
|
+
urlPath: url
|
75
|
+
});
|
76
|
+
}
|
77
|
+
});
|
78
|
+
} else if (isPlainObject(route)) {
|
79
|
+
const _ref2 = route,
|
80
|
+
{
|
81
|
+
path: urlPath
|
82
|
+
} = _ref2,
|
83
|
+
other = _objectWithoutProperties(_ref2, _excluded2);
|
84
|
+
|
85
|
+
routes = [_objectSpread(_objectSpread(_objectSpread({}, original), other), {}, {
|
86
|
+
urlPath
|
87
|
+
})];
|
88
|
+
} else {
|
89
|
+
routes = [_objectSpread(_objectSpread({}, original), {}, {
|
90
|
+
urlPath: route
|
91
|
+
})];
|
92
|
+
}
|
93
|
+
} else {
|
94
|
+
routes = [original];
|
95
|
+
}
|
96
|
+
|
97
|
+
return routes;
|
98
|
+
};
|
99
|
+
/**
|
100
|
+
* Collect routes from entrypoints.
|
101
|
+
* @param entrypoints - Bundle entrypoints.
|
102
|
+
* @param config - Normalized user config.
|
103
|
+
* @returns entrypoint Routes
|
104
|
+
*/
|
105
|
+
|
106
|
+
|
107
|
+
const collectHtmlRoutes = (entrypoints, appContext, config) => {
|
108
|
+
const {
|
109
|
+
output: {
|
110
|
+
htmlPath,
|
111
|
+
disableHtmlFolder,
|
112
|
+
enableModernMode
|
113
|
+
},
|
114
|
+
server: {
|
115
|
+
baseUrl,
|
116
|
+
routes,
|
117
|
+
ssr,
|
118
|
+
ssrByEntries
|
119
|
+
}
|
120
|
+
} = config;
|
121
|
+
const {
|
122
|
+
packageName
|
123
|
+
} = appContext;
|
124
|
+
let htmlRoutes = entrypoints.reduce((previous, {
|
125
|
+
entryName
|
126
|
+
}) => {
|
127
|
+
const entryOptions = getEntryOptions(entryName, ssr, ssrByEntries, packageName);
|
128
|
+
const isSSR = Boolean(entryOptions);
|
129
|
+
const {
|
130
|
+
resHeaders
|
131
|
+
} = (routes === null || routes === void 0 ? void 0 : routes[entryName]) || {};
|
132
|
+
let route = {
|
133
|
+
urlPath: `/${entryName === MAIN_ENTRY_NAME ? '' : entryName}`,
|
134
|
+
entryName,
|
135
|
+
entryPath: removeLeadingSlash(path.posix.normalize(`${htmlPath}/${entryName}${disableHtmlFolder ? '.html' : '/index.html'}`)),
|
136
|
+
isSPA: true,
|
137
|
+
isSSR,
|
138
|
+
responseHeaders: resHeaders,
|
139
|
+
enableModernMode: Boolean(enableModernMode),
|
140
|
+
bundle: isSSR ? `${SERVER_BUNDLE_DIRECTORY}/${entryName}.js` : undefined
|
141
|
+
};
|
142
|
+
|
143
|
+
if (routes !== null && routes !== void 0 && routes.hasOwnProperty(entryName)) {
|
144
|
+
const routeOptions = isPlainObject(routes[entryName]) ? routes[entryName] : {
|
145
|
+
route: routes[entryName]
|
146
|
+
};
|
147
|
+
route = applyRouteOptions(route, routeOptions);
|
148
|
+
}
|
149
|
+
|
150
|
+
return Array.isArray(route) ? [...previous, ...route] : [...previous, route];
|
151
|
+
}, []);
|
152
|
+
htmlRoutes = applyBaseUrl(baseUrl, htmlRoutes);
|
153
|
+
return htmlRoutes;
|
154
|
+
};
|
155
|
+
/**
|
156
|
+
* Collect static public file routes from config/public folder.
|
157
|
+
* @param appContext - App context info.
|
158
|
+
* @param config - normalized user config.
|
159
|
+
* @returns Static public file routes.
|
160
|
+
*/
|
161
|
+
|
162
|
+
|
163
|
+
const collectStaticRoutes = (appContext, config) => {
|
164
|
+
const {
|
165
|
+
appDirectory
|
166
|
+
} = appContext;
|
167
|
+
const {
|
168
|
+
source: {
|
169
|
+
configDir
|
170
|
+
},
|
171
|
+
server: {
|
172
|
+
publicRoutes = {}
|
173
|
+
}
|
174
|
+
} = config;
|
175
|
+
const publicFolder = path.resolve(appDirectory, configDir, 'public');
|
176
|
+
return fs.existsSync(publicFolder) ? walkDirectory(publicFolder).map(filePath => {
|
177
|
+
const urlPath = `${urlJoin(toPosix(filePath).slice(toPosix(publicFolder).length))}`;
|
178
|
+
return {
|
179
|
+
urlPath: publicRoutes[removeLeadingSlash(urlPath)] || urlPath,
|
180
|
+
isSPA: true,
|
181
|
+
isSSR: false,
|
182
|
+
entryPath: toPosix(path.relative(path.resolve(appDirectory, configDir), filePath))
|
183
|
+
};
|
184
|
+
}) : [];
|
185
|
+
};
|
186
|
+
|
187
|
+
export const getServerRoutes = (entrypoints, {
|
188
|
+
appContext,
|
189
|
+
config
|
190
|
+
}) => [...collectHtmlRoutes(entrypoints, appContext, config), ...collectStaticRoutes(appContext, config)];
|
191
|
+
|
192
|
+
const toPosix = pathStr => pathStr.split(path.sep).join(path.posix.sep);
|