@umijs/plugins 4.0.0-rc.14 → 4.0.0-rc.17

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/access.js CHANGED
@@ -1,13 +1,4 @@
1
1
  "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
12
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
4
  };
@@ -24,7 +15,7 @@ exports.default = (api) => {
24
15
  },
25
16
  enableBy: api.EnableBy.config,
26
17
  });
27
- api.onGenerateFiles(() => __awaiter(void 0, void 0, void 0, function* () {
18
+ api.onGenerateFiles(async () => {
28
19
  // allow enable access without access file
29
20
  const hasAccessFile = ['js', 'jsx', 'ts', 'tsx'].some((ext) => fs_1.default.existsSync((0, path_1.join)(api.paths.absSrcPath, `access.${ext}`)));
30
21
  // runtime.tsx
@@ -137,7 +128,7 @@ import React from 'react';
137
128
  export const AccessContext = React.createContext<any>(null);
138
129
  `,
139
130
  });
140
- }));
131
+ });
141
132
  api.addRuntimePlugin(() => {
142
133
  return [(0, withTmpPath_1.withTmpPath)({ api, path: 'runtime.tsx' })];
143
134
  });
package/dist/antd.js CHANGED
@@ -30,7 +30,12 @@ exports.default = (api) => {
30
30
  });
31
31
  },
32
32
  },
33
- enableBy: api.EnableBy.config,
33
+ enableBy({ userConfig }) {
34
+ // 由于本插件有 api.modifyConfig 的调用,以及 Umi 框架的限制
35
+ // 在其他插件中通过 api.modifyDefaultConfig 设置 antd 并不能让 api.modifyConfig 生效
36
+ // 所以这里通过环境变量来判断是否启用
37
+ return process.env.UMI_PLUGIN_ANTD_ENABLE || userConfig.antd;
38
+ },
34
39
  });
35
40
  function checkPkgPath() {
36
41
  if (!pkgPath) {
@@ -48,21 +53,31 @@ exports.default = (api) => {
48
53
  });
49
54
  api.modifyConfig((memo) => {
50
55
  checkPkgPath();
56
+ const antd = memo.antd || {};
57
+ // defaultConfig 的取值在 config 之后,所以改用环境变量传默认值
58
+ if (process.env.UMI_PLUGIN_ANTD_ENABLE) {
59
+ const { defaultConfig } = JSON.parse(process.env.UMI_PLUGIN_ANTD_ENABLE);
60
+ Object.assign(antd, defaultConfig);
61
+ }
51
62
  // antd import
52
63
  memo.alias.antd = pkgPath;
53
64
  // moment > dayjs
54
- if (memo.antd.dayjs) {
65
+ if (antd.dayjs) {
55
66
  memo.alias.moment = (0, path_1.dirname)(require.resolve('dayjs/package.json'));
56
67
  }
57
68
  // dark mode & compact mode
58
- if (memo.antd.dark || memo.antd.compact) {
69
+ if (antd.dark || antd.compact) {
59
70
  const { getThemeVariables } = require('antd/dist/theme');
60
- memo.theme = Object.assign(Object.assign({}, getThemeVariables(memo.antd)), memo.theme);
71
+ memo.theme = {
72
+ ...getThemeVariables(antd),
73
+ ...memo.theme,
74
+ };
61
75
  }
62
- return memo;
63
- });
64
- api.modifyConfig((memo) => {
65
- memo.theme = Object.assign({ 'root-entry-name': 'default' }, memo.theme);
76
+ // antd theme
77
+ memo.theme = {
78
+ 'root-entry-name': 'default',
79
+ ...memo.theme,
80
+ };
66
81
  return memo;
67
82
  });
68
83
  // babel-plugin-import
package/dist/layout.js CHANGED
@@ -39,7 +39,7 @@ exports.default = (api) => {
39
39
  schema(joi) {
40
40
  return joi.object();
41
41
  },
42
- // onChange: api.ConfigChangeType.regenerateTmpFiles,
42
+ onChange: api.ConfigChangeType.regenerateTmpFiles,
43
43
  },
44
44
  enableBy: api.EnableBy.config,
45
45
  });
@@ -137,7 +137,8 @@ const { formatMessage } = useIntl();
137
137
  }
138
138
  if (menuItemProps.path && location.pathname !== menuItemProps.path) {
139
139
  return (
140
- <Link to={menuItemProps.path} target={menuItemProps.target}>
140
+ // handle wildcard route path, for example /slave/* from qiankun
141
+ <Link to={menuItemProps.path.replace('/*', '')} target={menuItemProps.target}>
141
142
  {defaultDom}
142
143
  </Link>
143
144
  );
package/dist/locale.js CHANGED
@@ -1,13 +1,4 @@
1
1
  "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
2
  Object.defineProperty(exports, "__esModule", { value: true });
12
3
  exports.packageNormalize = void 0;
13
4
  const fs_1 = require("fs");
@@ -58,9 +49,9 @@ exports.default = (api) => {
58
49
  },
59
50
  ]
60
51
  : []);
61
- const addAntdLocales = (args) => __awaiter(void 0, void 0, void 0, function* () {
52
+ const addAntdLocales = async (args) => {
62
53
  var _a;
63
- return yield api.applyPlugins({
54
+ return await api.applyPlugins({
64
55
  key: 'addAntdLocales',
65
56
  type: api.ApplyPluginsType.add,
66
57
  initialValue: [
@@ -68,29 +59,32 @@ exports.default = (api) => {
68
59
  ],
69
60
  args,
70
61
  });
71
- });
72
- const getList = (resolveKey) => __awaiter(void 0, void 0, void 0, function* () {
73
- var _b;
62
+ };
63
+ const getList = async (resolveKey) => {
64
+ var _a;
74
65
  const { paths } = api;
75
66
  return (0, localeUtils_1.getLocaleList)({
76
67
  localeFolder: 'locales',
77
- separator: (_b = api.config.locale) === null || _b === void 0 ? void 0 : _b.baseSeparator,
68
+ separator: (_a = api.config.locale) === null || _a === void 0 ? void 0 : _a.baseSeparator,
78
69
  absSrcPath: paths.absSrcPath,
79
70
  absPagesPath: paths.absPagesPath,
80
71
  addAntdLocales,
81
72
  resolveKey,
82
73
  });
83
- });
84
- api.onGenerateFiles(() => __awaiter(void 0, void 0, void 0, function* () {
85
- var _c, _d, _e, _f;
74
+ };
75
+ api.onGenerateFiles(async () => {
76
+ var _a, _b, _c, _d;
86
77
  const localeTpl = (0, fs_1.readFileSync)((0, path_1.join)(__dirname, '../libs/locale/locale.tpl'), 'utf-8');
87
78
  // moment2dayjs
88
79
  const resolveKey = api.config.moment2dayjs ? 'dayjs' : 'moment';
89
80
  const momentPkgPath = (0, plugin_utils_1.winPath)((0, path_1.dirname)(require.resolve(`${resolveKey}/package.json`)));
90
81
  const EventEmitterPkg = (0, plugin_utils_1.winPath)((0, path_1.dirname)(require.resolve('event-emitter/package')));
91
- const { baseSeparator, baseNavigator, antd, title, useLocalStorage } = Object.assign(Object.assign({}, defaultConfig), api.config.locale);
92
- const defaultLocale = ((_c = api.config.locale) === null || _c === void 0 ? void 0 : _c.default) || `zh${baseSeparator}CN`;
93
- const localeList = yield getList(resolveKey);
82
+ const { baseSeparator, baseNavigator, antd, title, useLocalStorage } = {
83
+ ...defaultConfig,
84
+ ...api.config.locale,
85
+ };
86
+ const defaultLocale = ((_a = api.config.locale) === null || _a === void 0 ? void 0 : _a.default) || `zh${baseSeparator}CN`;
87
+ const localeList = await getList(resolveKey);
94
88
  const momentLocales = localeList
95
89
  .map(({ momentLocale }) => momentLocale)
96
90
  .filter((locale) => locale);
@@ -100,7 +94,7 @@ exports.default = (api) => {
100
94
  let MomentLocales = momentLocales;
101
95
  let DefaultMomentLocale = '';
102
96
  // set moment default accounding to locale.default
103
- if (!MomentLocales.length && ((_d = api.config.locale) === null || _d === void 0 ? void 0 : _d.default)) {
97
+ if (!MomentLocales.length && ((_b = api.config.locale) === null || _b === void 0 ? void 0 : _b.default)) {
104
98
  const [lang, country = ''] = defaultLocale.split(baseSeparator);
105
99
  const { momentLocale } = (0, localeUtils_1.getMomentLocale)(lang, country, resolveKey);
106
100
  if (momentLocale) {
@@ -110,9 +104,9 @@ exports.default = (api) => {
110
104
  }
111
105
  let DefaultAntdLocales = [];
112
106
  // set antd default locale
113
- if (!antdLocales.length && ((_e = api.config.locale) === null || _e === void 0 ? void 0 : _e.antd)) {
107
+ if (!antdLocales.length && ((_c = api.config.locale) === null || _c === void 0 ? void 0 : _c.antd)) {
114
108
  const [lang, country = ''] = defaultLocale.split(baseSeparator);
115
- DefaultAntdLocales = plugin_utils_1.lodash.uniq(yield addAntdLocales({
109
+ DefaultAntdLocales = plugin_utils_1.lodash.uniq(await addAntdLocales({
116
110
  lang,
117
111
  country,
118
112
  }));
@@ -148,13 +142,17 @@ exports.default = (api) => {
148
142
  UseLocalStorage: !!useLocalStorage,
149
143
  LocaleDir: localeDirName,
150
144
  ExistLocaleDir: (0, fs_1.existsSync)(localeDirPath),
151
- LocaleList: localeList.map((locale) => (Object.assign(Object.assign({}, locale), { antdLocale: locale.antdLocale.map((antdLocale, index) => ({
145
+ LocaleList: localeList.map((locale) => ({
146
+ ...locale,
147
+ antdLocale: locale.antdLocale.map((antdLocale, index) => ({
152
148
  locale: antdLocale,
153
149
  index: index,
154
- })), paths: locale.paths.map((path, index) => ({
150
+ })),
151
+ paths: locale.paths.map((path, index) => ({
155
152
  path,
156
153
  index,
157
- })) }))),
154
+ })),
155
+ })),
158
156
  Antd: !!antd,
159
157
  DefaultLocale: JSON.stringify(defaultLocale),
160
158
  warningPkgPath: (0, plugin_utils_1.winPath)((0, path_1.dirname)(require.resolve('warning/package'))),
@@ -177,7 +175,7 @@ exports.default = (api) => {
177
175
  Antd: !!antd,
178
176
  LocaleList: localeList,
179
177
  ShowSelectLang: localeList.length > 1 && !!antd,
180
- antdFiles: ((_f = api.config) === null || _f === void 0 ? void 0 : _f.ssr) ? 'lib' : 'es',
178
+ antdFiles: ((_d = api.config) === null || _d === void 0 ? void 0 : _d.ssr) ? 'lib' : 'es',
181
179
  }),
182
180
  });
183
181
  // index.ts
@@ -188,14 +186,14 @@ export { setLocale, getLocale, useIntl, injectIntl, formatMessage, FormattedMess
188
186
  export { SelectLang } from './SelectLang.tsx';
189
187
  `,
190
188
  });
191
- }));
189
+ });
192
190
  // Runtime Plugin
193
191
  api.addRuntimePlugin(() => [(0, withTmpPath_1.withTmpPath)({ api, path: 'runtime.tsx' })]);
194
192
  api.addRuntimePluginKey(() => ['locale']);
195
193
  // watch locale files
196
- api.addTmpGenerateWatcherPaths(() => __awaiter(void 0, void 0, void 0, function* () {
194
+ api.addTmpGenerateWatcherPaths(async () => {
197
195
  const resolveKey = api.config.moment2dayjs ? 'dayjs' : 'moment';
198
- const localeList = yield getList(resolveKey);
196
+ const localeList = await getList(resolveKey);
199
197
  return (0, localeUtils_1.exactLocalePaths)(localeList);
200
- }));
198
+ });
201
199
  };
package/dist/model.js CHANGED
@@ -22,15 +22,6 @@ var __importStar = (this && this.__importStar) || function (mod) {
22
22
  __setModuleDefault(result, mod);
23
23
  return result;
24
24
  };
25
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27
- return new (P || (P = Promise))(function (resolve, reject) {
28
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31
- step((generator = generator.apply(thisArg, _arguments || [])).next());
32
- });
33
- };
34
25
  Object.defineProperty(exports, "__esModule", { value: true });
35
26
  const t = __importStar(require("@umijs/bundler-utils/compiled/babel/types"));
36
27
  const fs_1 = require("fs");
@@ -49,17 +40,8 @@ exports.default = (api) => {
49
40
  },
50
41
  enableBy: api.EnableBy.config,
51
42
  });
52
- api.modifyAppData((memo) => __awaiter(void 0, void 0, void 0, function* () {
53
- const models = yield getAllModels(api);
54
- memo.pluginModel = {
55
- models,
56
- };
57
- return memo;
58
- }));
59
- api.onGenerateFiles((args) => __awaiter(void 0, void 0, void 0, function* () {
60
- const models = args.isFirstTime
61
- ? api.appData.pluginModel.models
62
- : yield getAllModels(api);
43
+ api.onGenerateFiles(async () => {
44
+ const models = await getAllModels(api);
63
45
  // model.ts
64
46
  api.writeTmpFile({
65
47
  path: 'model.ts',
@@ -94,7 +76,7 @@ export function dataflowProvider(container, opts) {
94
76
  }
95
77
  `,
96
78
  });
97
- }));
79
+ });
98
80
  api.addTmpGenerateWatcherPaths(() => {
99
81
  return [(0, path_1.join)(api.paths.absSrcPath, 'models')];
100
82
  });
@@ -102,19 +84,18 @@ export function dataflowProvider(container, opts) {
102
84
  return [(0, withTmpPath_1.withTmpPath)({ api, path: 'runtime.tsx' })];
103
85
  });
104
86
  };
105
- function getAllModels(api) {
106
- return __awaiter(this, void 0, void 0, function* () {
107
- const extraModels = yield api.applyPlugins({
108
- key: 'addExtraModels',
109
- type: api.ApplyPluginsType.add,
110
- initialValue: [],
111
- });
112
- return new modelUtils_1.ModelUtils(api, {
113
- astTest({ node }) {
114
- return t.isArrowFunctionExpression(node) || t.isFunctionDeclaration(node);
115
- },
116
- }).getAllModels({
117
- extraModels: [...extraModels, ...(api.config.model.extraModels || [])],
118
- });
87
+ async function getAllModels(api) {
88
+ const extraModels = await api.applyPlugins({
89
+ key: 'addExtraModels',
90
+ type: api.ApplyPluginsType.add,
91
+ initialValue: [],
92
+ });
93
+ return new modelUtils_1.ModelUtils(api, {
94
+ astTest({ node }) {
95
+ return t.isArrowFunctionExpression(node) || t.isFunctionDeclaration(node);
96
+ },
97
+ }).getAllModels({
98
+ sort: {},
99
+ extraModels: [...extraModels, ...(api.config.model.extraModels || [])],
119
100
  });
120
101
  }
@@ -23,7 +23,17 @@ exports.default = (api) => {
23
23
  api.addRuntimePlugin(() => {
24
24
  return [(0, withTmpPath_1.withTmpPath)({ api, path: 'masterRuntimePlugin.tsx' })];
25
25
  });
26
- api.modifyDefaultConfig((config) => (Object.assign(Object.assign({}, config), { mountElementId: constants_1.defaultMasterRootId, qiankun: Object.assign(Object.assign({}, config.qiankun), { master: Object.assign(Object.assign({}, JSON.parse(process.env.INITIAL_QIANKUN_MASTER_OPTIONS || '{}')), (config.qiankun || {}).master) }) })));
26
+ api.modifyDefaultConfig((config) => ({
27
+ ...config,
28
+ mountElementId: constants_1.defaultMasterRootId,
29
+ qiankun: {
30
+ ...config.qiankun,
31
+ master: {
32
+ ...JSON.parse(process.env.INITIAL_QIANKUN_MASTER_OPTIONS || '{}'),
33
+ ...(config.qiankun || {}).master,
34
+ },
35
+ },
36
+ }));
27
37
  // TODO: modify routes
28
38
  api.modifyRoutes((memo) => {
29
39
  Object.keys(memo).forEach((id) => {
@@ -38,7 +48,7 @@ exports.default = (api) => {
38
48
  const normalizedRouteProps = JSON.stringify(routeProps).replace(/"/g, "'");
39
49
  route.file = `(async () => {
40
50
  const { getMicroAppRouteComponent } = await import('@@/plugin-qiankun-master/getMicroAppRouteComponent');
41
- return getMicroAppRouteComponent({ appName: '${appName}', base: '${base}', masterHistoryType: '${masterHistoryType}', routeProps: ${normalizedRouteProps} })
51
+ return getMicroAppRouteComponent({ appName: '${appName}', base: '${base}', routePath: '${route.path}', masterHistoryType: '${masterHistoryType}', routeProps: ${normalizedRouteProps} })
42
52
  })()`;
43
53
  }
44
54
  });
@@ -65,7 +75,11 @@ exports.default = (api) => {
65
75
  api.writeTmpFile({
66
76
  path: 'masterOptions.ts',
67
77
  content: `
68
- let options = ${JSON.stringify(Object.assign({ masterHistoryType: ((_a = api.config.history) === null || _a === void 0 ? void 0 : _a.type) || constants_1.defaultHistoryType, base: api.config.base || '/' }, api.config.qiankun.master))};
78
+ let options = ${JSON.stringify({
79
+ masterHistoryType: ((_a = api.config.history) === null || _a === void 0 ? void 0 : _a.type) || constants_1.defaultHistoryType,
80
+ base: api.config.base || '/',
81
+ ...api.config.qiankun.master,
82
+ })};
69
83
  export const getMasterOptions = () => options;
70
84
  export const setMasterOptions = (newOpts) => options = ({ ...options, ...newOpts });
71
85
  `,
@@ -99,13 +113,16 @@ export const setMasterOptions = (newOpts) => options = ({ ...options, ...newOpts
99
113
  });
100
114
  }
101
115
  else {
116
+ let content = getFileContent(file);
117
+ if (!api.config.qiankun.externalQiankun) {
118
+ content = content.replace(/from 'qiankun'/g, `from '${(0, plugin_utils_1.winPath)((0, path_1.dirname)(require.resolve('qiankun/package')))}'`);
119
+ }
102
120
  api.writeTmpFile({
103
121
  path: file.replace(/\.tpl$/, ''),
104
- content: getFileContent(file)
122
+ content: content
105
123
  .replace('__USE_MODEL__', api.isPluginEnable('model')
106
124
  ? `import { useModel } from '@@/plugin-model'`
107
125
  : `const useModel = null;`)
108
- .replace(/from 'qiankun'/g, `from '${(0, plugin_utils_1.winPath)((0, path_1.dirname)(require.resolve('qiankun/package')))}'`)
109
126
  .replace(/from 'lodash\//g, `from '${(0, plugin_utils_1.winPath)((0, path_1.dirname)(require.resolve('lodash/package')))}/`),
110
127
  });
111
128
  }
@@ -30,16 +30,29 @@ exports.default = (api) => {
30
30
  key: 'addExtraModels',
31
31
  fn() {
32
32
  return [
33
- `@@/plugin-qiankun-slave/qiankunModel#{"namespace":"${constants_1.qiankunStateFromMasterModelNamespace}"}`,
33
+ (0, withTmpPath_1.withTmpPath)({
34
+ api,
35
+ path: `qiankunModel.ts#{"namespace":"${constants_1.qiankunStateFromMasterModelNamespace}"}`,
36
+ }),
34
37
  ];
35
38
  },
36
39
  });
37
40
  api.modifyDefaultConfig((memo) => {
38
41
  var _a, _b, _c, _d;
39
- const initialSlaveOptions = Object.assign(Object.assign({ devSourceMap: true }, JSON.parse(process.env.INITIAL_QIANKUN_SLAVE_OPTIONS || '{}')), (memo.qiankun || {}).slave);
40
- const modifiedDefaultConfig = Object.assign(Object.assign({}, memo), {
42
+ const initialSlaveOptions = {
43
+ devSourceMap: true,
44
+ ...JSON.parse(process.env.INITIAL_QIANKUN_SLAVE_OPTIONS || '{}'),
45
+ ...(memo.qiankun || {}).slave,
46
+ };
47
+ const modifiedDefaultConfig = {
48
+ ...memo,
41
49
  // 默认开启 runtimePublicPath,避免出现 dynamic import 场景子应用资源地址出问题
42
- runtimePublicPath: true, qiankun: Object.assign(Object.assign({}, memo.qiankun), { slave: initialSlaveOptions }) });
50
+ runtimePublicPath: true,
51
+ qiankun: {
52
+ ...memo.qiankun,
53
+ slave: initialSlaveOptions,
54
+ },
55
+ };
43
56
  const shouldNotModifyDefaultBase = (_c = (_b = (_a = api.userConfig.qiankun) === null || _a === void 0 ? void 0 : _a.slave) === null || _b === void 0 ? void 0 : _b.shouldNotModifyDefaultBase) !== null && _c !== void 0 ? _c : initialSlaveOptions.shouldNotModifyDefaultBase;
44
57
  const historyType = ((_d = api.userConfig.history) === null || _d === void 0 ? void 0 : _d.type) || 'browser';
45
58
  if (!shouldNotModifyDefaultBase && historyType !== 'hash') {
@@ -52,8 +65,11 @@ exports.default = (api) => {
52
65
  var _a, _b;
53
66
  // mfsu 场景默认给子应用增加 mfName 配置,从而避免冲突
54
67
  if (config.mfsu !== false) {
55
- config.mfsu = Object.assign(Object.assign({}, config.mfsu), { mfName: ((_a = config.mfsu) === null || _a === void 0 ? void 0 : _a.mfName) ||
56
- `mf_${(_b = api.pkg.name) === null || _b === void 0 ? void 0 : _b.replace(/^@/, '').replace(/\W/g, '_')}` });
68
+ config.mfsu = {
69
+ ...config.mfsu,
70
+ mfName: ((_a = config.mfsu) === null || _a === void 0 ? void 0 : _a.mfName) ||
71
+ `mf_${(_b = api.pkg.name) === null || _b === void 0 ? void 0 : _b.replace(/^@/, '').replace(/\W/g, '_')}`,
72
+ };
57
73
  }
58
74
  return config;
59
75
  });
@@ -110,36 +126,39 @@ if (!window.__POWERED_BY_QIANKUN__) {
110
126
  function getFileContent(file) {
111
127
  return (0, fs_1.readFileSync)((0, path_1.join)(__dirname, '../../libs/qiankun/slave', file), 'utf-8');
112
128
  }
113
- api.onGenerateFiles(() => {
114
- // api.writeTmpFile({
115
- // path: 'slaveOptions.ts',
116
- // content: `
117
- // let options = ${JSON.stringify((api.config.qiankun || {}).slave || {})};
118
- // export const getSlaveOptions = () => options;
119
- // export const setSlaveOptions = (newOpts) => options = ({ ...options, ...newOpts });
120
- // `,
121
- // });
122
- [
123
- 'qiankunModel.ts',
124
- 'connectMaster.tsx',
125
- 'slaveRuntimePlugin.ts',
126
- 'lifecycles.ts',
127
- ].forEach((file) => {
128
- api.writeTmpFile({
129
- path: file.replace(/\.tpl$/, ''),
130
- content: getFileContent(file)
131
- .replace('__USE_MODEL__', api.isPluginEnable('model')
132
- ? `import { useModel } from '@@/plugin-model'`
133
- : `const useModel = null;`)
134
- .replace(/from 'qiankun'/g, `from '${(0, plugin_utils_1.winPath)((0, path_1.dirname)(require.resolve('qiankun/package')))}'`)
135
- .replace(/from 'lodash\//g, `from '${(0, plugin_utils_1.winPath)((0, path_1.dirname)(require.resolve('lodash/package')))}/`),
129
+ api.onGenerateFiles({
130
+ fn() {
131
+ // api.writeTmpFile({
132
+ // path: 'slaveOptions.ts',
133
+ // content: `
134
+ // let options = ${JSON.stringify((api.config.qiankun || {}).slave || {})};
135
+ // export const getSlaveOptions = () => options;
136
+ // export const setSlaveOptions = (newOpts) => options = ({ ...options, ...newOpts });
137
+ // `,
138
+ // });
139
+ [
140
+ 'qiankunModel.ts',
141
+ 'connectMaster.tsx',
142
+ 'slaveRuntimePlugin.ts',
143
+ 'lifecycles.ts',
144
+ ].forEach((file) => {
145
+ api.writeTmpFile({
146
+ path: file.replace(/\.tpl$/, ''),
147
+ content: getFileContent(file)
148
+ .replace('__USE_MODEL__', api.isPluginEnable('model')
149
+ ? `import { useModel } from '@@/plugin-model'`
150
+ : `const useModel = null;`)
151
+ .replace(/from 'qiankun'/g, `from '${(0, plugin_utils_1.winPath)((0, path_1.dirname)(require.resolve('qiankun/package')))}'`)
152
+ .replace(/from 'lodash\//g, `from '${(0, plugin_utils_1.winPath)((0, path_1.dirname)(require.resolve('lodash/package')))}/`),
153
+ });
136
154
  });
137
- });
138
- api.writeTmpFile({
139
- path: 'index.ts',
140
- content: `
155
+ api.writeTmpFile({
156
+ path: 'index.ts',
157
+ content: `
141
158
  export { connectMaster } from './connectMaster';
142
159
  `,
143
- });
160
+ });
161
+ },
162
+ before: 'model',
144
163
  });
145
164
  };
package/dist/qiankun.js CHANGED
@@ -7,6 +7,7 @@ exports.default = (api) => {
7
7
  return joi.object().keys({
8
8
  slave: joi.object(),
9
9
  master: joi.object(),
10
+ externalQiankun: joi.boolean(),
10
11
  });
11
12
  },
12
13
  },
package/dist/request.js CHANGED
@@ -160,12 +160,12 @@ const getRequestInstance = (): AxiosInstance => {
160
160
  const config = getConfig();
161
161
  requestInstance = axios.create(config);
162
162
 
163
- config?.requestInterceptors?.forEach((interceptor) => {
163
+ config?.requestInterceptors?.forEach((interceptor) => {
164
164
  if(interceptor instanceof Array){
165
165
  requestInstance.interceptors.request.use((config) => {
166
166
  const { url } = config;
167
167
  if(interceptor[0].length === 2){
168
- const { url: newUrl, options } = interceptor[0](url, config);
168
+ const { url: newUrl, options } = interceptor[0](url, config);
169
169
  return { ...options, url: newUrl };
170
170
  }
171
171
  return interceptor[0](config);
@@ -182,16 +182,16 @@ const getRequestInstance = (): AxiosInstance => {
182
182
  }
183
183
  });
184
184
 
185
- config?.responseInterceptors?.forEach((interceptor) => {
186
- interceptor instanceof Array ?
185
+ config?.responseInterceptors?.forEach((interceptor) => {
186
+ interceptor instanceof Array ?
187
187
  requestInstance.interceptors.response.use(interceptor[0], interceptor[1]):
188
188
  requestInstance.interceptors.response.use(interceptor);
189
189
  });
190
190
 
191
191
  // 当响应的数据 success 是 false 的时候,抛出 error 以供 errorHandler 处理。
192
- requestInstance.interceptors.response.use((response)=>{
192
+ requestInstance.interceptors.response.use((response) => {
193
193
  const { data } = response;
194
- if(config?.errorConfig?.errorThrower){
194
+ if(data?.success === false && config?.errorConfig?.errorThrower){
195
195
  config.errorConfig.errorThrower(data);
196
196
  }
197
197
  return response;
@@ -199,16 +199,16 @@ const getRequestInstance = (): AxiosInstance => {
199
199
  return requestInstance;
200
200
  };
201
201
 
202
- const request: IRequest = (url: string, opts: any = { method: 'GET' }) => {
202
+ const request: IRequest = (url: string, opts: any = { method: 'GET' }) => {
203
203
  const requestInstance = getRequestInstance();
204
204
  const config = getConfig();
205
205
  const { getResponse = false, requestInterceptors, responseInterceptors } = opts;
206
- const requestInterceptorsToEject = requestInterceptors?.map((interceptor) => {
206
+ const requestInterceptorsToEject = requestInterceptors?.map((interceptor) => {
207
207
  if(interceptor instanceof Array){
208
208
  return requestInstance.interceptors.request.use((config) => {
209
209
  const { url } = config;
210
210
  if(interceptor[0].length === 2){
211
- const { url: newUrl, options } = interceptor[0](url, config);
211
+ const { url: newUrl, options } = interceptor[0](url, config);
212
212
  return { ...options, url: newUrl };
213
213
  }
214
214
  return interceptor[0](config);
@@ -224,8 +224,8 @@ const request: IRequest = (url: string, opts: any = { method: 'GET' }) => {
224
224
  })
225
225
  }
226
226
  });
227
- const responseInterceptorsToEject = responseInterceptors?.map((interceptor) => {
228
- return interceptor instanceof Array ?
227
+ const responseInterceptorsToEject = responseInterceptors?.map((interceptor) => {
228
+ return interceptor instanceof Array ?
229
229
  requestInstance.interceptors.response.use(interceptor[0], interceptor[1]):
230
230
  requestInstance.interceptors.response.use(interceptor);
231
231
  });
@@ -291,6 +291,12 @@ export type {
291
291
  formatResult,
292
292
  }),
293
293
  });
294
+ api.writeTmpFile({
295
+ path: 'types.d.ts',
296
+ content: `
297
+ export type { RequestConfig } from './request';
298
+ `,
299
+ });
294
300
  api.writeTmpFile({
295
301
  path: 'index.ts',
296
302
  content: `
@@ -299,10 +305,6 @@ export {
299
305
  UseRequestProvider,
300
306
  request,
301
307
  } from './request';
302
-
303
- export type {
304
- RequestConfig
305
- } from './request';
306
308
  `,
307
309
  });
308
310
  });
@@ -1,13 +1,4 @@
1
1
  "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
2
  Object.defineProperty(exports, "__esModule", { value: true });
12
3
  exports.isNeedPolyfill = exports.exactLocalePaths = exports.getLocaleList = exports.getAntdLocale = exports.getMomentLocale = void 0;
13
4
  const fs_1 = require("fs");
@@ -55,7 +46,7 @@ const modulesHasLocale = (localePath) => {
55
46
  return false;
56
47
  }
57
48
  };
58
- const getLocaleList = (opts) => __awaiter(void 0, void 0, void 0, function* () {
49
+ const getLocaleList = async (opts) => {
59
50
  const { localeFolder, separator = '-', absSrcPath = '', absPagesPath = '', addAntdLocales, resolveKey = 'moment', } = opts;
60
51
  const localeFileMath = new RegExp(`^([a-z]{2})${separator}?([A-Z]{2})?\.(js|json|ts)$`);
61
52
  const localeFiles = plugin_utils_1.glob
@@ -80,11 +71,11 @@ const getLocaleList = (opts) => __awaiter(void 0, void 0, void 0, function* () {
80
71
  };
81
72
  });
82
73
  const groups = plugin_utils_1.lodash.groupBy(localeFiles, 'name');
83
- const promises = Object.keys(groups).map((name) => __awaiter(void 0, void 0, void 0, function* () {
74
+ const promises = Object.keys(groups).map(async (name) => {
84
75
  const [lang, country = ''] = name.split(separator);
85
76
  const { momentLocale } = (0, exports.getMomentLocale)(lang, country, resolveKey);
86
77
  const antdLocale = plugin_utils_1.lodash
87
- .uniq(yield addAntdLocales({ lang, country }))
78
+ .uniq(await addAntdLocales({ lang, country }))
88
79
  .filter((localePath) => modulesHasLocale(localePath));
89
80
  return {
90
81
  lang,
@@ -97,9 +88,9 @@ const getLocaleList = (opts) => __awaiter(void 0, void 0, void 0, function* () {
97
88
  paths: groups[name].map((item) => (0, plugin_utils_1.winPath)(item.path)),
98
89
  momentLocale,
99
90
  };
100
- }));
91
+ });
101
92
  return Promise.all(promises);
102
- });
93
+ };
103
94
  exports.getLocaleList = getLocaleList;
104
95
  const exactLocalePaths = (data) => {
105
96
  return plugin_utils_1.lodash.flatten(data.map((item) => item.paths));
@@ -12,7 +12,9 @@ export declare class Model {
12
12
  namespace: string;
13
13
  id: string;
14
14
  exportName: string;
15
- constructor(file: string, id: number);
15
+ deps: string[];
16
+ constructor(file: string, sort: {} | undefined, id: number);
17
+ findDeps(sort: object): string[];
16
18
  }
17
19
  export declare class ModelUtils {
18
20
  api: IApi;
@@ -20,8 +22,10 @@ export declare class ModelUtils {
20
22
  count: number;
21
23
  constructor(api: IApi | null, opts: IOpts);
22
24
  getAllModels(opts: {
25
+ sort?: object;
23
26
  extraModels: string[];
24
27
  }): Model[];
28
+ getSortedNamespaces(models: Model[]): string[];
25
29
  getModels(opts: {
26
30
  base: string;
27
31
  pattern?: string;
@@ -29,13 +29,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
29
29
  exports.ModelUtils = exports.Model = void 0;
30
30
  const parser = __importStar(require("@umijs/bundler-utils/compiled/babel/parser"));
31
31
  const traverse_1 = __importDefault(require("@umijs/bundler-utils/compiled/babel/traverse"));
32
+ const t = __importStar(require("@umijs/bundler-utils/compiled/babel/types"));
32
33
  const esbuild_1 = require("@umijs/bundler-utils/compiled/esbuild");
33
34
  const fs_1 = require("fs");
34
35
  const path_1 = require("path");
35
36
  const plugin_utils_1 = require("umi/plugin-utils");
36
37
  const astUtils_1 = require("./astUtils");
37
38
  class Model {
38
- constructor(file, id) {
39
+ constructor(file, sort, id) {
39
40
  let namespace;
40
41
  let exportName;
41
42
  const [_file, meta] = file.split('#');
@@ -48,6 +49,36 @@ class Model {
48
49
  this.id = `model_${id}`;
49
50
  this.namespace = namespace || (0, path_1.basename)(file, (0, path_1.extname)(file));
50
51
  this.exportName = exportName || 'default';
52
+ this.deps = sort ? this.findDeps(sort) : [];
53
+ }
54
+ findDeps(sort) {
55
+ const content = (0, fs_1.readFileSync)(this.file, 'utf-8');
56
+ // transform with esbuild first
57
+ // to reduce unexpected ast problem
58
+ const loader = (0, path_1.extname)(this.file).slice(1);
59
+ const result = (0, esbuild_1.transformSync)(content, {
60
+ loader,
61
+ sourcemap: false,
62
+ minify: false,
63
+ });
64
+ // transform with babel
65
+ const deps = new Set();
66
+ const ast = parser.parse(result.code, {
67
+ sourceType: 'module',
68
+ sourceFilename: this.file,
69
+ plugins: [],
70
+ });
71
+ // TODO: use sort
72
+ sort;
73
+ (0, traverse_1.default)(ast, {
74
+ CallExpression: (path) => {
75
+ if (t.isIdentifier(path.node.callee, { name: 'useModel' }) &&
76
+ t.isStringLiteral(path.node.arguments[0])) {
77
+ deps.add(path.node.arguments[0].value);
78
+ }
79
+ },
80
+ });
81
+ return [...deps];
51
82
  }
52
83
  }
53
84
  exports.Model = Model;
@@ -61,7 +92,7 @@ class ModelUtils {
61
92
  getAllModels(opts) {
62
93
  // reset count
63
94
  this.count = 1;
64
- return [
95
+ const models = [
65
96
  ...this.getModels({
66
97
  base: (0, path_1.join)(this.api.paths.absSrcPath, 'models'),
67
98
  pattern: '**/*.{ts,tsx,js,jsx}',
@@ -76,8 +107,59 @@ class ModelUtils {
76
107
  }),
77
108
  ...opts.extraModels,
78
109
  ].map((file) => {
79
- return new Model(file, this.count++);
110
+ return new Model(file, opts.sort, this.count++);
111
+ });
112
+ // check duplicate
113
+ const namespaces = models.map((model) => model.namespace);
114
+ if (new Set(namespaces).size !== namespaces.length) {
115
+ throw new Error(`Duplicate namespace in models: ${namespaces.join(', ')}`);
116
+ }
117
+ // sort models by deps
118
+ if (opts.sort) {
119
+ const namespaces = this.getSortedNamespaces(models);
120
+ models.sort((a, b) => namespaces.indexOf(a.namespace) - namespaces.indexOf(b.namespace));
121
+ }
122
+ return models;
123
+ }
124
+ getSortedNamespaces(models) {
125
+ let final = [];
126
+ models.forEach((model, index) => {
127
+ const { deps, namespace } = model;
128
+ if (deps && deps.length) {
129
+ const itemGroup = [...deps, namespace];
130
+ const cannotUse = [namespace];
131
+ for (let i = 0; i <= index; i += 1) {
132
+ if (models[i].deps.filter((v) => cannotUse.includes(v)).length) {
133
+ if (!cannotUse.includes(models[i].namespace)) {
134
+ cannotUse.push(models[i].namespace);
135
+ i = -1;
136
+ }
137
+ }
138
+ }
139
+ const errorList = deps.filter((v) => cannotUse.includes(v));
140
+ if (errorList.length) {
141
+ throw Error(`Circular dependencies: ${namespace} can't use ${errorList.join(', ')}`);
142
+ }
143
+ const intersection = final.filter((v) => itemGroup.includes(v));
144
+ if (intersection.length) {
145
+ // first intersection
146
+ const finalIndex = final.indexOf(intersection[0]);
147
+ // replace with groupItem
148
+ final = final
149
+ .slice(0, finalIndex)
150
+ .concat(itemGroup)
151
+ .concat(final.slice(finalIndex + 1));
152
+ }
153
+ else {
154
+ final.push(...itemGroup);
155
+ }
156
+ }
157
+ if (!final.includes(namespace)) {
158
+ // first occurrence append to the end
159
+ final.push(namespace);
160
+ }
80
161
  });
162
+ return [...new Set(final)];
81
163
  }
82
164
  getModels(opts) {
83
165
  return plugin_utils_1.glob
@@ -139,6 +139,13 @@ export const MicroApp = forwardRef(
139
139
  setComponentError(null);
140
140
  setLoading(true);
141
141
  const configuration = {
142
+ fetch(url) {
143
+ return window.fetch(url, {
144
+ headers: {
145
+ accept: 'text/html',
146
+ },
147
+ });
148
+ },
142
149
  globalContext: window,
143
150
  ...globalSettings,
144
151
  ...settingsFromProps,
@@ -5,7 +5,7 @@
5
5
  * @since 2019-06-20
6
6
  */
7
7
 
8
- import { ReactComponentElement } from 'react';
8
+ import React, { ReactComponentElement } from 'react';
9
9
  import type { IRouteProps } from 'umi';
10
10
 
11
11
  export const defaultMountContainerId = 'root-subapp';
@@ -48,6 +48,7 @@ export function patchMicroAppRoute(
48
48
  getMicroAppRouteComponent: (opts: {
49
49
  appName: string;
50
50
  base: string;
51
+ routePath: string;
51
52
  masterHistoryType: string;
52
53
  routeProps?: any;
53
54
  }) => string | ReactComponentElement<any>,
@@ -63,9 +64,9 @@ export function patchMicroAppRoute(
63
64
  const microAppProps =
64
65
  route[`${routeBindingAlias}Props`] || route.microAppProps || {};
65
66
  if (microAppName) {
66
- if (route.routes?.length) {
67
- const childrenRouteHasComponent = route.routes.some(
68
- (r: any) => r.component,
67
+ if (route.children?.length) {
68
+ const childrenRouteHasComponent = route.children.some(
69
+ (r: any) => r.element,
69
70
  );
70
71
  if (childrenRouteHasComponent) {
71
72
  throw new Error(
@@ -74,7 +75,10 @@ export function patchMicroAppRoute(
74
75
  }
75
76
  }
76
77
 
77
- route.exact = false;
78
+ // 自动追加通配符,匹配子应用的路由
79
+ if (!route.path.endsWith('/*')) {
80
+ route.path = route.path.replace(/\/?$/, '/*');
81
+ }
78
82
 
79
83
  const { settings = {}, ...componentProps } = microAppProps;
80
84
  const routeProps = {
@@ -85,10 +89,11 @@ export function patchMicroAppRoute(
85
89
  const opts = {
86
90
  appName: microAppName,
87
91
  base,
92
+ routePath: route.path,
88
93
  masterHistoryType,
89
94
  routeProps,
90
95
  };
91
- route.component = getMicroAppRouteComponent(opts);
96
+ route.element = React.createElement(getMicroAppRouteComponent(opts), null);
92
97
  }
93
98
  }
94
99
 
@@ -100,8 +105,8 @@ const recursiveSearch = (
100
105
  if (routes[i].path === path) {
101
106
  return routes[i];
102
107
  }
103
- if (routes[i].routes && routes[i].routes?.length) {
104
- const found = recursiveSearch(routes[i].routes || [], path);
108
+ if (routes[i].children && routes[i].children?.length) {
109
+ const found = recursiveSearch(routes[i].children || [], path);
105
110
  if (found) {
106
111
  return found;
107
112
  }
@@ -123,8 +128,8 @@ export function insertRoute(routes: IRouteProps[], microAppRoute: IRouteProps) {
123
128
  );
124
129
  }
125
130
  found.exact = false;
126
- found.routes = found.routes || [];
127
- found.routes.push(microAppRoute);
131
+ found.children = found.children || [];
132
+ found.children.push(microAppRoute);
128
133
  } else {
129
134
  throw new Error(
130
135
  `[plugin-qiankun]: path "${microAppRoute.insert}" not found`,
@@ -1,22 +1,20 @@
1
1
  import React from 'react';
2
2
  import { MicroApp } from './MicroApp';
3
- import { useLocation } from 'umi';
4
3
 
5
4
  export function getMicroAppRouteComponent(opts: {
6
5
  appName: string;
7
6
  base: string;
7
+ routePath: string;
8
8
  masterHistoryType: string;
9
9
  routeProps?: any;
10
10
  }) {
11
- const { base, masterHistoryType, appName, routeProps } = opts;
12
- const RouteComponent = ({ match }: any) => {
13
- const url = useLocation().pathname;
14
-
11
+ const { base, masterHistoryType, appName, routeProps, routePath } = opts;
12
+ const RouteComponent = () => {
15
13
  // 默认取静态配置的 base
16
14
  let umiConfigBase = base === '/' ? '' : base;
17
15
 
18
- let runtimeMatchedBase =
19
- umiConfigBase + (url.endsWith('/') ? url.substr(0, url.length - 1) : url);
16
+ // 拼接子应用挂载路由
17
+ let runtimeMatchedBase = umiConfigBase + routePath.replace('/*', '');
20
18
 
21
19
  {{#dynamicRoot}}
22
20
  // @see https://github.com/umijs/umi/blob/master/packages/preset-built-in/src/plugins/commands/htmlUtils.ts#L102
@@ -34,10 +34,10 @@ function patchMicroAppRouteComponent(routes: any[]) {
34
34
  const rootRoute = routes.find((route) => route.path === '/');
35
35
  if (rootRoute) {
36
36
  // 如果根路由是叶子节点,则直接返回其父节点
37
- if (!rootRoute.routes) {
37
+ if (!rootRoute.children) {
38
38
  return routes;
39
39
  }
40
- return getRootRoutes(rootRoute.routes);
40
+ return getRootRoutes(rootRoute.children);
41
41
  }
42
42
  return routes;
43
43
  };
@@ -50,11 +50,12 @@ function patchMicroAppRouteComponent(routes: any[]) {
50
50
  const patchRoute = (route: any) => {
51
51
  patchMicroAppRoute(route, getMicroAppRouteComponent, {
52
52
  base,
53
+ routePath: route.path,
53
54
  masterHistoryType,
54
55
  routeBindingAlias,
55
56
  });
56
- if (route.routes?.length) {
57
- route.routes.forEach(patchRoute);
57
+ if (route.children?.length) {
58
+ route.children.forEach(patchRoute);
58
59
  }
59
60
  };
60
61
 
@@ -123,7 +124,7 @@ export async function render(oldRender: typeof noop) {
123
124
  }
124
125
  }
125
126
 
126
- export function patchRoutes({ routes }: { routes: any[] }) {
127
+ export function patchClientRoutes({ routes }: { routes: any[] }) {
127
128
  if (microAppRuntimeRoutes) {
128
129
  patchMicroAppRouteComponent(routes);
129
130
  }
@@ -1,5 +1,4 @@
1
1
  // @ts-nocheck
2
- /* eslint-disable */
3
2
  __USE_MODEL__;
4
3
  import React from 'react';
5
4
 
@@ -1,5 +1,4 @@
1
1
  // @ts-nocheck
2
- /* eslint-disable */
3
2
  import { getPluginManager } from '@@/core/plugin';
4
3
  import ReactDOM from 'react-dom';
5
4
  import { ApplyPluginsType } from 'umi';
@@ -22,7 +21,7 @@ let render = noop;
22
21
  let hasMountedAtLeastOnce = false;
23
22
 
24
23
  export default () => defer.promise;
25
- export const clientRenderOptsStack: any[] = [];
24
+ export const contextOptsStack: any[] = [];
26
25
 
27
26
  // function normalizeHistory(
28
27
  // history?: 'string' | Record<string, any>,
@@ -79,10 +78,7 @@ export function genMount(mountElementId: string) {
79
78
  // 默认开启
80
79
  // 如果需要手动控制 loading,通过主应用配置 props.autoSetLoading false 可以关闭
81
80
  callback: () => {
82
- if (
83
- props?.autoSetLoading &&
84
- typeof props?.setLoading === 'function'
85
- ) {
81
+ if (props.autoSetLoading && typeof props.setLoading === 'function') {
86
82
  props.setLoading(false);
87
83
  }
88
84
 
@@ -94,9 +90,11 @@ export function genMount(mountElementId: string) {
94
90
  // 支持通过 props 注入 container 来限定子应用 mountElementId 的查找范围
95
91
  // 避免多个子应用出现在同一主应用时出现 mount 冲突
96
92
  rootElement:
97
- props?.container?.querySelector(`#${mountElementId}`) ||
93
+ props.container?.querySelector(`#${mountElementId}`) ||
98
94
  mountElementId,
99
95
 
96
+ basename: props.base,
97
+
100
98
  // 当存在同一个 umi 子应用在同一个页面被多实例渲染的场景时(比如一个页面里,同时展示了这个子应用的多个路由页面)
101
99
  // mount 钩子会被调用多次,但是具体什么时候对应的实例开始 render 则是不定的,即它调用 applyPlugins('modifyClientRenderOpts') 的时机是不确定的
102
100
  // 为了保证每次 applyPlugins('modifyClientRenderOpts') 调用是生成正确的 history,我们需要这里通过闭包上下文维持 mount 调用时的一些配置信息
@@ -111,7 +109,7 @@ export function genMount(mountElementId: string) {
111
109
  // },
112
110
  };
113
111
 
114
- clientRenderOptsStack.push(clientRenderOpts);
112
+ contextOptsStack.push(clientRenderOpts);
115
113
  }
116
114
 
117
115
  // 第一次 mount defer 被 resolve 后umi 会自动触发 render,非第一次 mount 则需手动触发
@@ -121,6 +119,12 @@ export function genMount(mountElementId: string) {
121
119
  defer.resolve();
122
120
  }
123
121
 
122
+ // 如果需要手动控制 loading,通过主应用配置 props.autoSetLoading false 可以关闭
123
+ // 考虑到 react 18 之后 callback 不再准
124
+ // 所以在这里直接返回,而不使用 ReactDOM.render 的第三个参数
125
+ if (props.autoSetLoading && typeof props.setLoading === 'function') {
126
+ props.setLoading(false);
127
+ }
124
128
  hasMountedAtLeastOnce = true;
125
129
  };
126
130
  }
@@ -1,5 +1,4 @@
1
1
  // @ts-nocheck
2
- /* eslint-disable */
3
2
  import { useState } from 'react';
4
3
 
5
4
  let initState: any;
@@ -1,21 +1,15 @@
1
1
  // @ts-nocheck
2
- /* eslint-disable */
3
- import qiankunRender from './lifecycles';
2
+ import qiankunRender, { contextOptsStack } from './lifecycles';
4
3
 
5
4
  export function render(oldRender: any) {
6
5
  return qiankunRender().then(oldRender);
7
6
  }
8
7
 
9
- // export function modifyClientRenderOpts(memo: any) {
10
- // // 每次应用 render 的时候会调 modifyClientRenderOpts,这时尝试从队列中取 render 的配置
11
- // const clientRenderOpts = clientRenderOptsStack.shift();
12
- // if (clientRenderOpts) {
13
- // const history = clientRenderOpts.getHistory();
14
- // delete clientRenderOpts.getHistory;
15
- // clientRenderOpts.history = history;
16
- // }
17
- // return {
18
- // ...memo,
19
- // ...clientRenderOpts,
20
- // };
21
- // }
8
+ export function modifyContextOpts(memo: any) {
9
+ // 每次应用 render 的时候会调 modifyClientRenderOpts,这时尝试从队列中取 render 的配置
10
+ const clientRenderOpts = contextOptsStack.shift();
11
+ return {
12
+ ...memo,
13
+ ...clientRenderOpts,
14
+ };
15
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umijs/plugins",
3
- "version": "4.0.0-rc.14",
3
+ "version": "4.0.0-rc.17",
4
4
  "description": "@umijs/plugins",
5
5
  "homepage": "https://github.com/umijs/umi-next/tree/master/packages/plugins#readme",
6
6
  "bugs": "https://github.com/umijs/umi-next/issues",
@@ -24,12 +24,12 @@
24
24
  "dependencies": {
25
25
  "@ahooksjs/use-request": "^2.0.0",
26
26
  "@ant-design/icons": "^4.7.0",
27
- "@ant-design/pro-layout": "^6.35.1",
28
- "@umijs/bundler-utils": "4.0.0-rc.14",
27
+ "@ant-design/pro-layout": "^6.38.0",
28
+ "@umijs/bundler-utils": "4.0.0-rc.17",
29
29
  "antd-dayjs-webpack-plugin": "^1.0.6",
30
- "axios": "^0.26.1",
30
+ "axios": "^0.27.2",
31
31
  "babel-plugin-import": "^1.13.3",
32
- "dayjs": "^1.11.0",
32
+ "dayjs": "^1.11.2",
33
33
  "dva-core": "^2.0.4",
34
34
  "dva-immer": "^1.0.0",
35
35
  "dva-loading": "^3.0.22",
@@ -39,12 +39,12 @@
39
39
  "moment": "^2.29.3",
40
40
  "qiankun": "^2.7.0",
41
41
  "react-intl": "3.12.1",
42
- "react-redux": "^8.0.0",
42
+ "react-redux": "^8.0.1",
43
43
  "redux": "^4.2.0",
44
44
  "warning": "^4.0.3"
45
45
  },
46
46
  "devDependencies": {
47
- "umi": "4.0.0-rc.14"
47
+ "umi": "4.0.0-rc.17"
48
48
  },
49
49
  "publishConfig": {
50
50
  "access": "public"