@umijs/preset-umi 4.1.2 → 4.1.3
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/features/okam/okam.js +8 -3
- package/dist/features/routePreloadOnLoad/routePreloadOnLoad.d.ts +21 -0
- package/dist/features/routePreloadOnLoad/routePreloadOnLoad.js +214 -0
- package/dist/features/routePreloadOnLoad/utils.d.ts +14 -0
- package/dist/features/routePreloadOnLoad/utils.js +57 -0
- package/dist/index.js +1 -0
- package/package.json +14 -14
- package/templates/routePreloadOnLoad/preloadRouteFilesScp.js +1 -0
|
@@ -24,9 +24,14 @@ __export(okam_exports, {
|
|
|
24
24
|
module.exports = __toCommonJS(okam_exports);
|
|
25
25
|
var import_utils = require("@umijs/utils");
|
|
26
26
|
var okam_default = (api) => {
|
|
27
|
+
api.describe({
|
|
28
|
+
enableBy: () => Boolean(process.env.OKAM)
|
|
29
|
+
});
|
|
27
30
|
api.onCheck(() => {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
+
(0, import_utils.checkVersion)(16, `Node 16 is required when using mako.`);
|
|
32
|
+
});
|
|
33
|
+
api.modifyAppData((memo) => {
|
|
34
|
+
memo.bundler = "mako";
|
|
35
|
+
return memo;
|
|
31
36
|
});
|
|
32
37
|
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { IApi } from '../../types';
|
|
2
|
+
export interface IRouteChunkFilesMap {
|
|
3
|
+
/**
|
|
4
|
+
* script attr prefix (package.json name)
|
|
5
|
+
*/
|
|
6
|
+
p: string;
|
|
7
|
+
/**
|
|
8
|
+
* bundler type
|
|
9
|
+
*/
|
|
10
|
+
b: string;
|
|
11
|
+
/**
|
|
12
|
+
* all chunk files
|
|
13
|
+
*/
|
|
14
|
+
f: [string, string | number][];
|
|
15
|
+
/**
|
|
16
|
+
* route files index map
|
|
17
|
+
*/
|
|
18
|
+
r: Record<string, number[]>;
|
|
19
|
+
}
|
|
20
|
+
declare const _default: (api: IApi) => void;
|
|
21
|
+
export default _default;
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __export = (target, all) => {
|
|
6
|
+
for (var name in all)
|
|
7
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
+
};
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
|
+
|
|
19
|
+
// src/features/routePreloadOnLoad/routePreloadOnLoad.ts
|
|
20
|
+
var routePreloadOnLoad_exports = {};
|
|
21
|
+
__export(routePreloadOnLoad_exports, {
|
|
22
|
+
default: () => routePreloadOnLoad_default
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(routePreloadOnLoad_exports);
|
|
25
|
+
var import_utils = require("@umijs/utils");
|
|
26
|
+
var import_fs = require("fs");
|
|
27
|
+
var import_path = require("path");
|
|
28
|
+
var import_constants = require("../../constants");
|
|
29
|
+
var import_scan = require("../../libs/scan");
|
|
30
|
+
var import_utils2 = require("./utils");
|
|
31
|
+
var routeScoreCache = /* @__PURE__ */ new Map();
|
|
32
|
+
function computeRouteScore(path) {
|
|
33
|
+
if (!routeScoreCache.get(path)) {
|
|
34
|
+
const paramRe = /^:[\w-]+$/;
|
|
35
|
+
const dynamicSegmentValue = 3;
|
|
36
|
+
const emptySegmentValue = 1;
|
|
37
|
+
const staticSegmentValue = 10;
|
|
38
|
+
const splatPenalty = -2;
|
|
39
|
+
const isSplat = (s) => s === "*";
|
|
40
|
+
let segments = path.split("/");
|
|
41
|
+
let initialScore = segments.length;
|
|
42
|
+
if (segments.some(isSplat)) {
|
|
43
|
+
initialScore += splatPenalty;
|
|
44
|
+
}
|
|
45
|
+
routeScoreCache.set(
|
|
46
|
+
path,
|
|
47
|
+
segments.filter((s) => !isSplat(s)).reduce(
|
|
48
|
+
(score, segment) => score + (paramRe.test(segment) ? dynamicSegmentValue : segment === "" ? emptySegmentValue : staticSegmentValue),
|
|
49
|
+
initialScore
|
|
50
|
+
)
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
return routeScoreCache.get(path);
|
|
54
|
+
}
|
|
55
|
+
async function getRouteChunkFilesMap(chunks, opts) {
|
|
56
|
+
var _a;
|
|
57
|
+
const { resolver, routeModuleName, routeModulePath } = opts;
|
|
58
|
+
const routeChunkFiles = {};
|
|
59
|
+
const routeFileChunksMap = {};
|
|
60
|
+
const pickPreloadFiles = (files) => files.filter((f) => f.endsWith(".js") || f.endsWith(".css"));
|
|
61
|
+
const routeFileResolveCache = {};
|
|
62
|
+
for (const chunk of chunks) {
|
|
63
|
+
if (chunk.entry)
|
|
64
|
+
continue;
|
|
65
|
+
const pickedFiles = pickPreloadFiles(chunk.files);
|
|
66
|
+
const routeOrigins = chunk.origins.filter(
|
|
67
|
+
(origin) => {
|
|
68
|
+
var _a2;
|
|
69
|
+
return (_a2 = origin.moduleName) == null ? void 0 : _a2.endsWith(routeModuleName);
|
|
70
|
+
}
|
|
71
|
+
);
|
|
72
|
+
for (const origin of routeOrigins) {
|
|
73
|
+
let fileAbsPath;
|
|
74
|
+
try {
|
|
75
|
+
fileAbsPath = routeFileResolveCache[_a = origin.request] ?? (routeFileResolveCache[_a] = await resolver.resolve((0, import_path.dirname)(routeModulePath), origin.request));
|
|
76
|
+
} catch (err) {
|
|
77
|
+
import_utils.logger.error(
|
|
78
|
+
`[routePreloadOnLoad]: route file resolve error, cannot preload for ${origin.request}`
|
|
79
|
+
);
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
pickedFiles.forEach((file) => {
|
|
83
|
+
routeChunkFiles[file] ?? (routeChunkFiles[file] = {
|
|
84
|
+
index: Object.keys(routeChunkFiles).length,
|
|
85
|
+
id: chunk.id
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
(routeFileChunksMap[fileAbsPath] ?? (routeFileChunksMap[fileAbsPath] = {
|
|
89
|
+
files: pickedFiles.slice()
|
|
90
|
+
})).files.push(...pickedFiles);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
Object.values(routeFileChunksMap).forEach((item) => {
|
|
94
|
+
item.indexes = item.files.map((f) => routeChunkFiles[f].index);
|
|
95
|
+
});
|
|
96
|
+
return {
|
|
97
|
+
routeChunkFiles,
|
|
98
|
+
routeFileChunksMap
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
async function getRoutePathFilesMap(routes, fileChunksMap, opts) {
|
|
102
|
+
const { resolver, absPagesPath } = opts;
|
|
103
|
+
const routeFilesMap = {};
|
|
104
|
+
for (const route of Object.values(routes)) {
|
|
105
|
+
if (!route.file)
|
|
106
|
+
continue;
|
|
107
|
+
let current = route;
|
|
108
|
+
const files = [];
|
|
109
|
+
do {
|
|
110
|
+
if (current.file && !current.file.startsWith("(")) {
|
|
111
|
+
try {
|
|
112
|
+
const fileReqPath = (0, import_path.isAbsolute)(current.file) || current.file.startsWith("@/") ? current.file : (
|
|
113
|
+
// a => ./a
|
|
114
|
+
// .a => ./.a
|
|
115
|
+
current.file.replace(/^([^.]|\.[^./])/, "./$1")
|
|
116
|
+
);
|
|
117
|
+
const fileAbsPath = await resolver.resolve(absPagesPath, fileReqPath);
|
|
118
|
+
files.push(fileAbsPath);
|
|
119
|
+
} catch {
|
|
120
|
+
import_utils.logger.error(
|
|
121
|
+
`[routePreloadOnLoad]: route file resolve error, cannot preload for ${current.file}`
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
current = current.parentId ? routes[current.parentId] : void 0;
|
|
126
|
+
} while (current);
|
|
127
|
+
const indexes = Array.from(
|
|
128
|
+
// use set to avoid duplicated indexes
|
|
129
|
+
files.reduce((indexSet, file) => {
|
|
130
|
+
var _a;
|
|
131
|
+
(_a = fileChunksMap[file]) == null ? void 0 : _a.indexes.forEach((i) => indexSet.add(i));
|
|
132
|
+
return indexSet;
|
|
133
|
+
}, /* @__PURE__ */ new Set())
|
|
134
|
+
);
|
|
135
|
+
const { absPath } = route;
|
|
136
|
+
routeFilesMap[absPath] = // why different route may has same absPath?
|
|
137
|
+
// because umi implement route.wrappers via nested routes way, the wrapper route will has same absPath with the nested route
|
|
138
|
+
// so we always select the longest file indexes for the nested route
|
|
139
|
+
!routeFilesMap[absPath] || routeFilesMap[absPath].length < indexes.length ? indexes : routeFilesMap[absPath];
|
|
140
|
+
}
|
|
141
|
+
return routeFilesMap;
|
|
142
|
+
}
|
|
143
|
+
var routePreloadOnLoad_default = (api) => {
|
|
144
|
+
let routeChunkFilesMap;
|
|
145
|
+
api.describe({
|
|
146
|
+
enableBy: () => Boolean(api.pkg.name)
|
|
147
|
+
});
|
|
148
|
+
api.addHTMLHeadScripts(() => {
|
|
149
|
+
if (api.name === "build") {
|
|
150
|
+
return api.config.tern ? (
|
|
151
|
+
// map mode
|
|
152
|
+
[
|
|
153
|
+
{
|
|
154
|
+
type: import_utils2.PRELOAD_ROUTE_MAP_SCP_TYPE,
|
|
155
|
+
content: JSON.stringify(routeChunkFilesMap)
|
|
156
|
+
}
|
|
157
|
+
]
|
|
158
|
+
) : (
|
|
159
|
+
// script mode
|
|
160
|
+
[
|
|
161
|
+
{
|
|
162
|
+
content: (0, import_fs.readFileSync)(
|
|
163
|
+
(0, import_path.join)(
|
|
164
|
+
import_constants.TEMPLATES_DIR,
|
|
165
|
+
"routePreloadOnLoad/preloadRouteFilesScp.js"
|
|
166
|
+
),
|
|
167
|
+
"utf-8"
|
|
168
|
+
).replace(
|
|
169
|
+
'"{{routeChunkFilesMap}}"',
|
|
170
|
+
JSON.stringify(routeChunkFilesMap)
|
|
171
|
+
).replace("{{basename}}", api.config.base).replace(
|
|
172
|
+
'"{{publicPath}}"',
|
|
173
|
+
`${// handle runtimePublicPath
|
|
174
|
+
api.config.runtimePublicPath ? "window.publicPath||" : ""}"${api.config.publicPath}"`
|
|
175
|
+
)
|
|
176
|
+
}
|
|
177
|
+
]
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
return [];
|
|
181
|
+
});
|
|
182
|
+
api.onBuildComplete(async ({ err, stats }) => {
|
|
183
|
+
if (!err && !stats.hasErrors()) {
|
|
184
|
+
const routeModulePath = (0, import_path.join)(api.paths.absTmpPath, "core/route.tsx");
|
|
185
|
+
const resolver = (0, import_scan.createResolver)({ alias: api.config.alias });
|
|
186
|
+
const { chunks = [] } = stats.toJson ? (
|
|
187
|
+
// webpack
|
|
188
|
+
stats.toJson()
|
|
189
|
+
) : (
|
|
190
|
+
// mako
|
|
191
|
+
stats.compilation
|
|
192
|
+
);
|
|
193
|
+
const { routeChunkFiles, routeFileChunksMap } = await getRouteChunkFilesMap(chunks, {
|
|
194
|
+
resolver,
|
|
195
|
+
routeModulePath,
|
|
196
|
+
routeModuleName: (0, import_utils.winPath)((0, import_path.relative)(api.cwd, routeModulePath))
|
|
197
|
+
});
|
|
198
|
+
const routeFilesMap = await getRoutePathFilesMap(
|
|
199
|
+
api.appData.routes,
|
|
200
|
+
routeFileChunksMap,
|
|
201
|
+
{ resolver, absPagesPath: api.paths.absPagesPath }
|
|
202
|
+
);
|
|
203
|
+
routeChunkFilesMap = {
|
|
204
|
+
p: api.pkg.name,
|
|
205
|
+
b: api.appData.bundler,
|
|
206
|
+
f: Object.entries(routeChunkFiles).sort((a, b) => a[1].index - b[1].index).map(([k, { id }]) => [k, id]),
|
|
207
|
+
// sort similar to react-router@6
|
|
208
|
+
r: (0, import_utils.lodash)(routeFilesMap).toPairs().sort(
|
|
209
|
+
([a], [b]) => computeRouteScore(a) - computeRouteScore(b)
|
|
210
|
+
).fromPairs().value()
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NOTE: DO NOT USE ADVANCED SYNTAX IN THIS FILE, TO AVOID INSERT HELPERS TO REDUCE SCRIPT SIZE.
|
|
3
|
+
*/
|
|
4
|
+
import type { IRouteChunkFilesMap } from './routePreloadOnLoad';
|
|
5
|
+
export type { IRouteChunkFilesMap };
|
|
6
|
+
export interface IPreloadRouteFile {
|
|
7
|
+
type: 'js' | 'css' | (string & {});
|
|
8
|
+
url: string;
|
|
9
|
+
attrs: ([string, string] | [string])[];
|
|
10
|
+
}
|
|
11
|
+
export declare const PRELOAD_ROUTE_MAP_SCP_TYPE = "umi-route-chunk-files-map";
|
|
12
|
+
export declare function getPreloadRouteFiles(path: string, map: IRouteChunkFilesMap, opts: {
|
|
13
|
+
publicPath: string;
|
|
14
|
+
}): IPreloadRouteFile[] | undefined;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __export = (target, all) => {
|
|
6
|
+
for (var name in all)
|
|
7
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
+
};
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
|
+
|
|
19
|
+
// src/features/routePreloadOnLoad/utils.ts
|
|
20
|
+
var utils_exports = {};
|
|
21
|
+
__export(utils_exports, {
|
|
22
|
+
PRELOAD_ROUTE_MAP_SCP_TYPE: () => PRELOAD_ROUTE_MAP_SCP_TYPE,
|
|
23
|
+
getPreloadRouteFiles: () => getPreloadRouteFiles
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(utils_exports);
|
|
26
|
+
var PRELOAD_ROUTE_MAP_SCP_TYPE = "umi-route-chunk-files-map";
|
|
27
|
+
function getPreloadRouteFiles(path, map, opts) {
|
|
28
|
+
var _a;
|
|
29
|
+
const matched = (
|
|
30
|
+
// search for static route
|
|
31
|
+
map.r[path] || // search for dynamic route
|
|
32
|
+
((_a = Object.entries(map.r).find((p) => {
|
|
33
|
+
const route = p[0];
|
|
34
|
+
const reg = new RegExp(
|
|
35
|
+
// replace /:id to /[^/]+
|
|
36
|
+
// replace /* to /.+
|
|
37
|
+
`^${route.replace(/\/:[^/]+/g, "/[^/]+").replace("/*", "/.+")}$`
|
|
38
|
+
);
|
|
39
|
+
return reg.test(path);
|
|
40
|
+
})) == null ? void 0 : _a[1])
|
|
41
|
+
);
|
|
42
|
+
return matched == null ? void 0 : matched.map((i) => {
|
|
43
|
+
const id = map.f[i][1];
|
|
44
|
+
const file = map.f[i][0];
|
|
45
|
+
const ext = file.split(".").pop();
|
|
46
|
+
return {
|
|
47
|
+
type: ext,
|
|
48
|
+
url: `${opts.publicPath}${file}`,
|
|
49
|
+
attrs: [[`data-${map.b}`, `${map.p}:${id}`]]
|
|
50
|
+
};
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
54
|
+
0 && (module.exports = {
|
|
55
|
+
PRELOAD_ROUTE_MAP_SCP_TYPE,
|
|
56
|
+
getPreloadRouteFiles
|
|
57
|
+
});
|
package/dist/index.js
CHANGED
|
@@ -86,6 +86,7 @@ var src_default = () => {
|
|
|
86
86
|
require.resolve("./features/swc/swc"),
|
|
87
87
|
require.resolve("./features/ui/ui"),
|
|
88
88
|
require.resolve("./features/hmrGuardian/hmrGuardian"),
|
|
89
|
+
require.resolve("./features/routePreloadOnLoad/routePreloadOnLoad"),
|
|
89
90
|
// commands
|
|
90
91
|
require.resolve("./commands/build"),
|
|
91
92
|
require.resolve("./commands/config/config"),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umijs/preset-umi",
|
|
3
|
-
"version": "4.1.
|
|
3
|
+
"version": "4.1.3",
|
|
4
4
|
"description": "@umijs/preset-umi",
|
|
5
5
|
"homepage": "https://github.com/umijs/umi/tree/master/packages/preset-umi#readme",
|
|
6
6
|
"bugs": "https://github.com/umijs/umi/issues",
|
|
@@ -39,21 +39,21 @@
|
|
|
39
39
|
"react-router": "6.3.0",
|
|
40
40
|
"react-router-dom": "6.3.0",
|
|
41
41
|
"regenerator-runtime": "0.13.11",
|
|
42
|
-
"@umijs/
|
|
43
|
-
"@umijs/
|
|
44
|
-
"@umijs/bundler-
|
|
45
|
-
"@umijs/bundler-
|
|
46
|
-
"@umijs/
|
|
47
|
-
"@umijs/bundler-webpack": "4.1.
|
|
48
|
-
"@umijs/
|
|
42
|
+
"@umijs/ast": "4.1.3",
|
|
43
|
+
"@umijs/babel-preset-umi": "4.1.3",
|
|
44
|
+
"@umijs/bundler-esbuild": "4.1.3",
|
|
45
|
+
"@umijs/bundler-utils": "4.1.3",
|
|
46
|
+
"@umijs/bundler-vite": "4.1.3",
|
|
47
|
+
"@umijs/bundler-webpack": "4.1.3",
|
|
48
|
+
"@umijs/core": "4.1.3",
|
|
49
|
+
"@umijs/mfsu": "4.1.3",
|
|
50
|
+
"@umijs/plugin-run": "4.1.3",
|
|
49
51
|
"@umijs/did-you-know": "1.0.3",
|
|
50
|
-
"@umijs/
|
|
51
|
-
"@umijs/
|
|
52
|
-
"@umijs/renderer-react": "4.1.2",
|
|
53
|
-
"@umijs/server": "4.1.2",
|
|
52
|
+
"@umijs/server": "4.1.3",
|
|
53
|
+
"@umijs/renderer-react": "4.1.3",
|
|
54
54
|
"@umijs/ui": "3.0.1",
|
|
55
|
-
"@umijs/utils": "4.1.
|
|
56
|
-
"@umijs/zod2ts": "4.1.
|
|
55
|
+
"@umijs/utils": "4.1.3",
|
|
56
|
+
"@umijs/zod2ts": "4.1.3"
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
59
|
"@manypkg/get-packages": "1.1.3",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
!function(){"use strict";var t="{{basename}}".replace(/([^/])$/,"$1/"),e=location.pathname,n=e.startsWith(t)&&decodeURI("/".concat(e.slice(t.length)));if(n){var a=document,c=a.head,r=a.createElement.bind(a),i=function(t,e,n){var a,c=e.r[t]||(null===(a=Object.entries(e.r).find((function(e){var n=e[0];return new RegExp("^".concat(n.replace(/\/:[^/]+/g,"/[^/]+").replace("/*","/.+"),"$")).test(t)})))||void 0===a?void 0:a[1]);return null==c?void 0:c.map((function(t){var a=e.f[t][1],c=e.f[t][0];return{type:c.split(".").pop(),url:"".concat(n.publicPath).concat(c),attrs:[["data-".concat(e.b),"".concat(e.p,":").concat(a)]]}}))}(n,"{{routeChunkFilesMap}}",{publicPath:"{{publicPath}}"});null==i||i.forEach((function(t){var e,n=t.type,a=t.url;if("js"===n)(e=r("script")).src=a,e.async=!0;else{if("css"!==n)return;(e=r("link")).href=a,e.rel="preload",e.as="style"}t.attrs.forEach((function(t){e.setAttribute(t[0],t[1]||"")})),c.appendChild(e)}))}}();
|