-
Notifications
You must be signed in to change notification settings - Fork 184
Expand file tree
/
Copy pathindex.ts
More file actions
126 lines (110 loc) · 4.28 KB
/
index.ts
File metadata and controls
126 lines (110 loc) · 4.28 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/* eslint-disable quotes */
import { existsSync } from 'fs';
import { join } from 'path';
// eslint-disable-next-line import/no-unresolved,@typescript-eslint/no-unused-vars
import { IApi, IConfig, IRoute } from 'umi-types';
import { defaultHistoryMode, defaultMasterRootId, testPathWithPrefix, toArray } from '../common';
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import { Options } from '../types';
export default function(api: IApi, options: Options) {
const { registerRuntimeKeyInIndex = false } = options || {};
api.addRuntimePlugin(require.resolve('./runtimePlugin'));
if (!registerRuntimeKeyInIndex) {
api.addRuntimePluginKey('qiankun');
}
api.modifyDefaultConfig(config => ({
...config,
mountElementId: defaultMasterRootId,
disableGlobalVariables: true,
}));
const {
config: { history = defaultHistoryMode },
} = api;
// apps 可能在构建期为空
const { apps = [] } = options || {};
if (apps.length) {
// 获取一组路由中以 basePath 为前缀的路由
const findRouteWithPrefix = (routes: IRoute[], basePath: string): IRoute | null => {
// eslint-disable-next-line no-restricted-syntax
for (const route of routes) {
if (route.path && testPathWithPrefix(basePath, route.path)) return route;
if (route.routes && route.routes.length) {
return findRouteWithPrefix(route.routes, basePath);
}
}
return null;
};
const modifyAppRoutes = (masterHistory: IConfig['history']) => {
api.modifyRoutes(routes => {
const newRoutes = routes.map(route => {
if (route.path === '/' && route.routes && route.routes.length) {
apps.forEach(({ history: slaveHistory = history, base }) => {
// 当子应用的 history mode 跟主应用一致时,为避免出现 404 手动为主应用创建一个 path 为 子应用 rule 的空 div 路由组件
if (slaveHistory === masterHistory) {
const baseConfig = toArray(base);
baseConfig.forEach(basePath => {
const routeWithPrefix = findRouteWithPrefix(routes, basePath);
// 应用没有自己配置过 basePath 相关路由,则自动加入 mock 的路由
if (!routeWithPrefix) {
route.routes!.unshift({
path: basePath,
exact: false,
component: `() => {
if (process.env.NODE_ENV === 'development') {
console.log('${basePath} 404 mock rendered');
}
return React.createElement('div');
}`,
});
} else {
// 若用户已配置过跟应用 base 重名的路由,则强制将该路由 exact 设置为 false,目的是兼容之前遗留的错误用法的场景
routeWithPrefix.exact = false;
}
});
}
});
}
return route;
});
return newRoutes;
});
};
modifyAppRoutes(history);
}
const rootExportsJsFile = join(api.paths.absSrcPath, 'rootExports.js');
const rootExportsTsFile = join(api.paths.absSrcPath, 'rootExports.ts');
const rootExportsJsFileExisted = existsSync(rootExportsJsFile);
const rootExportsFileExisted = rootExportsJsFileExisted || existsSync(rootExportsTsFile);
api.addPageWatcher(rootExportsJsFileExisted ? rootExportsJsFile : rootExportsTsFile);
api.onGenerateFiles(() => {
const rootExports = `
window.g_rootExports = ${rootExportsFileExisted ? `require('@/rootExports')` : `{}`};
`.trim();
api.writeTmpFile('qiankunRootExports.js', rootExports);
api.writeTmpFile(
'subAppsConfig.json',
JSON.stringify({
masterHistory: history,
...options,
}),
);
});
api.writeTmpFile(
'qiankunDefer.js',
`
class Deferred {
constructor() {
this.promise = new Promise(resolve => this.resolve = resolve);
}
}
export const deferred = new Deferred();
export const qiankunStart = deferred.resolve;
`.trim(),
);
api.addUmiExports([
{
specifiers: ['qiankunStart'],
source: '@tmp/qiankunDefer',
},
]);
}