@umijs/plugins 4.0.0-beta.8 → 4.0.0-canary-20240513.3
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/LICENSE +21 -0
- package/README.md +4 -1
- package/dist/access.d.ts +1 -1
- package/dist/access.js +194 -4
- package/dist/{sass.d.ts → analytics.d.ts} +1 -1
- package/dist/analytics.js +118 -0
- package/dist/antd.d.ts +1 -1
- package/dist/antd.js +345 -157
- package/dist/{icons.d.ts → confetti.d.ts} +1 -1
- package/dist/confetti.js +64 -0
- package/dist/constants.d.ts +1 -0
- package/dist/constants.js +30 -0
- package/dist/dva.d.ts +4 -1
- package/dist/dva.js +302 -8
- package/dist/initial-state.d.ts +1 -1
- package/dist/initial-state.js +147 -4
- package/dist/layout.d.ts +1 -1
- package/dist/layout.js +754 -4
- package/dist/locale.d.ts +2 -1
- package/dist/locale.js +257 -4
- package/dist/mf.d.ts +2 -0
- package/dist/mf.js +358 -0
- package/dist/model.d.ts +1 -1
- package/dist/model.js +109 -4
- package/dist/moment2dayjs.d.ts +3 -0
- package/dist/moment2dayjs.js +125 -0
- package/dist/qiankun/constants.d.ts +5 -0
- package/dist/qiankun/constants.js +41 -0
- package/dist/qiankun/master.d.ts +6 -0
- package/dist/qiankun/master.js +236 -0
- package/dist/qiankun/slave.d.ts +3 -0
- package/dist/qiankun/slave.js +345 -0
- package/dist/qiankun.d.ts +1 -1
- package/dist/qiankun.js +51 -4
- package/dist/react-query.d.ts +3 -0
- package/dist/react-query.js +193 -0
- package/dist/request.d.ts +1 -1
- package/dist/request.js +384 -4
- package/dist/styled-components.d.ts +3 -0
- package/dist/styled-components.js +150 -0
- package/dist/tailwindcss.d.ts +3 -0
- package/dist/tailwindcss.js +106 -0
- package/dist/unocss.d.ts +3 -0
- package/dist/unocss.js +71 -0
- package/dist/utils/astUtils.d.ts +3 -0
- package/dist/utils/astUtils.js +49 -0
- package/dist/utils/localeUtils.d.ts +33 -0
- package/dist/utils/localeUtils.js +139 -0
- package/dist/utils/mfUtils.d.ts +14 -0
- package/dist/utils/mfUtils.js +56 -0
- package/dist/utils/modelUtils.d.ts +40 -0
- package/dist/utils/modelUtils.js +286 -0
- package/dist/utils/resolveProjectDep.d.ts +5 -0
- package/dist/utils/resolveProjectDep.js +40 -0
- package/dist/utils/withTmpPath.d.ts +6 -0
- package/dist/utils/withTmpPath.js +39 -0
- package/dist/valtio.d.ts +3 -0
- package/dist/valtio.js +81 -0
- package/libs/dva.tsx +45 -0
- package/libs/model.tsx +180 -0
- package/libs/qiankun/master/AntdErrorBoundary.tsx +34 -0
- package/libs/qiankun/master/AntdLoader.tsx +15 -0
- package/libs/qiankun/master/ErrorBoundary.tsx +7 -0
- package/libs/qiankun/master/MicroApp.tsx +327 -0
- package/libs/qiankun/master/MicroAppWithMemoHistory.tsx +43 -0
- package/libs/qiankun/master/common.ts +172 -0
- package/libs/qiankun/master/constants.ts +19 -0
- package/libs/qiankun/master/getMicroAppRouteComponent.tsx.tpl +45 -0
- package/libs/qiankun/master/masterRuntimePlugin.tsx +161 -0
- package/libs/qiankun/master/routeUtils.ts +26 -0
- package/libs/qiankun/master/types.ts +54 -0
- package/libs/qiankun/slave/MicroAppLink.tsx +122 -0
- package/libs/qiankun/slave/connectMaster.tsx +14 -0
- package/libs/qiankun/slave/constants.ts +5 -0
- package/libs/qiankun/slave/lifecycles.ts +164 -0
- package/libs/qiankun/slave/qiankunModel.ts +18 -0
- package/libs/qiankun/slave/slaveRuntimePlugin.ts +36 -0
- package/package.json +54 -24
- package/templates/antd/runtime.ts.tpl +170 -0
- package/templates/antd/types.d.ts.tpl +17 -0
- package/templates/locale/SelectLang.tpl +502 -0
- package/templates/locale/locale.tpl +82 -0
- package/templates/locale/localeExports.tpl +307 -0
- package/templates/locale/runtime.tpl +34 -0
- package/templates/mf/runtime.ts.tpl +149 -0
- package/dist/access.d.ts.map +0 -1
- package/dist/antd.d.ts.map +0 -1
- package/dist/dva.d.ts.map +0 -1
- package/dist/icons.d.ts.map +0 -1
- package/dist/icons.js +0 -5
- package/dist/initial-state.d.ts.map +0 -1
- package/dist/layout.d.ts.map +0 -1
- package/dist/locale.d.ts.map +0 -1
- package/dist/model.d.ts.map +0 -1
- package/dist/qiankun.d.ts.map +0 -1
- package/dist/request.d.ts.map +0 -1
- package/dist/sass.d.ts.map +0 -1
- package/dist/sass.js +0 -5
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
|
|
4
|
+
import { getPluginManager } from '@@/core/plugin';
|
|
5
|
+
import { prefetchApps } from 'qiankun';
|
|
6
|
+
import { ApplyPluginsType } from 'umi';
|
|
7
|
+
import { insertRoute, noop, patchMicroAppRoute } from './common';
|
|
8
|
+
import { getMasterOptions, setMasterOptions } from './masterOptions';
|
|
9
|
+
import { deepFilterLeafRoutes } from './routeUtils';
|
|
10
|
+
import { MasterOptions, MicroAppRoute } from './types';
|
|
11
|
+
|
|
12
|
+
let microAppRuntimeRoutes: MicroAppRoute[];
|
|
13
|
+
|
|
14
|
+
async function getMasterRuntime() {
|
|
15
|
+
const config = await getPluginManager().applyPlugins({
|
|
16
|
+
key: 'qiankun',
|
|
17
|
+
type: ApplyPluginsType.modify,
|
|
18
|
+
initialValue: {},
|
|
19
|
+
async: true,
|
|
20
|
+
});
|
|
21
|
+
const { master } = config;
|
|
22
|
+
return master || config;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// modify route with "microApp" attribute to use real component
|
|
26
|
+
function patchMicroAppRouteComponent(routes: any[]) {
|
|
27
|
+
const insertRoutes = microAppRuntimeRoutes.filter(
|
|
28
|
+
(r) => r.insert || r.insertBefore || r.appendChildTo,
|
|
29
|
+
);
|
|
30
|
+
// 先处理 insert 配置
|
|
31
|
+
insertRoutes.forEach((route) => {
|
|
32
|
+
insertRoute(routes, route);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
const getRootRoutes = (routes: any[]) => {
|
|
36
|
+
// 重定向根路由不能用作 microAppRuntimeRoutes 的父节点
|
|
37
|
+
const rootRoute = routes.find(
|
|
38
|
+
// 基于是否有 .to props 判断是否为 redirect
|
|
39
|
+
(route) => route.path === '/' && !route.element?.props?.to,
|
|
40
|
+
);
|
|
41
|
+
if (rootRoute) {
|
|
42
|
+
// 如果根路由是叶子节点,则直接返回其父节点
|
|
43
|
+
if (!rootRoute.children?.length) {
|
|
44
|
+
return routes;
|
|
45
|
+
}
|
|
46
|
+
return getRootRoutes(rootRoute.children);
|
|
47
|
+
}
|
|
48
|
+
return routes;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const rootRoutes = getRootRoutes(routes);
|
|
52
|
+
if (rootRoutes) {
|
|
53
|
+
const { routeBindingAlias, base, masterHistoryType } =
|
|
54
|
+
getMasterOptions() as MasterOptions;
|
|
55
|
+
microAppRuntimeRoutes.reverse().forEach((microAppRoute) => {
|
|
56
|
+
const patchRoute = (route: any) => {
|
|
57
|
+
patchMicroAppRoute(route, {
|
|
58
|
+
base,
|
|
59
|
+
masterHistoryType,
|
|
60
|
+
routeBindingAlias,
|
|
61
|
+
});
|
|
62
|
+
if (route.children?.length) {
|
|
63
|
+
route.children.forEach(patchRoute);
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
patchRoute(microAppRoute);
|
|
68
|
+
if (
|
|
69
|
+
!microAppRoute.insert &&
|
|
70
|
+
!microAppRoute.insertBefore &&
|
|
71
|
+
!microAppRoute.appendChildTo
|
|
72
|
+
) {
|
|
73
|
+
rootRoutes.unshift(microAppRoute);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export async function render(oldRender: typeof noop) {
|
|
80
|
+
// 在 ssr 的场景下,直接返回旧的 render
|
|
81
|
+
if (typeof window === 'undefined') {
|
|
82
|
+
return oldRender();
|
|
83
|
+
}
|
|
84
|
+
const runtimeOptions = await getMasterRuntime();
|
|
85
|
+
let masterOptions: MasterOptions = {
|
|
86
|
+
...getMasterOptions(),
|
|
87
|
+
...runtimeOptions,
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const masterApps = masterOptions.apps || [];
|
|
91
|
+
const credentialsApps = masterApps.filter((app) => app.credentials);
|
|
92
|
+
if (credentialsApps.length) {
|
|
93
|
+
const defaultFetch = masterOptions.fetch || window.fetch;
|
|
94
|
+
const fetchWithCredentials = (url: string, init?: RequestInit) => {
|
|
95
|
+
// 如果当前 url 为 credentials 应用的 entry,则为其加上 cors 相关配置
|
|
96
|
+
if (credentialsApps.some((app) => app.entry === url)) {
|
|
97
|
+
return defaultFetch(url, {
|
|
98
|
+
...init,
|
|
99
|
+
mode: 'cors',
|
|
100
|
+
credentials: 'include',
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
return defaultFetch(url, init);
|
|
104
|
+
};
|
|
105
|
+
// 设置新的 fetch
|
|
106
|
+
masterOptions = { ...masterOptions, fetch: fetchWithCredentials };
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// 更新 master options
|
|
110
|
+
setMasterOptions(masterOptions);
|
|
111
|
+
|
|
112
|
+
const { apps = [], routes, ...options } = masterOptions;
|
|
113
|
+
microAppRuntimeRoutes = routes;
|
|
114
|
+
|
|
115
|
+
// 主应用相关的配置注册完毕后即可开启渲染
|
|
116
|
+
const renderData = oldRender();
|
|
117
|
+
|
|
118
|
+
// 未使用 base 配置的可以认为是路由关联或者使用标签装载的应用
|
|
119
|
+
const loadableApps = apps.filter((app) => !app.base);
|
|
120
|
+
if (loadableApps.length) {
|
|
121
|
+
const { prefetch, ...importEntryOpts } = options;
|
|
122
|
+
if (prefetch === 'all') {
|
|
123
|
+
prefetchApps(loadableApps, importEntryOpts);
|
|
124
|
+
} else if (Array.isArray(prefetch)) {
|
|
125
|
+
const specialPrefetchApps = loadableApps.filter(
|
|
126
|
+
(app) => prefetch.indexOf(app.name) !== -1,
|
|
127
|
+
);
|
|
128
|
+
prefetchApps(specialPrefetchApps, importEntryOpts);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// 使用了 base 配置的应用为可注册应用
|
|
133
|
+
// 不再支持
|
|
134
|
+
const registrableApps = apps.filter((app) => app.base);
|
|
135
|
+
if (registrableApps.length) {
|
|
136
|
+
console.error(
|
|
137
|
+
'[plugins/qiankun] 检测到还在使用旧版配置,该配置已移除,请尽快升级到最新配置方式以获得更好的开发体验,详见 https://umijs.org/plugins/plugin-qiankun#%E5%8D%87%E7%BA%A7%E6%8C%87%E5%8D%97',
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return renderData;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export function patchClientRoutes({ routes }: { routes: any[] }) {
|
|
145
|
+
// 在 ssr 的场景下,不执行主应用的 patchClientRoutes
|
|
146
|
+
if (typeof window === 'undefined') {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
const microAppRoutes = [].concat(
|
|
150
|
+
deepFilterLeafRoutes(routes),
|
|
151
|
+
deepFilterLeafRoutes(microAppRuntimeRoutes),
|
|
152
|
+
);
|
|
153
|
+
// 微应用的 routes 存到 masterOptions.microAppRoutes 下以供 MicroAppLink 使用
|
|
154
|
+
const masterOptions = getMasterOptions();
|
|
155
|
+
masterOptions.microAppRoutes = microAppRoutes;
|
|
156
|
+
setMasterOptions(masterOptions);
|
|
157
|
+
|
|
158
|
+
if (microAppRuntimeRoutes) {
|
|
159
|
+
patchMicroAppRouteComponent(routes);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
interface Route extends Record<string, any> {
|
|
2
|
+
children: Route[];
|
|
3
|
+
microApp?: string;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export function deepFilterLeafRoutes(routeTree: Route[]) {
|
|
7
|
+
if (!routeTree?.length) {
|
|
8
|
+
return [];
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const leafRoutes: Route[] = [];
|
|
12
|
+
|
|
13
|
+
const findLeafRoutes = (routes: Route[]) => {
|
|
14
|
+
for (let i = 0; i < routes.length; i++) {
|
|
15
|
+
const r = routes[i];
|
|
16
|
+
if (r.children) {
|
|
17
|
+
findLeafRoutes(r.children);
|
|
18
|
+
}
|
|
19
|
+
leafRoutes.push(r);
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
findLeafRoutes(routeTree);
|
|
24
|
+
|
|
25
|
+
return leafRoutes.filter((r) => r.microApp);
|
|
26
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
import { FrameworkConfiguration, FrameworkLifeCycles } from 'qiankun';
|
|
4
|
+
import type { MicroAppRouteMode } from './constants';
|
|
5
|
+
|
|
6
|
+
type BaseIConfig = any;
|
|
7
|
+
|
|
8
|
+
export type HistoryType = 'browser' | 'hash';
|
|
9
|
+
export type App = {
|
|
10
|
+
name: string;
|
|
11
|
+
entry: string | { scripts: string[]; styles: string[] };
|
|
12
|
+
base?: string | string[];
|
|
13
|
+
history?: HistoryType;
|
|
14
|
+
// 取 entry 时是否需要开启跨域 credentials
|
|
15
|
+
credentials?: boolean;
|
|
16
|
+
props?: any;
|
|
17
|
+
} & Partial<Pick<BaseIConfig, 'mountElementId'>>;
|
|
18
|
+
|
|
19
|
+
export type MicroAppRoute = {
|
|
20
|
+
path: string;
|
|
21
|
+
microApp: string;
|
|
22
|
+
mode: `${MicroAppRouteMode}`;
|
|
23
|
+
} & Record<string, any>;
|
|
24
|
+
|
|
25
|
+
export type MasterOptions = {
|
|
26
|
+
enable?: boolean;
|
|
27
|
+
apps?: App[];
|
|
28
|
+
routes?: MicroAppRoute[];
|
|
29
|
+
lifeCycles?: FrameworkLifeCycles<object>;
|
|
30
|
+
masterHistoryType?: HistoryType;
|
|
31
|
+
base?: string;
|
|
32
|
+
// 关联路由标记的别名,默认 microApp
|
|
33
|
+
routeBindingAlias?: string;
|
|
34
|
+
// 导出的组件别名,默认 MicroApp
|
|
35
|
+
exportComponentAlias?: string;
|
|
36
|
+
// MicroApp 寻址时使用的应用名唯一键,默认是 name
|
|
37
|
+
appNameKeyAlias?: string;
|
|
38
|
+
// 预加载应用阈值
|
|
39
|
+
prefetchThreshold?: number;
|
|
40
|
+
// 子应用默认的错误捕获组件,值为文件路径
|
|
41
|
+
defaultErrorBoundary?: string;
|
|
42
|
+
// 子应用默认的加载动画,值为文件路径
|
|
43
|
+
defaultLoader?: string;
|
|
44
|
+
} & FrameworkConfiguration;
|
|
45
|
+
|
|
46
|
+
export type SlaveOptions = {
|
|
47
|
+
enable?: boolean;
|
|
48
|
+
devSourceMap?: boolean;
|
|
49
|
+
keepOriginalRoutes?: boolean | string;
|
|
50
|
+
shouldNotModifyRuntimePublicPath?: boolean;
|
|
51
|
+
shouldNotModifyDefaultBase?: boolean;
|
|
52
|
+
// library name 是否增加 -[name] 应对多 chunk 场景
|
|
53
|
+
shouldNotAddLibraryChunkName?: boolean;
|
|
54
|
+
};
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
__USE_MODEL__;
|
|
4
|
+
import React, {
|
|
5
|
+
forwardRef,
|
|
6
|
+
FC,
|
|
7
|
+
useImperativeHandle,
|
|
8
|
+
useRef,
|
|
9
|
+
MouseEvent,
|
|
10
|
+
HTMLAttributes,
|
|
11
|
+
useCallback,
|
|
12
|
+
} from 'react';
|
|
13
|
+
import noop from 'lodash/noop';
|
|
14
|
+
import find from 'lodash/find';
|
|
15
|
+
import {
|
|
16
|
+
qiankunStateFromMasterModelNamespace,
|
|
17
|
+
defaultHistoryType,
|
|
18
|
+
} from './constants';
|
|
19
|
+
|
|
20
|
+
const COMPONENT_NAME = 'qiankun-microapp-link';
|
|
21
|
+
|
|
22
|
+
interface MicroAppLinkProps {
|
|
23
|
+
// 应用名称
|
|
24
|
+
name?: string;
|
|
25
|
+
|
|
26
|
+
// 相对路由,不包含应用前缀,以为 `/` 开头
|
|
27
|
+
to: string;
|
|
28
|
+
|
|
29
|
+
// 是否主应用下的路由,默认false
|
|
30
|
+
isMaster?: boolean;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const urlFactory =
|
|
34
|
+
(base: string, routes: Record<string, any>[]) =>
|
|
35
|
+
({ name, to, isMaster }: MicroAppLinkProps) => {
|
|
36
|
+
if (isMaster) {
|
|
37
|
+
return to;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (!to?.startsWith('/')) {
|
|
41
|
+
throw new Error(`[${COMPONENT_NAME}] props "to" should start with "/"`);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const app = find(routes, ({ microApp }) => microApp === name);
|
|
45
|
+
if (!app) {
|
|
46
|
+
console.error(`[${COMPONENT_NAME}] microapp "${name}" is not found`);
|
|
47
|
+
return to;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const prefix =
|
|
51
|
+
base === '/'
|
|
52
|
+
? app.path.replace('/*', '')
|
|
53
|
+
: `${base}${app.path.replace('/*', '')}`;
|
|
54
|
+
return `${prefix}${to}`;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export const MicroAppLink: FC<
|
|
58
|
+
MicroAppLinkProps & HTMLAttributes<HTMLAnchorElement>
|
|
59
|
+
> = forwardRef((props, ref) => {
|
|
60
|
+
const { children, name, to, isMaster = false, ...anchorProps } = props;
|
|
61
|
+
const stateFromMaster = (useModel || noop)(
|
|
62
|
+
qiankunStateFromMasterModelNamespace,
|
|
63
|
+
);
|
|
64
|
+
const linkRef = useRef<HTMLAnchorElement>();
|
|
65
|
+
|
|
66
|
+
const {
|
|
67
|
+
masterHistoryType,
|
|
68
|
+
microAppRoutes,
|
|
69
|
+
base,
|
|
70
|
+
appNameKeyAlias = 'name',
|
|
71
|
+
} = stateFromMaster?.__globalRoutesInfo || {};
|
|
72
|
+
// ref: https://github.com/umijs/plugins/pull/866 基于 name 或 appNameKeyAlias 取到 appName 的逻辑
|
|
73
|
+
const appName =
|
|
74
|
+
name && props[appNameKeyAlias] ? name : props[appNameKeyAlias] || name;
|
|
75
|
+
|
|
76
|
+
const linkProps = { name: appName, to, isMaster };
|
|
77
|
+
const createHerf = urlFactory(base, microAppRoutes);
|
|
78
|
+
|
|
79
|
+
const linkUrl =
|
|
80
|
+
masterHistoryType === 'browser'
|
|
81
|
+
? createHerf(linkProps)
|
|
82
|
+
: `#${createHerf(linkProps)}`;
|
|
83
|
+
|
|
84
|
+
useImperativeHandle(ref, () => linkRef.current);
|
|
85
|
+
|
|
86
|
+
const handleClick = useCallback(
|
|
87
|
+
(e: MouseEvent<HTMLAnchorElement>) => {
|
|
88
|
+
if (anchorProps.onClick) {
|
|
89
|
+
return anchorProps.onClick(e);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// hash路由 使用 a标签 默认行为
|
|
93
|
+
if (masterHistoryType === 'hash') {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (masterHistoryType === 'browser') {
|
|
98
|
+
e?.stopPropagation();
|
|
99
|
+
e?.preventDefault();
|
|
100
|
+
return window.history.pushState({}, '', linkUrl);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
console.error(
|
|
104
|
+
`[${COMPONENT_NAME}] not support "masterHistoryType = '${masterHistoryType}'"`,
|
|
105
|
+
);
|
|
106
|
+
return;
|
|
107
|
+
},
|
|
108
|
+
[anchorProps.onClick, masterHistoryType],
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
return (
|
|
112
|
+
<a
|
|
113
|
+
{...anchorProps}
|
|
114
|
+
ref={linkRef}
|
|
115
|
+
className={`${COMPONENT_NAME} ${anchorProps.className}`}
|
|
116
|
+
href={linkUrl}
|
|
117
|
+
onClick={handleClick}
|
|
118
|
+
>
|
|
119
|
+
{children}
|
|
120
|
+
</a>
|
|
121
|
+
);
|
|
122
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
__USE_MODEL__;
|
|
3
|
+
import React from 'react';
|
|
4
|
+
|
|
5
|
+
const noop = () => {};
|
|
6
|
+
|
|
7
|
+
const connectMaster = <T extends object>(Component: React.ComponentType<T>) => {
|
|
8
|
+
return (props: T, ...rest: any[]) => {
|
|
9
|
+
const masterProps = (useModel || noop)('@@qiankunStateFromMaster') || {};
|
|
10
|
+
return <Component {...props} {...rest} {...masterProps} />;
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export { connectMaster };
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
import { getPluginManager } from '@@/core/plugin';
|
|
3
|
+
import ReactDOM from 'react-dom';
|
|
4
|
+
import { ApplyPluginsType, history, __getRoot } from 'umi';
|
|
5
|
+
import { setModelState } from './qiankunModel';
|
|
6
|
+
|
|
7
|
+
const noop = () => {};
|
|
8
|
+
|
|
9
|
+
type Defer = {
|
|
10
|
+
promise: Promise<any>;
|
|
11
|
+
resolve(value?: any): void;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
// @ts-ignore
|
|
15
|
+
const defer: Defer = {};
|
|
16
|
+
defer.promise = new Promise((resolve) => {
|
|
17
|
+
defer.resolve = resolve;
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
let render = noop;
|
|
21
|
+
let hasMountedAtLeastOnce = false;
|
|
22
|
+
|
|
23
|
+
export default () => defer.promise;
|
|
24
|
+
export const contextOptsStack: any[] = [];
|
|
25
|
+
|
|
26
|
+
function normalizeHistory(
|
|
27
|
+
history?: 'string' | Record<string, any>,
|
|
28
|
+
base?: string,
|
|
29
|
+
) {
|
|
30
|
+
let normalizedHistory: Record<string, any> = {};
|
|
31
|
+
if (base) normalizedHistory.basename = base;
|
|
32
|
+
if (history) {
|
|
33
|
+
if (typeof history === 'string') {
|
|
34
|
+
normalizedHistory.type = history;
|
|
35
|
+
} else {
|
|
36
|
+
normalizedHistory = history;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return normalizedHistory;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async function getSlaveRuntime() {
|
|
44
|
+
const config = await getPluginManager().applyPlugins({
|
|
45
|
+
key: 'qiankun',
|
|
46
|
+
type: ApplyPluginsType.modify,
|
|
47
|
+
initialValue: {},
|
|
48
|
+
async: true,
|
|
49
|
+
});
|
|
50
|
+
// 应用既是 master 又是 slave 的场景,运行时 slave 配置方式为 export const qiankun = { slave: {} }
|
|
51
|
+
const { slave } = config;
|
|
52
|
+
return slave || config;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function genBootstrap(oldRender: typeof noop) {
|
|
56
|
+
return async (props: any) => {
|
|
57
|
+
const slaveRuntime = await getSlaveRuntime();
|
|
58
|
+
if (slaveRuntime.bootstrap) {
|
|
59
|
+
await slaveRuntime.bootstrap(props);
|
|
60
|
+
}
|
|
61
|
+
render = oldRender;
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function genMount(mountElementId: string) {
|
|
66
|
+
return async (props?: any) => {
|
|
67
|
+
// props 有值时说明应用是通过 lifecycle 被主应用唤醒的,而不是独立运行时自己 mount
|
|
68
|
+
if (typeof props !== 'undefined') {
|
|
69
|
+
setModelState(props);
|
|
70
|
+
|
|
71
|
+
const slaveRuntime = await getSlaveRuntime();
|
|
72
|
+
if (slaveRuntime.mount) {
|
|
73
|
+
await slaveRuntime.mount(props);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const { type, ...historyOpts } = normalizeHistory(
|
|
77
|
+
props?.history || {},
|
|
78
|
+
props?.base,
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
// 更新 clientRender 配置
|
|
82
|
+
const clientRenderOpts = {
|
|
83
|
+
callback: () => {
|
|
84
|
+
// 默认开启
|
|
85
|
+
// 如果需要手动控制 loading,通过主应用配置 props.autoSetLoading false 可以关闭
|
|
86
|
+
if (props.autoSetLoading && typeof props.setLoading === 'function') {
|
|
87
|
+
props.setLoading(false);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// 支持将子应用的 history 回传给父应用
|
|
91
|
+
if (typeof props?.onHistoryInit === 'function') {
|
|
92
|
+
props.onHistoryInit(history);
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
// 支持通过 props 注入 container 来限定子应用 mountElementId 的查找范围
|
|
96
|
+
// 避免多个子应用出现在同一主应用时出现 mount 冲突
|
|
97
|
+
rootElement:
|
|
98
|
+
props.container?.querySelector(`#${mountElementId}`) ||
|
|
99
|
+
document.getElementById(mountElementId),
|
|
100
|
+
|
|
101
|
+
basename: props.base,
|
|
102
|
+
|
|
103
|
+
// 支持 MicroAppWithMemoHistory 需要
|
|
104
|
+
historyType: type,
|
|
105
|
+
historyOpts: historyOpts,
|
|
106
|
+
|
|
107
|
+
// 当存在同一个 umi 子应用在同一个页面被多实例渲染的场景时(比如一个页面里,同时展示了这个子应用的多个路由页面)
|
|
108
|
+
// mount 钩子会被调用多次,但是具体什么时候对应的实例开始 render 则是不定的,即它调用 applyPlugins('modifyClientRenderOpts') 的时机是不确定的
|
|
109
|
+
// 为了保证每次 applyPlugins('modifyClientRenderOpts') 调用是生成正确的 history,我们需要这里通过闭包上下文维持 mount 调用时的一些配置信息
|
|
110
|
+
// FIXME 由于 umi history 是全局的,通过 import { history } from 'umi' 调用的永远都是最后一个调用 createHistory 产生的对象,所以这种场景下会存在子应用内部获取 history 时,获取到的是同一个 history 的问题。这种场景下就不能直接从 umi import history,而应该从组件的 props 中取
|
|
111
|
+
// getHistory() {
|
|
112
|
+
// // 动态改变 history
|
|
113
|
+
// const historyOptions = normalizeHistory(props.history, props.base);
|
|
114
|
+
// setCreateHistoryOptions(historyOptions);
|
|
115
|
+
//
|
|
116
|
+
// // FIXME 子应用嵌入模式下不支持热更
|
|
117
|
+
// return createHistory();
|
|
118
|
+
// },
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
contextOptsStack.push(clientRenderOpts);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// 第一次 mount defer 被 resolve 后umi 会自动触发 render,非第一次 mount 则需手动触发
|
|
125
|
+
if (hasMountedAtLeastOnce) {
|
|
126
|
+
render();
|
|
127
|
+
} else {
|
|
128
|
+
defer.resolve();
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
hasMountedAtLeastOnce = true;
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export function genUpdate() {
|
|
136
|
+
return async (props: any) => {
|
|
137
|
+
setModelState(props);
|
|
138
|
+
const slaveRuntime = await getSlaveRuntime();
|
|
139
|
+
if (slaveRuntime.update) {
|
|
140
|
+
await slaveRuntime.update(props);
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export function genUnmount(mountElementId: string) {
|
|
146
|
+
return async (props: any) => {
|
|
147
|
+
const root = __getRoot();
|
|
148
|
+
|
|
149
|
+
// support react 18 unmount
|
|
150
|
+
if (typeof root?.unmount === 'function') {
|
|
151
|
+
root.unmount();
|
|
152
|
+
} else {
|
|
153
|
+
const container = props?.container
|
|
154
|
+
? props.container.querySelector(`#${mountElementId}`)
|
|
155
|
+
: document.getElementById(mountElementId);
|
|
156
|
+
if (container) {
|
|
157
|
+
ReactDOM.unmountComponentAtNode(container);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const slaveRuntime = await getSlaveRuntime();
|
|
162
|
+
if (slaveRuntime.unmount) await slaveRuntime.unmount(props);
|
|
163
|
+
};
|
|
164
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
|
|
4
|
+
let initState: any;
|
|
5
|
+
let setModelState = (val: any) => {
|
|
6
|
+
initState = val;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export default () => {
|
|
10
|
+
const [state, setState] = useState(initState);
|
|
11
|
+
setModelState = (val: any) => {
|
|
12
|
+
initState = val;
|
|
13
|
+
setState(val);
|
|
14
|
+
};
|
|
15
|
+
return state;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export { setModelState };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
import { createHistory } from '@@/core/history';
|
|
3
|
+
import qiankunRender, { contextOptsStack } from './lifecycles';
|
|
4
|
+
|
|
5
|
+
export function render(oldRender: any) {
|
|
6
|
+
// 在 ssr 的场景下,直接返回旧的 render
|
|
7
|
+
if (typeof window === 'undefined') {
|
|
8
|
+
return oldRender();
|
|
9
|
+
}
|
|
10
|
+
return qiankunRender().then(oldRender);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function modifyClientRenderOpts(memo: any) {
|
|
14
|
+
// 每次应用 render 的时候会调 modifyClientRenderOpts,这时尝试从队列中取 render 的配置
|
|
15
|
+
const clientRenderOpts = contextOptsStack.shift();
|
|
16
|
+
const { basename, historyType } = memo;
|
|
17
|
+
|
|
18
|
+
// use ?? instead of ||, incase clientRenderOpts.basename is ''
|
|
19
|
+
// only break when microApp has a config.base and mount path is /*
|
|
20
|
+
const newBasename = clientRenderOpts?.basename ?? basename;
|
|
21
|
+
const newHistoryType = clientRenderOpts?.historyType || historyType;
|
|
22
|
+
|
|
23
|
+
if (newHistoryType !== historyType || newBasename !== basename) {
|
|
24
|
+
clientRenderOpts.history = createHistory({
|
|
25
|
+
type: newHistoryType,
|
|
26
|
+
basename: newBasename,
|
|
27
|
+
...clientRenderOpts.historyOpts,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
return {
|
|
31
|
+
...memo,
|
|
32
|
+
...clientRenderOpts,
|
|
33
|
+
basename: newBasename,
|
|
34
|
+
historyType: newHistoryType,
|
|
35
|
+
};
|
|
36
|
+
}
|