@umijs/plugins 4.0.0-rc.15 → 4.0.0-rc.16
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/antd.js +13 -4
- package/dist/dva.js +0 -1
- package/dist/initial-state.js +1 -1
- package/dist/layout.js +2 -1
- package/dist/model.js +2 -19
- package/dist/qiankun/master.js +6 -3
- package/dist/qiankun/slave.js +35 -29
- package/dist/qiankun.js +1 -0
- package/dist/request.js +11 -11
- package/dist/utils/modelUtils.d.ts +5 -2
- package/dist/utils/modelUtils.js +85 -4
- package/libs/qiankun/master/common.ts +15 -10
- package/libs/qiankun/master/getMicroAppRouteComponent.tsx.tpl +5 -7
- package/libs/qiankun/master/masterRuntimePlugin.tsx +6 -5
- package/libs/qiankun/slave/lifecycles.ts +6 -0
- package/package.json +7 -7
package/dist/antd.js
CHANGED
|
@@ -30,7 +30,12 @@ exports.default = (api) => {
|
|
|
30
30
|
});
|
|
31
31
|
},
|
|
32
32
|
},
|
|
33
|
-
enableBy
|
|
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,6 +53,12 @@ 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
|
|
@@ -62,9 +73,7 @@ exports.default = (api) => {
|
|
|
62
73
|
...memo.theme,
|
|
63
74
|
};
|
|
64
75
|
}
|
|
65
|
-
|
|
66
|
-
});
|
|
67
|
-
api.modifyConfig((memo) => {
|
|
76
|
+
// antd theme
|
|
68
77
|
memo.theme = {
|
|
69
78
|
'root-entry-name': 'default',
|
|
70
79
|
...memo.theme,
|
package/dist/dva.js
CHANGED
package/dist/initial-state.js
CHANGED
|
@@ -13,7 +13,7 @@ exports.default = (api) => {
|
|
|
13
13
|
enableBy: api.EnableBy.config,
|
|
14
14
|
});
|
|
15
15
|
api.register({
|
|
16
|
-
key: '
|
|
16
|
+
key: 'addExtraModels',
|
|
17
17
|
fn: () => [(0, withTmpPath_1.withTmpPath)({ api, path: '@@initialState.ts' })],
|
|
18
18
|
});
|
|
19
19
|
api.addRuntimePluginKey(() => ['getInitialState']);
|
package/dist/layout.js
CHANGED
|
@@ -137,7 +137,8 @@ const { formatMessage } = useIntl();
|
|
|
137
137
|
}
|
|
138
138
|
if (menuItemProps.path && location.pathname !== menuItemProps.path) {
|
|
139
139
|
return (
|
|
140
|
-
|
|
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/model.js
CHANGED
|
@@ -40,17 +40,8 @@ exports.default = (api) => {
|
|
|
40
40
|
},
|
|
41
41
|
enableBy: api.EnableBy.config,
|
|
42
42
|
});
|
|
43
|
-
api.
|
|
43
|
+
api.onGenerateFiles(async () => {
|
|
44
44
|
const models = await getAllModels(api);
|
|
45
|
-
memo.pluginModel = {
|
|
46
|
-
models,
|
|
47
|
-
};
|
|
48
|
-
return memo;
|
|
49
|
-
});
|
|
50
|
-
api.onGenerateFiles(async (args) => {
|
|
51
|
-
const models = args.isFirstTime
|
|
52
|
-
? api.appData.pluginModel.models
|
|
53
|
-
: await getAllModels(api);
|
|
54
45
|
// model.ts
|
|
55
46
|
api.writeTmpFile({
|
|
56
47
|
path: 'model.ts',
|
|
@@ -94,11 +85,6 @@ export function dataflowProvider(container, opts) {
|
|
|
94
85
|
});
|
|
95
86
|
};
|
|
96
87
|
async function getAllModels(api) {
|
|
97
|
-
const extraModelsPre = await api.applyPlugins({
|
|
98
|
-
key: 'addExtraModelsPre',
|
|
99
|
-
type: api.ApplyPluginsType.add,
|
|
100
|
-
initialValue: [],
|
|
101
|
-
});
|
|
102
88
|
const extraModels = await api.applyPlugins({
|
|
103
89
|
key: 'addExtraModels',
|
|
104
90
|
type: api.ApplyPluginsType.add,
|
|
@@ -109,10 +95,7 @@ async function getAllModels(api) {
|
|
|
109
95
|
return t.isArrowFunctionExpression(node) || t.isFunctionDeclaration(node);
|
|
110
96
|
},
|
|
111
97
|
}).getAllModels({
|
|
112
|
-
|
|
113
|
-
...extraModelsPre,
|
|
114
|
-
...(api.config.model.extraModelsPre || []),
|
|
115
|
-
],
|
|
98
|
+
sort: {},
|
|
116
99
|
extraModels: [...extraModels, ...(api.config.model.extraModels || [])],
|
|
117
100
|
});
|
|
118
101
|
}
|
package/dist/qiankun/master.js
CHANGED
|
@@ -48,7 +48,7 @@ exports.default = (api) => {
|
|
|
48
48
|
const normalizedRouteProps = JSON.stringify(routeProps).replace(/"/g, "'");
|
|
49
49
|
route.file = `(async () => {
|
|
50
50
|
const { getMicroAppRouteComponent } = await import('@@/plugin-qiankun-master/getMicroAppRouteComponent');
|
|
51
|
-
return getMicroAppRouteComponent({ appName: '${appName}', base: '${base}', masterHistoryType: '${masterHistoryType}', routeProps: ${normalizedRouteProps} })
|
|
51
|
+
return getMicroAppRouteComponent({ appName: '${appName}', base: '${base}', routePath: '${route.path}', masterHistoryType: '${masterHistoryType}', routeProps: ${normalizedRouteProps} })
|
|
52
52
|
})()`;
|
|
53
53
|
}
|
|
54
54
|
});
|
|
@@ -113,13 +113,16 @@ export const setMasterOptions = (newOpts) => options = ({ ...options, ...newOpts
|
|
|
113
113
|
});
|
|
114
114
|
}
|
|
115
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
|
+
}
|
|
116
120
|
api.writeTmpFile({
|
|
117
121
|
path: file.replace(/\.tpl$/, ''),
|
|
118
|
-
content:
|
|
122
|
+
content: content
|
|
119
123
|
.replace('__USE_MODEL__', api.isPluginEnable('model')
|
|
120
124
|
? `import { useModel } from '@@/plugin-model'`
|
|
121
125
|
: `const useModel = null;`)
|
|
122
|
-
.replace(/from 'qiankun'/g, `from '${(0, plugin_utils_1.winPath)((0, path_1.dirname)(require.resolve('qiankun/package')))}'`)
|
|
123
126
|
.replace(/from 'lodash\//g, `from '${(0, plugin_utils_1.winPath)((0, path_1.dirname)(require.resolve('lodash/package')))}/`),
|
|
124
127
|
});
|
|
125
128
|
}
|
package/dist/qiankun/slave.js
CHANGED
|
@@ -30,7 +30,10 @@ exports.default = (api) => {
|
|
|
30
30
|
key: 'addExtraModels',
|
|
31
31
|
fn() {
|
|
32
32
|
return [
|
|
33
|
-
|
|
33
|
+
(0, withTmpPath_1.withTmpPath)({
|
|
34
|
+
api,
|
|
35
|
+
path: `qiankunModel.ts#{"namespace":"${constants_1.qiankunStateFromMasterModelNamespace}"}`,
|
|
36
|
+
}),
|
|
34
37
|
];
|
|
35
38
|
},
|
|
36
39
|
});
|
|
@@ -123,36 +126,39 @@ if (!window.__POWERED_BY_QIANKUN__) {
|
|
|
123
126
|
function getFileContent(file) {
|
|
124
127
|
return (0, fs_1.readFileSync)((0, path_1.join)(__dirname, '../../libs/qiankun/slave', file), 'utf-8');
|
|
125
128
|
}
|
|
126
|
-
api.onGenerateFiles(
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
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
|
+
});
|
|
149
154
|
});
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
content: `
|
|
155
|
+
api.writeTmpFile({
|
|
156
|
+
path: 'index.ts',
|
|
157
|
+
content: `
|
|
154
158
|
export { connectMaster } from './connectMaster';
|
|
155
159
|
`,
|
|
156
|
-
|
|
160
|
+
});
|
|
161
|
+
},
|
|
162
|
+
before: 'model',
|
|
157
163
|
});
|
|
158
164
|
};
|
package/dist/qiankun.js
CHANGED
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
|
});
|
|
@@ -12,7 +12,9 @@ export declare class Model {
|
|
|
12
12
|
namespace: string;
|
|
13
13
|
id: string;
|
|
14
14
|
exportName: string;
|
|
15
|
-
|
|
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,9 +22,10 @@ export declare class ModelUtils {
|
|
|
20
22
|
count: number;
|
|
21
23
|
constructor(api: IApi | null, opts: IOpts);
|
|
22
24
|
getAllModels(opts: {
|
|
23
|
-
|
|
25
|
+
sort?: object;
|
|
24
26
|
extraModels: string[];
|
|
25
27
|
}): Model[];
|
|
28
|
+
getSortedNamespaces(models: Model[]): string[];
|
|
26
29
|
getModels(opts: {
|
|
27
30
|
base: string;
|
|
28
31
|
pattern?: string;
|
package/dist/utils/modelUtils.js
CHANGED
|
@@ -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,8 +92,7 @@ class ModelUtils {
|
|
|
61
92
|
getAllModels(opts) {
|
|
62
93
|
// reset count
|
|
63
94
|
this.count = 1;
|
|
64
|
-
|
|
65
|
-
...opts.extraModelsPre,
|
|
95
|
+
const models = [
|
|
66
96
|
...this.getModels({
|
|
67
97
|
base: (0, path_1.join)(this.api.paths.absSrcPath, 'models'),
|
|
68
98
|
pattern: '**/*.{ts,tsx,js,jsx}',
|
|
@@ -77,8 +107,59 @@ class ModelUtils {
|
|
|
77
107
|
}),
|
|
78
108
|
...opts.extraModels,
|
|
79
109
|
].map((file) => {
|
|
80
|
-
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
|
+
}
|
|
81
161
|
});
|
|
162
|
+
return [...new Set(final)];
|
|
82
163
|
}
|
|
83
164
|
getModels(opts) {
|
|
84
165
|
return plugin_utils_1.glob
|
|
@@ -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.
|
|
67
|
-
const childrenRouteHasComponent = route.
|
|
68
|
-
(r: any) => r.
|
|
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
|
-
|
|
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.
|
|
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].
|
|
104
|
-
const found = recursiveSearch(routes[i].
|
|
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.
|
|
127
|
-
found.
|
|
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 = (
|
|
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
|
-
|
|
19
|
-
|
|
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.
|
|
37
|
+
if (!rootRoute.children) {
|
|
38
38
|
return routes;
|
|
39
39
|
}
|
|
40
|
-
return getRootRoutes(rootRoute.
|
|
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.
|
|
57
|
-
route.
|
|
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
|
|
127
|
+
export function patchClientRoutes({ routes }: { routes: any[] }) {
|
|
127
128
|
if (microAppRuntimeRoutes) {
|
|
128
129
|
patchMicroAppRouteComponent(routes);
|
|
129
130
|
}
|
|
@@ -119,6 +119,12 @@ export function genMount(mountElementId: string) {
|
|
|
119
119
|
defer.resolve();
|
|
120
120
|
}
|
|
121
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
|
+
}
|
|
122
128
|
hasMountedAtLeastOnce = true;
|
|
123
129
|
};
|
|
124
130
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umijs/plugins",
|
|
3
|
-
"version": "4.0.0-rc.
|
|
3
|
+
"version": "4.0.0-rc.16",
|
|
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.
|
|
28
|
-
"@umijs/bundler-utils": "4.0.0-rc.
|
|
27
|
+
"@ant-design/pro-layout": "^6.38.0",
|
|
28
|
+
"@umijs/bundler-utils": "4.0.0-rc.16",
|
|
29
29
|
"antd-dayjs-webpack-plugin": "^1.0.6",
|
|
30
|
-
"axios": "^0.
|
|
30
|
+
"axios": "^0.27.2",
|
|
31
31
|
"babel-plugin-import": "^1.13.3",
|
|
32
|
-
"dayjs": "^1.11.
|
|
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.
|
|
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.
|
|
47
|
+
"umi": "4.0.0-rc.16"
|
|
48
48
|
},
|
|
49
49
|
"publishConfig": {
|
|
50
50
|
"access": "public"
|