@umijs/preset-umi 4.0.28 → 4.0.30

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 (42) hide show
  1. package/assets/bundle-status.html +22 -0
  2. package/dist/commands/build.js +12 -5
  3. package/dist/commands/dev/createRouteMiddleware.js +2 -2
  4. package/dist/commands/dev/depBuildWorker/depBuildWorker.js +1 -1
  5. package/dist/commands/dev/depBuildWorker/depBuilder.js +3 -2
  6. package/dist/commands/dev/dev.js +16 -7
  7. package/dist/commands/dev/getAssetsMap.js +14 -2
  8. package/dist/features/404/404.js +1 -0
  9. package/dist/features/apiRoute/request.d.ts +1 -0
  10. package/dist/features/codeSplitting/codeSplitting.d.ts +3 -0
  11. package/dist/features/codeSplitting/codeSplitting.js +137 -0
  12. package/dist/features/crossorigin/crossorigin.js +1 -1
  13. package/dist/features/devTool/devTool.js +6 -4
  14. package/dist/features/exportStatic/exportStatic.js +42 -8
  15. package/dist/features/monorepo/redirect.js +3 -1
  16. package/dist/features/overrides/overrides.js +13 -15
  17. package/dist/features/polyfill/polyfill.js +2 -0
  18. package/dist/features/ssr/ssr.js +18 -8
  19. package/dist/features/ssr/webpack/webpack.d.ts +2 -0
  20. package/dist/features/ssr/webpack/webpack.js +67 -0
  21. package/dist/features/test/test.d.ts +3 -0
  22. package/dist/features/test/test.js +84 -0
  23. package/dist/features/tmpFiles/configTypes.js +11 -8
  24. package/dist/features/tmpFiles/routes.js +6 -0
  25. package/dist/features/tmpFiles/tmpFiles.js +6 -10
  26. package/dist/index.js +2 -0
  27. package/dist/libs/folderCache/AutoUpdateFolderCache.d.ts +1 -8
  28. package/dist/libs/folderCache/AutoUpdateSourceCodeCache.d.ts +2 -1
  29. package/dist/libs/folderCache/AutoUpdateSourceCodeCache.js +4 -15
  30. package/dist/libs/folderCache/FolderWatch.d.ts +18 -0
  31. package/dist/libs/folderCache/FolderWatch.js +95 -0
  32. package/dist/libs/folderCache/LazySourceCodeCache.d.ts +33 -0
  33. package/dist/libs/folderCache/LazySourceCodeCache.js +180 -0
  34. package/dist/libs/folderCache/constant.d.ts +1 -0
  35. package/dist/libs/folderCache/constant.js +41 -0
  36. package/dist/libs/folderCache/types.d.ts +9 -0
  37. package/dist/libs/folderCache/types.js +17 -0
  38. package/dist/registerMethods.js +1 -0
  39. package/dist/types.d.ts +8 -2
  40. package/package.json +13 -12
  41. package/templates/TestBrowser.tpl +79 -0
  42. package/templates/server.tpl +16 -6
@@ -15,6 +15,7 @@
15
15
  display: flex;
16
16
  align-items: center;
17
17
  justify-content: center;
18
+ flex-direction: column;
18
19
  }
19
20
 
20
21
  #loading {
@@ -82,6 +83,12 @@
82
83
  font-size: 16px;
83
84
  }
84
85
 
86
+ code.progress-details {
87
+ margin-top: 20px;
88
+ font-size: 13px;
89
+ color: #999999;
90
+ }
91
+
85
92
  @keyframes fade-in-out {
86
93
  0% {
87
94
  opacity: 0.4;
@@ -141,6 +148,7 @@
141
148
  }
142
149
  </style>
143
150
  </head>
151
+
144
152
  <body>
145
153
  <div id="loading">
146
154
  <h3>Bundling...</h3>
@@ -148,8 +156,11 @@
148
156
  <p class="summary"></p>
149
157
  <p class="detail"></p>
150
158
  </div>
159
+ <code class="progress-details"></code>
160
+
151
161
  <script>
152
162
  const loading = document.getElementById('loading');
163
+ const progressDetails = document.querySelector('.progress-details');
153
164
  const summary = loading.querySelector('.summary');
154
165
  const detail = loading.querySelector('.detail');
155
166
 
@@ -167,6 +178,17 @@
167
178
 
168
179
  function renderStatus(data) {
169
180
  const hasMFSU = Boolean(data.mfsuBundleStatus);
181
+ const hasProgressDetails = Boolean(
182
+ data.bundleStatus.progresses[0].details,
183
+ );
184
+
185
+ if (hasProgressDetails) {
186
+ const details = data.bundleStatus.progresses[0].details;
187
+ if (details.length) {
188
+ progressDetails.innerHTML = details.join('<br />');
189
+ }
190
+ }
191
+
170
192
  const srcPercent = Math.floor(
171
193
  (data.bundleStatus.done
172
194
  ? 1
@@ -69,9 +69,6 @@ umi build --clean
69
69
  await generate({
70
70
  isFirstTime: true
71
71
  });
72
- await api.applyPlugins({
73
- key: "onBeforeCompiler"
74
- });
75
72
  const {
76
73
  babelPreset,
77
74
  beforeBabelPlugins,
@@ -125,6 +122,10 @@ umi build --clean
125
122
  },
126
123
  clean: true
127
124
  };
125
+ await api.applyPlugins({
126
+ key: "onBeforeCompiler",
127
+ args: { compiler: api.config.vite ? "vite" : "webpack", opts }
128
+ });
128
129
  let stats;
129
130
  if (api.config.vite) {
130
131
  stats = await bundlerVite.build(opts);
@@ -149,8 +150,14 @@ umi build --clean
149
150
  const markupArgs = await (0, import_getMarkupArgs.getMarkupArgs)({ api });
150
151
  const finalMarkUpArgs = {
151
152
  ...markupArgs,
152
- styles: markupArgs.styles.concat(api.config.vite ? [] : assetsMap["umi.css"] || []),
153
- scripts: (api.config.vite ? [] : assetsMap["umi.js"] || []).concat(markupArgs.scripts),
153
+ styles: markupArgs.styles.concat(api.config.vite ? [] : [
154
+ ...(assetsMap["framework.css"] || []).map((src) => ({ src })),
155
+ ...(assetsMap["umi.css"] || []).map((src) => ({ src }))
156
+ ]),
157
+ scripts: (api.config.vite ? [] : [
158
+ ...(assetsMap["framework.js"] || []).map((src) => ({ src })),
159
+ ...(assetsMap["umi.js"] || []).map((src) => ({ src }))
160
+ ]).concat(markupArgs.scripts),
154
161
  esmScript: !!opts.config.esm || vite,
155
162
  path: "/"
156
163
  };
@@ -53,8 +53,8 @@ function createRouteMiddleware(opts) {
53
53
  });
54
54
  const requestHandler = await (0, import_server.createRequestHandler)({
55
55
  ...markupArgs,
56
- styles: markupArgs.styles.concat(assetsMap["umi.css"] || []),
57
- scripts: (assetsMap["umi.js"] || []).concat(markupArgs.scripts),
56
+ styles: markupArgs.styles.concat((assetsMap["umi.css"] || []).map((src) => ({ src }))),
57
+ scripts: (assetsMap["umi.js"] || []).map((src) => ({ src })).concat(markupArgs.scripts),
58
58
  esmScript: false,
59
59
  historyType: ((_a = opts.api.config.history) == null ? void 0 : _a.type) || "browser"
60
60
  });
@@ -96,7 +96,7 @@ async function start() {
96
96
  depEsBuildConfig,
97
97
  externals
98
98
  });
99
- import_utils.logger.info("[MFSU][eager] worker init, takes", Date.now() - start2);
99
+ import_utils.logger.info(`[MFSU][eager] worker init, takes ${Date.now() - start2}ms`);
100
100
  scheduleBuild();
101
101
  }
102
102
  start().catch((e) => {
@@ -36,6 +36,7 @@ var import_utils = require("@umijs/utils");
36
36
  var import_fs = require("fs");
37
37
  var import_path = require("path");
38
38
  var import_worker_threads = require("worker_threads");
39
+ var MF_ENTRY = "mf_index.js";
39
40
  var DepBuilderInWorker = class {
40
41
  constructor(opts) {
41
42
  this.completeFns = [];
@@ -131,13 +132,13 @@ var DepBuilderInWorker = class {
131
132
  const content = await dep.buildExposeContent();
132
133
  (0, import_fs.writeFileSync)((0, import_path.join)(tmpBase, dep.filePath), content, "utf-8");
133
134
  }
134
- (0, import_fs.writeFileSync)((0, import_path.join)(tmpBase, "index.js"), '"\u{1F61B}"', "utf-8");
135
+ (0, import_fs.writeFileSync)((0, import_path.join)(tmpBase, MF_ENTRY), '"\u{1F61B}"', "utf-8");
135
136
  }
136
137
  getWebpackConfig(opts) {
137
138
  var _a, _b;
138
139
  const mfName = this.opts.mfName;
139
140
  const depConfig = import_utils.lodash.cloneDeep(this.opts.depConfig);
140
- depConfig.entry = (0, import_path.join)(this.opts.tmpBase, "index.js");
141
+ depConfig.entry = (0, import_path.join)(this.opts.tmpBase, MF_ENTRY);
141
142
  depConfig.output.path = this.opts.tmpBase;
142
143
  depConfig.output.publicPath = "auto";
143
144
  depConfig.devtool = false;
@@ -30,7 +30,6 @@ var import_fs = require("fs");
30
30
  var import_path = require("path");
31
31
  var import_worker_threads = require("worker_threads");
32
32
  var import_constants = require("../../constants");
33
- var import_AutoUpdateSourceCodeCache = require("../../libs/folderCache/AutoUpdateSourceCodeCache");
34
33
  var import_lazyImportFromCurrentPkg = require("../../utils/lazyImportFromCurrentPkg");
35
34
  var import_createRouteMiddleware = require("./createRouteMiddleware");
36
35
  var import_faviconMiddleware = require("./faviconMiddleware");
@@ -38,6 +37,7 @@ var import_getBabelOpts = require("./getBabelOpts");
38
37
  var import_ViteHtmlPlugin = __toESM(require("./plugins/ViteHtmlPlugin"));
39
38
  var import_printMemoryUsage = require("./printMemoryUsage");
40
39
  var import_watch = require("./watch");
40
+ var import_LazySourceCodeCache = require("../../libs/folderCache/LazySourceCodeCache");
41
41
  var bundlerWebpack = (0, import_lazyImportFromCurrentPkg.lazyImportFromCurrentPkg)("@umijs/bundler-webpack");
42
42
  var bundlerVite = (0, import_lazyImportFromCurrentPkg.lazyImportFromCurrentPkg)("@umijs/bundler-vite");
43
43
  var MFSU_EAGER_DEFAULT_INCLUDE = [
@@ -178,9 +178,6 @@ PORT=8888 umi dev
178
178
  }
179
179
  });
180
180
  });
181
- await api.applyPlugins({
182
- key: "onBeforeCompiler"
183
- });
184
181
  const beforeMiddlewares = await api.applyPlugins({
185
182
  key: "addBeforeMiddlewares",
186
183
  initialValue: []
@@ -223,9 +220,9 @@ PORT=8888 umi dev
223
220
  let startBuildWorker = () => {
224
221
  };
225
222
  if (((_b = api.config.mfsu) == null ? void 0 : _b.strategy) === "eager") {
226
- srcCodeCache = new import_AutoUpdateSourceCodeCache.AutoUpdateSrcCodeCache({
223
+ srcCodeCache = new import_LazySourceCodeCache.LazySourceCodeCache({
227
224
  cwd: api.paths.absSrcPath,
228
- cachePath: (0, import_path.join)(api.paths.absNodeModulesPath, ".cache", "mfsu", "v4")
225
+ cachePath: (0, import_path.join)(api.paths.absNodeModulesPath, ".cache", "mfsu", "mfsu_v4")
229
226
  });
230
227
  await srcCodeCache.init();
231
228
  (0, import_watch.addUnWatch)(() => {
@@ -301,8 +298,20 @@ PORT=8888 umi dev
301
298
  ...MFSU_EAGER_DEFAULT_INCLUDE,
302
299
  ...((_e = api.config.mfsu) == null ? void 0 : _e.include) || []
303
300
  ]),
304
- startBuildWorker
301
+ startBuildWorker,
302
+ onBeforeMiddleware(app) {
303
+ api.applyPlugins({
304
+ key: "onBeforeMiddleware",
305
+ args: {
306
+ app
307
+ }
308
+ });
309
+ }
305
310
  };
311
+ await api.applyPlugins({
312
+ key: "onBeforeCompiler",
313
+ args: { compiler: enableVite ? "vite" : "webpack", opts }
314
+ });
306
315
  if (enableVite) {
307
316
  await bundlerVite.dev(opts);
308
317
  } else {
@@ -26,6 +26,10 @@ var UMI_ASSETS_REG = {
26
26
  js: /^umi(\..+)?\.js$/,
27
27
  css: /^umi(\..+)?\.css$/
28
28
  };
29
+ var FRAMEWORK_ASSETS_REG = {
30
+ js: /^framework(\..+)?\.js$/,
31
+ css: /^framework(\..+)?\.css$/
32
+ };
29
33
  var HOT_UPDATE = ".hot-update.";
30
34
  function getAssetsMap(opts) {
31
35
  const { stats, publicPath } = opts;
@@ -34,12 +38,20 @@ function getAssetsMap(opts) {
34
38
  let json = stats.toJson();
35
39
  const entrypoints = json.entrypoints || json.children[0].entrypoints;
36
40
  for (const asset of entrypoints["umi"].assets) {
37
- if (!asset.name.includes(HOT_UPDATE) && UMI_ASSETS_REG.js.test(asset.name)) {
38
- ret["umi.js"] = [`${displayPublicPath}${asset.name}`];
41
+ if (!asset.name.includes(HOT_UPDATE)) {
42
+ if (UMI_ASSETS_REG.js.test(asset.name)) {
43
+ ret["umi.js"] = [`${displayPublicPath}${asset.name}`];
44
+ }
45
+ if (FRAMEWORK_ASSETS_REG.js.test(asset.name)) {
46
+ ret["framework.js"] = [`${displayPublicPath}${asset.name}`];
47
+ }
39
48
  }
40
49
  if (UMI_ASSETS_REG.css.test(asset.name)) {
41
50
  ret["umi.css"] = [`${displayPublicPath}${asset.name}`];
42
51
  }
52
+ if (FRAMEWORK_ASSETS_REG.css.test(asset.name)) {
53
+ ret["framework.css"] = [`${displayPublicPath}${asset.name}`];
54
+ }
43
55
  }
44
56
  return ret;
45
57
  }
@@ -27,6 +27,7 @@ function patchRoutes(routes) {
27
27
  Object.keys(routes).forEach((key) => {
28
28
  if (routes[key].path === "404") {
29
29
  routes[key].path = "*";
30
+ routes[key].absPath = "/*";
30
31
  }
31
32
  });
32
33
  return routes;
@@ -1,4 +1,5 @@
1
1
  /// <reference types="node" />
2
+ /// <reference types="node" />
2
3
  import type { IncomingMessage } from 'http';
3
4
  import type { IRoute } from '../../types';
4
5
  declare class UmiApiRequest {
@@ -0,0 +1,3 @@
1
+ import { IApi } from '../../types';
2
+ declare const _default: (api: IApi) => void;
3
+ export default _default;
@@ -0,0 +1,137 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod));
20
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
21
+
22
+ // src/features/codeSplitting/codeSplitting.ts
23
+ var codeSplitting_exports = {};
24
+ __export(codeSplitting_exports, {
25
+ default: () => codeSplitting_default
26
+ });
27
+ module.exports = __toCommonJS(codeSplitting_exports);
28
+ var import_crypto = __toESM(require("crypto"));
29
+ var codeSplitting_default = (api) => {
30
+ api.describe({
31
+ key: "codeSplitting",
32
+ config: {
33
+ schema(Joi) {
34
+ return Joi.object({
35
+ jsStrategy: Joi.string().allow("bigVendors", "depPerChunk", "granularChunks"),
36
+ jsStrategyOptions: Joi.object(),
37
+ cssStrategy: Joi.string().allow("mergeAll"),
38
+ cssStrategyOptions: Joi.object()
39
+ });
40
+ }
41
+ },
42
+ enableBy: api.EnableBy.config
43
+ });
44
+ api.chainWebpack((memo) => {
45
+ if (api.env !== "production")
46
+ return;
47
+ const { jsStrategy, jsStrategyOptions, cssStrategy } = api.config.codeSplitting;
48
+ if (jsStrategy === "bigVendors") {
49
+ memo.optimization.splitChunks({
50
+ cacheGroups: {
51
+ vendors: {
52
+ test: /[\\/]node_modules[\\/]/,
53
+ priority: 10,
54
+ name: "vendors",
55
+ chunks: "async",
56
+ ...jsStrategyOptions
57
+ }
58
+ }
59
+ });
60
+ }
61
+ if (jsStrategy === "depPerChunk") {
62
+ memo.optimization.splitChunks({
63
+ cacheGroups: {
64
+ vendors: {
65
+ test: /[\\/]node_modules[\\/]/,
66
+ priority: 10,
67
+ chunks: "async",
68
+ name(module2) {
69
+ const path = module2.context.replace(/.pnpm[\\/]/, "");
70
+ const packageName = path.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1];
71
+ return `npm.${packageName.replace(/@/g, "_at_").replace(/\+/g, "_")}`;
72
+ }
73
+ }
74
+ }
75
+ });
76
+ }
77
+ if (jsStrategy === "granularChunks") {
78
+ const FRAMEWORK_BUNDLES = [
79
+ "react-dom",
80
+ "react",
81
+ "history",
82
+ "react-router",
83
+ "react-router-dom",
84
+ "scheduler"
85
+ ];
86
+ memo.optimization.splitChunks({
87
+ cacheGroups: {
88
+ default: false,
89
+ defaultVendors: false,
90
+ framework: {
91
+ name: "framework",
92
+ chunks: "all",
93
+ test: new RegExp(`[\\\\/]node_modules[\\\\/](${FRAMEWORK_BUNDLES.join(`|`)})[\\\\/]`),
94
+ priority: 40,
95
+ enforce: true
96
+ },
97
+ lib: {
98
+ test(module2) {
99
+ return module2.size() > 16e4 && /node_modules[/\\]/.test(module2.identifier());
100
+ },
101
+ name(module2) {
102
+ const rawRequest = module2.rawRequest && module2.rawRequest.replace(/^@(\w+)[/\\]/, "$1-");
103
+ if (rawRequest)
104
+ return `${rawRequest}-lib`;
105
+ const identifier = module2.identifier();
106
+ const trimmedIdentifier = /(?:^|[/\\])node_modules[/\\](.*)/.exec(identifier);
107
+ const processedIdentifier = trimmedIdentifier && trimmedIdentifier[1].replace(/^@(\w+)[/\\]/, "$1-");
108
+ return `${processedIdentifier || identifier}-lib`;
109
+ },
110
+ priority: 30,
111
+ minChunks: 1,
112
+ reuseExistingChunk: true,
113
+ chunks: "async"
114
+ },
115
+ shared: {
116
+ name(_module, chunks) {
117
+ const cryptoName = import_crypto.default.createHash("sha1").update(chunks.reduce((acc, chunk) => {
118
+ return acc + chunk.name;
119
+ }, "")).digest("base64").replace(/\//g, "");
120
+ return `shared-${cryptoName}`;
121
+ },
122
+ chunks: "async",
123
+ priority: 10,
124
+ minChunks: 2,
125
+ reuseExistingChunk: true
126
+ }
127
+ }
128
+ });
129
+ }
130
+ if (cssStrategy) {
131
+ throw new Error(`codeSplitting.cssStrategy is not supported yet`);
132
+ }
133
+ return memo;
134
+ });
135
+ };
136
+ // Annotate the CommonJS export names for ESM import in node:
137
+ 0 && (module.exports = {});
@@ -28,7 +28,7 @@ var crossorigin_default = (api) => {
28
28
  config: {
29
29
  schema(Joi) {
30
30
  return Joi.alternatives(Joi.boolean(), Joi.object({
31
- include: Joi.array().items(Joi.object().instance(RegExp))
31
+ includes: Joi.array().items(Joi.object().instance(RegExp))
32
32
  }));
33
33
  }
34
34
  },
@@ -58,13 +58,15 @@ var devTool_default = (api) => {
58
58
  });
59
59
  }
60
60
  if (shortPath === "status") {
61
- const isMFSUDone = api.config.mfsu ? (_a = api.appData.mfsuBundleStatus) == null ? void 0 : _a.done : true;
62
- const isBundleDone = (_b = api.appData.bundleStatus) == null ? void 0 : _b.done;
61
+ const isBundleDone = (_a = api.appData.bundleStatus) == null ? void 0 : _a.done;
62
+ if (enableVite && isBundleDone) {
63
+ return res.end();
64
+ }
65
+ const isMFSUDone = api.config.mfsu ? (_b = api.appData.mfsuBundleStatus) == null ? void 0 : _b.done : true;
63
66
  if (isMFSUDone && isBundleDone) {
64
67
  return res.end();
65
- } else {
66
- return res.status(400).end();
67
68
  }
69
+ return res.status(400).end();
68
70
  }
69
71
  return next();
70
72
  }
@@ -29,15 +29,18 @@ var import_path = require("path");
29
29
  var import_server = require("@umijs/server");
30
30
  var import_utils = require("@umijs/utils");
31
31
  var import_assert = __toESM(require("assert"));
32
+ var import_utils2 = require("../ssr/utils");
33
+ var markupRender;
32
34
  var IS_WIN = process.platform === "win32";
33
35
  function getExportHtmlData(routes) {
34
36
  const map = /* @__PURE__ */ new Map();
35
37
  Object.values(routes).forEach((route) => {
36
- if (!route.isLayout && (!IS_WIN || !route.path.includes("/:")) && !route.path.includes("*")) {
37
- const file = (0, import_path.join)(".", route.absPath, "index.html");
38
+ const is404 = route.absPath === "/*";
39
+ if (!route.isLayout && (!IS_WIN || !route.path.includes("/:")) && (!route.path.includes("*") || is404)) {
40
+ const file = is404 ? "404.html" : (0, import_path.join)(".", route.absPath, "index.html");
38
41
  map.set(file, {
39
42
  route: {
40
- path: route.absPath,
43
+ path: is404 ? "/404" : route.absPath,
41
44
  redirect: route.redirect
42
45
  },
43
46
  file
@@ -46,10 +49,33 @@ function getExportHtmlData(routes) {
46
49
  });
47
50
  return Array.from(map.values());
48
51
  }
52
+ async function getPreRenderedHTML(api, htmlTpl, path) {
53
+ var _a;
54
+ markupRender ?? (markupRender = require((0, import_utils2.absServerBuildPath)(api))._markupGenerator);
55
+ try {
56
+ const markup = await markupRender(path);
57
+ const [mainTpl, extraTpl] = markup.split("</html>");
58
+ const bodyContent = (_a = mainTpl.match(/<body[^>]*>([^]+?)<\/body>/)) == null ? void 0 : _a[1];
59
+ htmlTpl = htmlTpl.replace(new RegExp(`<div id="${api.config.mountElementId}"[^>]*>.*?</div>`), bodyContent).replace(/$/, `${extraTpl}`);
60
+ import_utils.logger.info(`Pre-render for ${path}`);
61
+ } catch (err) {
62
+ import_utils.logger.error(`Pre-render ${path} error: ${err}`);
63
+ }
64
+ return htmlTpl;
65
+ }
49
66
  var exportStatic_default = (api) => {
67
+ async function getRoutesFromUserExtraPaths(routePaths) {
68
+ const paths = typeof routePaths === "function" ? await routePaths() : routePaths;
69
+ return paths.reduce((acc, p) => ({
70
+ ...acc,
71
+ [p]: { id: p, absPath: p, path: p.slice(1), file: "" }
72
+ }), {});
73
+ }
50
74
  api.describe({
51
75
  config: {
52
- schema: (Joi) => Joi.object()
76
+ schema: (Joi) => Joi.object({
77
+ extraRoutePaths: Joi.alternatives(Joi.function(), Joi.array().items(Joi.string()))
78
+ })
53
79
  },
54
80
  enableBy: api.EnableBy.config
55
81
  });
@@ -57,10 +83,14 @@ var exportStatic_default = (api) => {
57
83
  (0, import_assert.default)(!api.config.mpa, "`exportStatic` is not supported in `mpa` mode.");
58
84
  });
59
85
  api.modifyExportHTMLFiles(async (_defaultFiles, opts) => {
60
- const { publicPath } = api.config;
61
- const htmlData = getExportHtmlData(api.appData.routes);
86
+ const {
87
+ publicPath,
88
+ exportStatic: { extraRoutePaths = [] }
89
+ } = api.config;
90
+ const extraHtmlData = getExportHtmlData(await getRoutesFromUserExtraPaths(extraRoutePaths));
91
+ const htmlData = getExportHtmlData(api.appData.routes).concat(extraHtmlData);
62
92
  const htmlFiles = [];
63
- for (const { file } of htmlData) {
93
+ for (const { file, route } of htmlData) {
64
94
  let { markupArgs } = opts;
65
95
  if (publicPath.startsWith(".")) {
66
96
  (0, import_assert.default)(api.config.runtimePublicPath, "`runtimePublicPath` should be enable when `publicPath` is relative!");
@@ -97,7 +127,11 @@ var exportStatic_default = (api) => {
97
127
  markupArgs = Object.assign({}, markupArgs, picked);
98
128
  }
99
129
  }
100
- htmlFiles.push({ path: file, content: await (0, import_server.getMarkup)(markupArgs) });
130
+ const htmlContent = await (0, import_server.getMarkup)(markupArgs);
131
+ htmlFiles.push({
132
+ path: file,
133
+ content: api.config.ssr ? await getPreRenderedHTML(api, htmlContent, route.path) : htmlContent
134
+ });
101
135
  }
102
136
  return htmlFiles;
103
137
  });
@@ -45,7 +45,9 @@ var redirect_default = (api) => {
45
45
  enableBy: api.EnableBy.config
46
46
  });
47
47
  api.modifyConfig(async (memo) => {
48
- const rootPkg = await (0, import_pkg_up.pkgUp)({ cwd: (0, import_path.dirname)(api.cwd) });
48
+ const rootPkg = await (0, import_pkg_up.pkgUp)({
49
+ cwd: (0, import_path.dirname)(process.env.APP_ROOT ? process.cwd() : api.cwd)
50
+ });
49
51
  if (!rootPkg)
50
52
  return memo;
51
53
  const root = (0, import_path.dirname)(rootPkg);
@@ -34,23 +34,21 @@ var overrides_default = (api) => {
34
34
  api.modifyConfig((memo) => {
35
35
  if (getOverridesCSS(api.paths.absSrcPath)) {
36
36
  memo.extraPostCSSPlugins ?? (memo.extraPostCSSPlugins = []);
37
- memo.extraPostCSSPlugins.push([
38
- require("postcss-prefix-selector")({
39
- prefix: "body",
40
- transform(_p, selector, prefixedSelector, filePath) {
41
- const isOverridesFile = (0, import_utils.winPath)(api.appData.overridesCSS[0]) === (0, import_utils.winPath)(filePath);
42
- if (isOverridesFile) {
43
- if (selector === "html") {
44
- return `html:first-child`;
45
- } else if (/^body([\s+~>[:]|$)/.test(selector)) {
46
- return `* + ${selector}`;
47
- }
48
- return prefixedSelector;
37
+ memo.extraPostCSSPlugins.push(require("postcss-prefix-selector")({
38
+ prefix: "body",
39
+ transform(_p, selector, prefixedSelector, filePath) {
40
+ const isOverridesFile = (0, import_utils.winPath)(api.appData.overridesCSS[0]) === (0, import_utils.winPath)(filePath);
41
+ if (isOverridesFile) {
42
+ if (selector === "html") {
43
+ return `html:first-child`;
44
+ } else if (/^body([\s+~>[:]|$)/.test(selector)) {
45
+ return `* + ${selector}`;
49
46
  }
50
- return selector;
47
+ return prefixedSelector;
51
48
  }
52
- })
53
- ]);
49
+ return selector;
50
+ }
51
+ }));
54
52
  }
55
53
  return memo;
56
54
  });
@@ -28,6 +28,7 @@ module.exports = __toCommonJS(polyfill_exports);
28
28
  var import_core = require("@umijs/bundler-utils/compiled/babel/core");
29
29
  var import_utils = require("@umijs/utils");
30
30
  var import_path = require("path");
31
+ var import_constants = require("@umijs/bundler-webpack/dist/constants");
31
32
  var polyfill_default = (api) => {
32
33
  api.describe({
33
34
  key: "polyfill",
@@ -74,6 +75,7 @@ export {};
74
75
  });
75
76
  api.addPolyfillImports(() => [{ source: `./core/polyfill` }]);
76
77
  api.modifyConfig((memo) => {
78
+ memo.targets || (memo.targets = import_constants.DEFAULT_BROWSER_TARGETS);
77
79
  memo.alias["regenerator-runtime"] = (0, import_path.dirname)(require.resolve("regenerator-runtime/package"));
78
80
  return memo;
79
81
  });
@@ -27,6 +27,7 @@ __export(ssr_exports, {
27
27
  module.exports = __toCommonJS(ssr_exports);
28
28
  var import_types = require("@umijs/core/dist/types");
29
29
  var import_utils = require("@umijs/utils");
30
+ var import_assert = __toESM(require("assert"));
30
31
  var import_fs = require("fs");
31
32
  var import_path = require("path");
32
33
  var import_utils2 = require("./utils");
@@ -37,7 +38,8 @@ var ssr_default = (api) => {
37
38
  schema(Joi) {
38
39
  return Joi.object({
39
40
  serverBuildPath: Joi.string(),
40
- platform: Joi.string()
41
+ platform: Joi.string(),
42
+ builder: Joi.string().allow("esbuild", "webpack")
41
43
  });
42
44
  }
43
45
  },
@@ -52,10 +54,11 @@ var ssr_default = (api) => {
52
54
  api.onStart(() => {
53
55
  import_utils.logger.warn(`SSR feature is in beta, may be unstable`);
54
56
  });
55
- api.addBeforeMiddlewares(() => [
57
+ api.addMiddlewares(() => [
56
58
  async (req, res, next) => {
57
59
  const modulePath = (0, import_utils2.absServerBuildPath)(api);
58
60
  if ((0, import_fs.existsSync)(modulePath)) {
61
+ delete require.cache[modulePath];
59
62
  (await require(modulePath)).default(req, res, next);
60
63
  } else {
61
64
  res.end("umi.server.js is compiling ...");
@@ -72,12 +75,19 @@ export { React };
72
75
  `
73
76
  });
74
77
  });
75
- api.onBeforeCompiler(async () => {
76
- const { build } = (0, import_utils.importLazy)(require.resolve("./builder/builder"));
77
- await build({
78
- api,
79
- watch: api.env === "development"
80
- });
78
+ api.onBeforeCompiler(async ({ opts }) => {
79
+ const { builder = "esbuild" } = api.config.ssr;
80
+ if (builder === "esbuild") {
81
+ const { build } = (0, import_utils.importLazy)(require.resolve("./builder/builder"));
82
+ await build({
83
+ api,
84
+ watch: api.env === "development"
85
+ });
86
+ } else if (builder === "webpack") {
87
+ (0, import_assert.default)(!api.config.vite, `The \`vite\` config is now allowed when \`ssr.builder\` is webpack!`);
88
+ const { build } = (0, import_utils.importLazy)(require.resolve("./webpack/webpack"));
89
+ await build(api, opts);
90
+ }
81
91
  });
82
92
  api.onBuildComplete(async ({ err }) => {
83
93
  if (err)
@@ -0,0 +1,2 @@
1
+ import { IApi } from '../../../types';
2
+ export declare const build: (api: IApi, opts: any) => Promise<void>;