@umijs/preset-umi 4.0.27 → 4.0.29

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.
@@ -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"] || [],
155
+ ...assetsMap["umi.css"] || []
156
+ ]),
157
+ scripts: (api.config.vite ? [] : [
158
+ ...assetsMap["framework.js"] || [],
159
+ ...assetsMap["umi.js"] || []
160
+ ]).concat(markupArgs.scripts),
154
161
  esmScript: !!opts.config.esm || vite,
155
162
  path: "/"
156
163
  };
@@ -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: []
@@ -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,5 +1,4 @@
1
1
  /// <reference types="node" />
2
- /// <reference types="node" />
3
2
  import type { IncomingMessage } from 'http';
4
3
  import type { IRoute } from '../../types';
5
4
  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 = {});
@@ -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,12 +29,14 @@ 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
+ if (!route.isLayout && (!IS_WIN || !route.path.includes("/:")) && (!route.path.includes("*") || route.absPath === "/*")) {
39
+ const file = route.absPath === "/*" ? "404.html" : (0, import_path.join)(".", route.absPath, "index.html");
38
40
  map.set(file, {
39
41
  route: {
40
42
  path: route.absPath,
@@ -46,10 +48,33 @@ function getExportHtmlData(routes) {
46
48
  });
47
49
  return Array.from(map.values());
48
50
  }
51
+ async function getPreRenderedHTML(api, htmlTpl, path) {
52
+ var _a;
53
+ markupRender ?? (markupRender = require((0, import_utils2.absServerBuildPath)(api))._markupGenerator);
54
+ try {
55
+ const markup = await markupRender(path);
56
+ const [mainTpl, extraTpl] = markup.split("</html>");
57
+ const bodyContent = (_a = mainTpl.match(/<body[^>]*>([^]+?)<\/body>/)) == null ? void 0 : _a[1];
58
+ htmlTpl = htmlTpl.replace(new RegExp(`<div id="${api.config.mountElementId}"[^>]*>.*?</div>`), bodyContent).replace(/$/, `${extraTpl}`);
59
+ import_utils.logger.info(`Pre-render for ${path}`);
60
+ } catch (err) {
61
+ import_utils.logger.error(`Pre-render ${path} error: ${err}`);
62
+ }
63
+ return htmlTpl;
64
+ }
49
65
  var exportStatic_default = (api) => {
66
+ async function getRoutesFromUserExtraPaths(routePaths) {
67
+ const paths = typeof routePaths === "function" ? await routePaths() : routePaths;
68
+ return paths.reduce((acc, p) => ({
69
+ ...acc,
70
+ [p]: { id: p, absPath: p, path: p.slice(1), file: "" }
71
+ }), {});
72
+ }
50
73
  api.describe({
51
74
  config: {
52
- schema: (Joi) => Joi.object()
75
+ schema: (Joi) => Joi.object({
76
+ extraRoutePaths: Joi.alternatives(Joi.function(), Joi.array().items(Joi.string()))
77
+ })
53
78
  },
54
79
  enableBy: api.EnableBy.config
55
80
  });
@@ -57,10 +82,14 @@ var exportStatic_default = (api) => {
57
82
  (0, import_assert.default)(!api.config.mpa, "`exportStatic` is not supported in `mpa` mode.");
58
83
  });
59
84
  api.modifyExportHTMLFiles(async (_defaultFiles, opts) => {
60
- const { publicPath } = api.config;
61
- const htmlData = getExportHtmlData(api.appData.routes);
85
+ const {
86
+ publicPath,
87
+ exportStatic: { extraRoutePaths = [] }
88
+ } = api.config;
89
+ const extraHtmlData = getExportHtmlData(await getRoutesFromUserExtraPaths(extraRoutePaths));
90
+ const htmlData = getExportHtmlData(api.appData.routes).concat(extraHtmlData);
62
91
  const htmlFiles = [];
63
- for (const { file } of htmlData) {
92
+ for (const { file, route } of htmlData) {
64
93
  let { markupArgs } = opts;
65
94
  if (publicPath.startsWith(".")) {
66
95
  (0, import_assert.default)(api.config.runtimePublicPath, "`runtimePublicPath` should be enable when `publicPath` is relative!");
@@ -97,7 +126,11 @@ var exportStatic_default = (api) => {
97
126
  markupArgs = Object.assign({}, markupArgs, picked);
98
127
  }
99
128
  }
100
- htmlFiles.push({ path: file, content: await (0, import_server.getMarkup)(markupArgs) });
129
+ const htmlContent = await (0, import_server.getMarkup)(markupArgs);
130
+ htmlFiles.push({
131
+ path: file,
132
+ content: api.config.ssr ? await getPreRenderedHTML(api, htmlContent, route.path) : htmlContent
133
+ });
101
134
  }
102
135
  return htmlFiles;
103
136
  });
@@ -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>;
@@ -0,0 +1,67 @@
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/ssr/webpack/webpack.ts
23
+ var webpack_exports = {};
24
+ __export(webpack_exports, {
25
+ build: () => build2
26
+ });
27
+ module.exports = __toCommonJS(webpack_exports);
28
+ var import_utils = require("@umijs/utils");
29
+ var bundlerWebpack = __toESM(require("@umijs/bundler-webpack"));
30
+ var import_utils2 = require("../utils");
31
+ var import_path = require("path");
32
+ var build2 = async (api, opts) => {
33
+ import_utils.logger.wait("[SSR] Compiling...");
34
+ const now = new Date().getTime();
35
+ const bundlerOpts = import_utils.lodash.cloneDeep(opts);
36
+ const oChainWebpack = bundlerOpts.chainWebpack;
37
+ delete bundlerOpts.config.deadCode;
38
+ bundlerOpts.extraBabelPlugins.push([
39
+ require.resolve("babel-plugin-dynamic-import-node"),
40
+ {},
41
+ "umi-server-dynamic-import-node"
42
+ ]);
43
+ delete bundlerOpts.onBuildComplete;
44
+ bundlerOpts.chainWebpack = async (memo) => {
45
+ const absOutputFile = (0, import_utils2.absServerBuildPath)(api);
46
+ await oChainWebpack(memo);
47
+ memo.entryPoints.clear();
48
+ memo.entry("umi").add((0, import_path.resolve)(api.paths.absTmpPath, "umi.server.ts"));
49
+ memo.target("node");
50
+ memo.name("umi");
51
+ memo.devtool(false);
52
+ memo.output.path((0, import_path.dirname)(absOutputFile)).filename("umi.server.js").chunkFilename("[name].server.js").libraryTarget("commonjs2");
53
+ memo.plugins.delete("progress-plugin");
54
+ memo.optimization.minimize(false);
55
+ if (api.env === "development") {
56
+ memo.watch(true);
57
+ }
58
+ return memo;
59
+ };
60
+ await bundlerWebpack.build(bundlerOpts);
61
+ const diff = new Date().getTime() - now;
62
+ import_utils.logger.info(`[SSR] Compiled in ${diff}ms`);
63
+ };
64
+ // Annotate the CommonJS export names for ESM import in node:
65
+ 0 && (module.exports = {
66
+ build
67
+ });
@@ -0,0 +1,3 @@
1
+ import { IApi } from '../../types';
2
+ declare const _default: (api: IApi) => void;
3
+ export default _default;
@@ -0,0 +1,90 @@
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/test/test.ts
23
+ var test_exports = {};
24
+ __export(test_exports, {
25
+ default: () => test_default
26
+ });
27
+ module.exports = __toCommonJS(test_exports);
28
+ var import_utils = require("@umijs/utils");
29
+ var import_fs = require("fs");
30
+ var import_path = require("path");
31
+ var import_constants = require("../../constants");
32
+ var import_importsToStr = require("../tmpFiles/importsToStr");
33
+ var test_default = (api) => {
34
+ api.describe({
35
+ key: "test",
36
+ config: {
37
+ schema(Joi) {
38
+ return Joi.object();
39
+ }
40
+ },
41
+ enableBy() {
42
+ if (process.env.NODE_ENV === "test") {
43
+ return true;
44
+ }
45
+ return false;
46
+ }
47
+ });
48
+ api.onGenerateFiles(async () => {
49
+ const rendererPath = (0, import_utils.winPath)(await api.applyPlugins({
50
+ key: "modifyRendererPath",
51
+ initialValue: (0, import_path.dirname)(require.resolve("@umijs/renderer-react/package.json"))
52
+ }));
53
+ api.writeTmpFile({
54
+ noPluginDir: true,
55
+ path: "testBrowser.tsx",
56
+ tplPath: (0, import_path.join)(import_constants.TEMPLATES_DIR, "TestBrowser.tpl"),
57
+ context: {
58
+ mountElementId: api.config.mountElementId,
59
+ rendererPath,
60
+ publicPath: api.config.publicPath,
61
+ runtimePublicPath: api.config.runtimePublicPath ? "true" : "false",
62
+ polyfillImports: (0, import_importsToStr.importsToStr)(await api.applyPlugins({
63
+ key: "addPolyfillImports",
64
+ initialValue: []
65
+ })).join("\n"),
66
+ importsAhead: (0, import_importsToStr.importsToStr)(await api.applyPlugins({
67
+ key: "addEntryImportsAhead",
68
+ initialValue: [
69
+ api.appData.globalCSS.length && {
70
+ source: api.appData.globalCSS[0]
71
+ },
72
+ api.appData.globalJS.length && {
73
+ source: api.appData.globalJS[0]
74
+ }
75
+ ].filter(Boolean)
76
+ })).join("\n"),
77
+ imports: (0, import_importsToStr.importsToStr)(await api.applyPlugins({
78
+ key: "addEntryImports",
79
+ initialValue: []
80
+ })).join("\n"),
81
+ basename: api.config.base,
82
+ historyType: api.config.history.type,
83
+ hydrate: !!api.config.ssr,
84
+ loadingComponent: (0, import_fs.existsSync)((0, import_path.join)(api.paths.absSrcPath, "loading.tsx")) || (0, import_fs.existsSync)((0, import_path.join)(api.paths.absSrcPath, "loading.jsx")) || (0, import_fs.existsSync)((0, import_path.join)(api.paths.absSrcPath, "loading.js"))
85
+ }
86
+ });
87
+ });
88
+ };
89
+ // Annotate the CommonJS export names for ESM import in node:
90
+ 0 && (module.exports = {});
@@ -27,24 +27,27 @@ __export(configTypes_exports, {
27
27
  module.exports = __toCommonJS(configTypes_exports);
28
28
  var import_joi = __toESM(require("@umijs/utils/compiled/@hapi/joi"));
29
29
  var import_joi2types = __toESM(require("../../../compiled/joi2types"));
30
+ var FILTER_KEYS = ["chainWebpack"];
30
31
  var configTypes_default = (api) => {
31
32
  api.onGenerateFiles(async () => {
32
33
  const { service } = api;
33
- const properties = Object.keys(service.configSchemas).map((key) => {
34
+ const properties = Object.keys(service.configSchemas).reduce((acc, key) => {
35
+ if (FILTER_KEYS.includes(key)) {
36
+ return acc;
37
+ }
34
38
  const schemaFn = service.configSchemas[key];
35
- if (typeof schemaFn !== "function")
36
- return;
39
+ if (typeof schemaFn !== "function") {
40
+ return acc;
41
+ }
37
42
  const schema = schemaFn(import_joi.default);
38
43
  if (!import_joi.default.isSchema(schema)) {
39
- return;
44
+ return acc;
40
45
  }
41
46
  return {
47
+ ...acc,
42
48
  [key]: schema
43
49
  };
44
- }).reduce((acc, curr) => ({
45
- ...acc,
46
- ...curr
47
- }), {});
50
+ }, {});
48
51
  const interfaceName = "IConfigFromPlugins";
49
52
  const content = await (0, import_joi2types.default)(import_joi.default.object(properties), {
50
53
  interfaceName,
@@ -176,6 +176,9 @@ async function getRouteComponents(opts) {
176
176
  const useSuspense = opts.api.appData.framework === "react" ? true : false;
177
177
  const route = opts.routes[key];
178
178
  if (!route.file) {
179
+ if (process.env.NODE_ENV === "test") {
180
+ return `'${key}': require( './EmptyRoute').default,`;
181
+ }
179
182
  return useSuspense ? `'${key}': React.lazy(() => import( './EmptyRoute')),` : `'${key}': () => import( './EmptyRoute'),`;
180
183
  }
181
184
  if (route.hasClientLoader) {
@@ -188,6 +191,9 @@ async function getRouteComponents(opts) {
188
191
  }
189
192
  const path = (0, import_path.isAbsolute)(route.file) || route.file.startsWith("@/") ? route.file : `${opts.prefix}${route.file}`;
190
193
  const webpackChunkName = componentToChunkName(path, opts.api.cwd);
194
+ if (process.env.NODE_ENV === "test") {
195
+ return `'${key}': require('${(0, import_utils.winPath)(path)}').default,`;
196
+ }
191
197
  return useSuspense ? `'${key}': React.lazy(() => import(/* webpackChunkName: "${webpackChunkName}" */'${(0, import_utils.winPath)(path)}')),` : `'${key}': () => import(/* webpackChunkName: "${webpackChunkName}" */'${(0, import_utils.winPath)(path)}'),`;
192
198
  }).join("\n");
193
199
  return `{
package/dist/index.js CHANGED
@@ -34,6 +34,7 @@ var src_default = () => {
34
34
  require.resolve("./features/appData/appData"),
35
35
  require.resolve("./features/check/check"),
36
36
  require.resolve("./features/clientLoader/clientLoader"),
37
+ require.resolve("./features/codeSplitting/codeSplitting"),
37
38
  require.resolve("./features/configPlugins/configPlugins"),
38
39
  require.resolve("./features/crossorigin/crossorigin"),
39
40
  require.resolve("./features/depsOnDemand/depsOnDemand"),
@@ -56,6 +57,7 @@ var src_default = () => {
56
57
  require.resolve("./features/vite/vite"),
57
58
  require.resolve("./features/apiRoute/apiRoute"),
58
59
  require.resolve("./features/monorepo/redirect"),
60
+ require.resolve("./features/test/test"),
59
61
  require.resolve("./features/clickToComponent/clickToComponent"),
60
62
  require.resolve("./features/legacy/legacy"),
61
63
  require.resolve("./features/classPropertiesLoose/classPropertiesLoose"),
@@ -60,7 +60,7 @@ var AutoUpdateSrcCodeCache = class {
60
60
  await this.batchProcess(files);
61
61
  for (const f of files) {
62
62
  let newFile = (0, import_path.join)(this.cachePath, (0, import_path.relative)(this.srcPath, f));
63
- newFile = newFile.replace((0, import_path.extname)(newFile), ".js");
63
+ newFile = newFile.replace(new RegExp(`${(0, import_path.extname)(newFile)}$`), ".js");
64
64
  loaded[f] = (0, import_fs.readFileSync)(newFile, "utf-8");
65
65
  }
66
66
  return loaded;
@@ -94,7 +94,7 @@ var AutoUpdateSrcCodeCache = class {
94
94
  outdir: this.cachePath,
95
95
  outbase: this.srcPath,
96
96
  loader: {
97
- ".js": "jsx",
97
+ ".js": "tsx",
98
98
  ".jsx": "tsx"
99
99
  },
100
100
  logLevel: "error"
@@ -44,6 +44,7 @@ var registerMethods_default = (api) => {
44
44
  "onCheckPkgJSON",
45
45
  "onCheckCode",
46
46
  "onCheckConfig",
47
+ "onBeforeMiddleware",
47
48
  "addBeforeMiddlewares",
48
49
  "addLayouts",
49
50
  "addMiddlewares",
package/dist/types.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { ImportDeclaration } from '@umijs/bundler-utils/compiled/@babel/types';
2
- import type { RequestHandler, webpack } from '@umijs/bundler-webpack';
2
+ import type { RequestHandler, webpack, Express } from '@umijs/bundler-webpack';
3
3
  import type WebpackChain from '@umijs/bundler-webpack/compiled/webpack-5-chain';
4
4
  import type { IConfig } from '@umijs/bundler-webpack/dist/types';
5
5
  import type { IAdd, IEvent, IModify, IRoute as ICoreRoute, IServicePluginAPI, PluginAPI } from '@umijs/core';
@@ -114,7 +114,13 @@ export declare type IApi = PluginAPI & IServicePluginAPI & {
114
114
  env: Env;
115
115
  webpack: typeof webpack;
116
116
  }>;
117
- onBeforeCompiler: IEvent<{}>;
117
+ onBeforeCompiler: IEvent<{
118
+ compiler: 'vite' | 'webpack';
119
+ opts: any;
120
+ }>;
121
+ onBeforeMiddleware: IEvent<{
122
+ app: Express;
123
+ }>;
118
124
  onBuildComplete: IEvent<{
119
125
  err?: Error;
120
126
  isFirstCompile: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umijs/preset-umi",
3
- "version": "4.0.27",
3
+ "version": "4.0.29",
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",
@@ -25,19 +25,20 @@
25
25
  "test": "umi-scripts jest-turbo"
26
26
  },
27
27
  "dependencies": {
28
- "@umijs/ast": "4.0.27",
29
- "@umijs/babel-preset-umi": "4.0.27",
30
- "@umijs/bundler-utils": "4.0.27",
31
- "@umijs/bundler-vite": "4.0.27",
32
- "@umijs/bundler-webpack": "4.0.27",
33
- "@umijs/core": "4.0.27",
28
+ "@umijs/ast": "4.0.29",
29
+ "@umijs/babel-preset-umi": "4.0.29",
30
+ "@umijs/bundler-utils": "4.0.29",
31
+ "@umijs/bundler-vite": "4.0.29",
32
+ "@umijs/bundler-webpack": "4.0.29",
33
+ "@umijs/core": "4.0.29",
34
34
  "@umijs/did-you-know": "^1.0.0",
35
35
  "@umijs/history": "5.3.1",
36
- "@umijs/mfsu": "4.0.27",
37
- "@umijs/plugin-run": "4.0.27",
38
- "@umijs/renderer-react": "4.0.27",
39
- "@umijs/server": "4.0.27",
40
- "@umijs/utils": "4.0.27",
36
+ "@umijs/mfsu": "4.0.29",
37
+ "@umijs/plugin-run": "4.0.29",
38
+ "@umijs/renderer-react": "4.0.29",
39
+ "@umijs/server": "4.0.29",
40
+ "@umijs/utils": "4.0.29",
41
+ "babel-plugin-dynamic-import-node": "2.3.3",
41
42
  "click-to-react-component": "^1.0.8",
42
43
  "core-js": "3.22.4",
43
44
  "current-script-polyfill": "1.0.0",
@@ -0,0 +1,79 @@
1
+ import React, { useEffect, useState } from 'react';
2
+ import { ApplyPluginsType } from 'umi';
3
+ import { renderClient, RenderClientOpts } from '{{{ rendererPath }}}';
4
+ import { createHistory } from './core/history';
5
+ import { createPluginManager } from './core/plugin';
6
+ import { getRoutes } from './core/route';
7
+ import type { Location } from 'history';
8
+ {{{ polyfillImports }}}
9
+ {{{ importsAhead }}}
10
+
11
+ const publicPath = '/';
12
+ const runtimePublicPath = false;
13
+
14
+ type TestBrowserProps = {
15
+ location?: Location;
16
+ historyRef?: any;
17
+ };
18
+
19
+ export function TestBrowser(props: TestBrowserProps) {
20
+ const pluginManager = createPluginManager();
21
+ const [context, setContext] = useState<RenderClientOpts | undefined>(
22
+ undefined,
23
+ );
24
+ useEffect(() => {
25
+ const genContext = async () => {
26
+ const { routes, routeComponents } = await getRoutes(pluginManager);
27
+ // allow user to extend routes
28
+ await pluginManager.applyPlugins({
29
+ key: 'patchRoutes',
30
+ type: ApplyPluginsType.event,
31
+ args: {
32
+ routes,
33
+ routeComponents,
34
+ },
35
+ });
36
+ const contextOpts = pluginManager.applyPlugins({
37
+ key: 'modifyContextOpts',
38
+ type: ApplyPluginsType.modify,
39
+ initialValue: {},
40
+ });
41
+ const basename = contextOpts.basename || '/';
42
+ const history = createHistory({
43
+ type: 'memory',
44
+ basename,
45
+ });
46
+ return {
47
+ routes,
48
+ routeComponents,
49
+ pluginManager,
50
+ rootElement: contextOpts.rootElement || document.getElementById('root'),
51
+ publicPath,
52
+ runtimePublicPath,
53
+ history,
54
+ basename,
55
+ components: true
56
+ };
57
+ };
58
+ genContext().then((context) => {
59
+ setContext(context);
60
+ if (props.location) {
61
+ context?.history?.push(props.location);
62
+ }
63
+ if (props.historyRef) {
64
+ props.historyRef.current = context?.history;
65
+ }
66
+ });
67
+ }, []);
68
+
69
+ if (context === undefined) {
70
+ return <div id="loading" />;
71
+ }
72
+
73
+ const Children = renderClient(context);
74
+ return (
75
+ <React.Fragment>
76
+ <Children />
77
+ </React.Fragment>
78
+ );
79
+ }
@@ -1,7 +1,9 @@
1
1
  import { getClientRootComponent } from '{{{ serverRendererPath }}}';
2
2
  import { getRoutes } from './core/route';
3
+ import { createHistory as createClientHistory } from './core/history';
4
+ import { getPlugins as getClientPlugins } from './core/plugin';
3
5
  import { PluginManager } from '{{{ umiPluginPath }}}';
4
- import createRequestHandler from '{{{ umiServerPath }}}';
6
+ import createRequestHandler, { createMarkupGenerator } from '{{{ umiServerPath }}}';
5
7
 
6
8
  const routesWithServerLoader = {
7
9
  {{#routesWithServerLoader}}
@@ -9,9 +11,8 @@ const routesWithServerLoader = {
9
11
  {{/routesWithServerLoader}}
10
12
  };
11
13
 
12
- // TODO: support runtime plugins
13
14
  export function getPlugins() {
14
- return [];
15
+ return getClientPlugins();
15
16
  }
16
17
 
17
18
  export function getValidKeys() {
@@ -22,6 +23,10 @@ export function getManifest() {
22
23
  return JSON.parse(require('fs').readFileSync('{{{ assetsPath }}}', 'utf-8'));
23
24
  }
24
25
 
26
+ export function createHistory(opts) {
27
+ return createClientHistory(opts);
28
+ }
29
+
25
30
  // TODO: remove global variable
26
31
  global.g_getAssets = (fileName) => {
27
32
  let m = typeof manifest === 'function' ? manifest() : manifest;
@@ -29,7 +34,7 @@ global.g_getAssets = (fileName) => {
29
34
  };
30
35
 
31
36
  const manifest = {{{ env }}} === 'development' ? getManifest : getManifest();
32
- const requestHandler = createRequestHandler({
37
+ const createOpts = {
33
38
  routesWithServerLoader,
34
39
  PluginManager,
35
40
  getPlugins,
@@ -37,6 +42,10 @@ const requestHandler = createRequestHandler({
37
42
  getRoutes,
38
43
  manifest,
39
44
  getClientRootComponent,
40
- });
45
+ createHistory,
46
+ };
47
+ const requestHandler = createRequestHandler(createOpts);
48
+
49
+ export const _markupGenerator = createMarkupGenerator(createOpts);
41
50
 
42
51
  export default requestHandler;