@module-federation/bridge-react 2.3.2 → 2.4.0
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/base.cjs.js +2 -2
- package/dist/base.es.js +2 -2
- package/dist/data-fetch-utils.cjs.js +1 -1
- package/dist/data-fetch-utils.es.js +2 -2
- package/dist/index.cjs.js +2 -2
- package/dist/index.es.js +2 -2
- package/dist/{lazy-load-component-plugin-CqxENGBE.mjs → lazy-load-component-plugin-Bf_HsMyF.mjs} +1 -1
- package/dist/{lazy-load-component-plugin-ZC6dhtcT.js → lazy-load-component-plugin-DZDwZ0Kz.js} +1 -1
- package/dist/lazy-load-component-plugin.cjs.js +2 -2
- package/dist/lazy-load-component-plugin.es.js +2 -2
- package/dist/{prefetch-CFKA0dZg.mjs → prefetch-ByDYONsx.mjs} +14 -7
- package/dist/{prefetch-8e8pqiSo.js → prefetch-DYFX9hl9.js} +14 -7
- package/package.json +9 -5
- package/.turbo/turbo-build.log +0 -85
- package/CHANGELOG.md +0 -833
- package/__tests__/bridge.spec.tsx +0 -160
- package/__tests__/createLazyComponent.spec.tsx +0 -209
- package/__tests__/prefetch.spec.ts +0 -156
- package/__tests__/router.spec.tsx +0 -82
- package/__tests__/setupTests.ts +0 -8
- package/__tests__/util.ts +0 -36
- package/jest.config.ts +0 -21
- package/src/base.ts +0 -50
- package/src/index.ts +0 -50
- package/src/lazy/AwaitDataFetch.tsx +0 -217
- package/src/lazy/constant.ts +0 -30
- package/src/lazy/createLazyComponent.tsx +0 -411
- package/src/lazy/data-fetch/cache.ts +0 -291
- package/src/lazy/data-fetch/call-data-fetch.ts +0 -13
- package/src/lazy/data-fetch/data-fetch-server-middleware.ts +0 -196
- package/src/lazy/data-fetch/index.ts +0 -16
- package/src/lazy/data-fetch/inject-data-fetch.ts +0 -109
- package/src/lazy/data-fetch/prefetch.ts +0 -112
- package/src/lazy/data-fetch/runtime-plugin.ts +0 -115
- package/src/lazy/index.ts +0 -35
- package/src/lazy/logger.ts +0 -6
- package/src/lazy/types.ts +0 -75
- package/src/lazy/utils.ts +0 -375
- package/src/lazy/wrapNoSSR.tsx +0 -10
- package/src/modern-app-env.d.ts +0 -2
- package/src/plugins/lazy-load-component-plugin.spec.ts +0 -21
- package/src/plugins/lazy-load-component-plugin.ts +0 -57
- package/src/provider/context.tsx +0 -4
- package/src/provider/plugin.ts +0 -22
- package/src/provider/versions/bridge-base.tsx +0 -153
- package/src/provider/versions/legacy.ts +0 -87
- package/src/provider/versions/v18.ts +0 -47
- package/src/provider/versions/v19.ts +0 -48
- package/src/remote/RemoteAppWrapper.tsx +0 -108
- package/src/remote/base-component/component.tsx +0 -2
- package/src/remote/base-component/create.tsx +0 -23
- package/src/remote/base-component/index.tsx +0 -10
- package/src/remote/createHelpers.tsx +0 -132
- package/src/remote/router-component/component.tsx +0 -104
- package/src/remote/router-component/create.tsx +0 -23
- package/src/remote/router-component/index.tsx +0 -10
- package/src/router/default.tsx +0 -73
- package/src/router/v5.tsx +0 -43
- package/src/router/v6.tsx +0 -74
- package/src/router/v7.tsx +0 -75
- package/src/types.ts +0 -147
- package/src/utils/index.ts +0 -44
- package/src/v18.ts +0 -9
- package/src/v19.ts +0 -9
- package/tsconfig.json +0 -42
- package/tsconfig.node.json +0 -11
- package/tsconfig.spec.json +0 -26
- package/vite.config.ts +0 -112
- package/vitest.config.ts +0 -27
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Entry point for React 16/17 (legacy) specific bridge components
|
|
3
|
-
* This file provides support for React 16 and 17 versions, using the traditional ReactDOM.render API
|
|
4
|
-
*/
|
|
5
|
-
import type { ProviderFnParams } from '../../types';
|
|
6
|
-
import { createBaseBridgeComponent } from './bridge-base';
|
|
7
|
-
import ReactDOM from 'react-dom';
|
|
8
|
-
import { LoggerInstance } from '../../utils';
|
|
9
|
-
|
|
10
|
-
export interface CreateRootOptions {
|
|
11
|
-
identifierPrefix?: string;
|
|
12
|
-
onRecoverableError?: (error: unknown, errorInfo: unknown) => void;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export interface Root {
|
|
16
|
-
render(children: React.ReactNode): void;
|
|
17
|
-
unmount(): void;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Default createRoot function that automatically detects React version and uses the appropriate API(only support React 16/17, 18)
|
|
22
|
-
*
|
|
23
|
-
* Note: Users can also directly import version-specific bridge components:
|
|
24
|
-
* - import { createBridgeComponent } from '@module-federation/bridge-react'
|
|
25
|
-
* - import { createBridgeComponent } from '@module-federation/bridge-react/v18'
|
|
26
|
-
* - import { createBridgeComponent } from '@module-federation/bridge-react/v19'
|
|
27
|
-
*/
|
|
28
|
-
|
|
29
|
-
export function createReact16Or17Root(
|
|
30
|
-
container: Element | DocumentFragment,
|
|
31
|
-
): Root {
|
|
32
|
-
return {
|
|
33
|
-
render(children: React.ReactNode) {
|
|
34
|
-
/**
|
|
35
|
-
* Detect React version
|
|
36
|
-
*/
|
|
37
|
-
const reactVersion = ReactDOM.version || '';
|
|
38
|
-
const isReact18 = reactVersion.startsWith('18');
|
|
39
|
-
const isReact19 = reactVersion.startsWith('19');
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Throw error for React 19
|
|
43
|
-
*
|
|
44
|
-
* Note: Due to Module Federation sharing mechanism, the actual version detected here
|
|
45
|
-
* might be 18 or 19, even if the application itself uses React 16/17.
|
|
46
|
-
* This happens because in MF environments, different remote modules may share different React versions.
|
|
47
|
-
* The console may throw warnings about version and API mismatches. If you need to resolve these issues,
|
|
48
|
-
* consider disabling the shared configuration for React.
|
|
49
|
-
*/
|
|
50
|
-
if (isReact19) {
|
|
51
|
-
throw new Error(
|
|
52
|
-
`React 19 detected in legacy mode. This is not supported. ` +
|
|
53
|
-
`Please use the version-specific import: ` +
|
|
54
|
-
`import { createBridgeComponent } from '@module-federation/bridge-react/v19'`,
|
|
55
|
-
);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Provide warning for React 18
|
|
60
|
-
*/
|
|
61
|
-
if (isReact18) {
|
|
62
|
-
LoggerInstance.warn(
|
|
63
|
-
`[Bridge-React] React 18 detected in legacy mode. ` +
|
|
64
|
-
`For better compatibility, please use the version-specific import: ` +
|
|
65
|
-
`import { createBridgeComponent } from '@module-federation/bridge-react/v18'`,
|
|
66
|
-
);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// @ts-ignore - React 17's render method is deprecated but still functional
|
|
70
|
-
ReactDOM.render(children, container);
|
|
71
|
-
},
|
|
72
|
-
unmount() {
|
|
73
|
-
ReactDOM.unmountComponentAtNode(container as Element);
|
|
74
|
-
},
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
export function createBridgeComponent<T = any>(
|
|
79
|
-
bridgeInfo: Omit<ProviderFnParams<T>, 'createRoot'>,
|
|
80
|
-
) {
|
|
81
|
-
const fullBridgeInfo = {
|
|
82
|
-
createRoot: createReact16Or17Root,
|
|
83
|
-
...bridgeInfo,
|
|
84
|
-
} as unknown as ProviderFnParams<T>;
|
|
85
|
-
|
|
86
|
-
return createBaseBridgeComponent(fullBridgeInfo);
|
|
87
|
-
}
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Entry point for React 18 specific bridge components
|
|
3
|
-
*/
|
|
4
|
-
import React from 'react';
|
|
5
|
-
import { createRoot as createReactRoot, hydrateRoot } from 'react-dom/client';
|
|
6
|
-
import { createBaseBridgeComponent } from './bridge-base';
|
|
7
|
-
import type { ProviderFnParams } from '../../types';
|
|
8
|
-
|
|
9
|
-
export interface CreateRootOptions {
|
|
10
|
-
identifierPrefix?: string;
|
|
11
|
-
onRecoverableError?: (error: unknown, errorInfo: unknown) => void;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export interface Root {
|
|
15
|
-
render(children: React.ReactNode): void;
|
|
16
|
-
unmount(): void;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function createReact18Root(
|
|
20
|
-
container: Element | DocumentFragment,
|
|
21
|
-
options?: CreateRootOptions,
|
|
22
|
-
): Root {
|
|
23
|
-
return createReactRoot(container, options);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export function hydrateReact18Root(
|
|
27
|
-
container: Element | DocumentFragment,
|
|
28
|
-
initialChildren: React.ReactNode,
|
|
29
|
-
options?: CreateRootOptions,
|
|
30
|
-
) {
|
|
31
|
-
return hydrateRoot(
|
|
32
|
-
container as Element,
|
|
33
|
-
initialChildren as React.ReactElement,
|
|
34
|
-
options,
|
|
35
|
-
);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export function createBridgeComponent<T = any>(
|
|
39
|
-
bridgeInfo: Omit<ProviderFnParams<T>, 'createRoot'>,
|
|
40
|
-
) {
|
|
41
|
-
const fullBridgeInfo = {
|
|
42
|
-
createRoot: createReact18Root,
|
|
43
|
-
...bridgeInfo,
|
|
44
|
-
} as unknown as ProviderFnParams<T>;
|
|
45
|
-
|
|
46
|
-
return createBaseBridgeComponent(fullBridgeInfo);
|
|
47
|
-
}
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Entry point for React 19 specific bridge components
|
|
3
|
-
* This file provides support for React 19 version, using the new ReactDOM.createRoot API
|
|
4
|
-
*/
|
|
5
|
-
import React from 'react';
|
|
6
|
-
import { createRoot, hydrateRoot } from 'react-dom/client';
|
|
7
|
-
import { createBaseBridgeComponent } from './bridge-base';
|
|
8
|
-
import type { ProviderFnParams } from '../../types';
|
|
9
|
-
export interface CreateRootOptions {
|
|
10
|
-
identifierPrefix?: string;
|
|
11
|
-
onRecoverableError?: (error: unknown, errorInfo: unknown) => void;
|
|
12
|
-
transitionCallbacks?: unknown;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export interface Root {
|
|
16
|
-
render(children: React.ReactNode): void;
|
|
17
|
-
unmount(): void;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export function createReact19Root(
|
|
21
|
-
container: Element | DocumentFragment,
|
|
22
|
-
options?: CreateRootOptions,
|
|
23
|
-
): Root {
|
|
24
|
-
return createRoot(container as Element, options);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export function hydrateReact19Root(
|
|
28
|
-
container: Element | DocumentFragment,
|
|
29
|
-
initialChildren: React.ReactNode,
|
|
30
|
-
options?: CreateRootOptions,
|
|
31
|
-
): Root {
|
|
32
|
-
return hydrateRoot(
|
|
33
|
-
container as Element,
|
|
34
|
-
initialChildren as React.ReactElement,
|
|
35
|
-
options,
|
|
36
|
-
);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export function createBridgeComponent<T = any>(
|
|
40
|
-
bridgeInfo: Omit<ProviderFnParams<T>, 'createRoot'>,
|
|
41
|
-
) {
|
|
42
|
-
const fullBridgeInfo = {
|
|
43
|
-
createRoot: createReact19Root,
|
|
44
|
-
...bridgeInfo,
|
|
45
|
-
} as unknown as ProviderFnParams<T>;
|
|
46
|
-
|
|
47
|
-
return createBaseBridgeComponent(fullBridgeInfo);
|
|
48
|
-
}
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shared RemoteAppWrapper component used by both base and router versions
|
|
3
|
-
* This component handles the lifecycle of remote Module Federation apps
|
|
4
|
-
*/
|
|
5
|
-
import React, { useEffect, useRef, useState, forwardRef } from 'react';
|
|
6
|
-
import { LoggerInstance, getRootDomDefaultClassName } from '../utils';
|
|
7
|
-
import { federationRuntime } from '../provider/plugin';
|
|
8
|
-
import { RemoteComponentProps, RemoteAppParams } from '../types';
|
|
9
|
-
|
|
10
|
-
export const RemoteAppWrapper = forwardRef(function (
|
|
11
|
-
props: RemoteAppParams & RemoteComponentProps,
|
|
12
|
-
ref,
|
|
13
|
-
) {
|
|
14
|
-
const {
|
|
15
|
-
moduleName,
|
|
16
|
-
memoryRoute,
|
|
17
|
-
basename,
|
|
18
|
-
providerInfo,
|
|
19
|
-
className,
|
|
20
|
-
style,
|
|
21
|
-
fallback,
|
|
22
|
-
loading,
|
|
23
|
-
...resProps
|
|
24
|
-
} = props;
|
|
25
|
-
|
|
26
|
-
const instance = federationRuntime.instance;
|
|
27
|
-
const rootRef: React.MutableRefObject<HTMLDivElement | null> =
|
|
28
|
-
ref && 'current' in ref
|
|
29
|
-
? (ref as React.MutableRefObject<HTMLDivElement | null>)
|
|
30
|
-
: useRef(null);
|
|
31
|
-
|
|
32
|
-
const renderDom: React.MutableRefObject<HTMLElement | null> = useRef(null);
|
|
33
|
-
const providerInfoRef = useRef<any>(null);
|
|
34
|
-
const [initialized, setInitialized] = useState(false);
|
|
35
|
-
|
|
36
|
-
LoggerInstance.debug(`RemoteAppWrapper instance from props >>>`, instance);
|
|
37
|
-
|
|
38
|
-
// 初始化远程组件
|
|
39
|
-
useEffect(() => {
|
|
40
|
-
if (initialized) return;
|
|
41
|
-
const providerReturn = providerInfo();
|
|
42
|
-
providerInfoRef.current = providerReturn;
|
|
43
|
-
setInitialized(true);
|
|
44
|
-
|
|
45
|
-
return () => {
|
|
46
|
-
if (providerInfoRef.current?.destroy) {
|
|
47
|
-
LoggerInstance.debug(
|
|
48
|
-
`createRemoteAppComponent LazyComponent destroy >>>`,
|
|
49
|
-
{ moduleName, basename, dom: renderDom.current },
|
|
50
|
-
);
|
|
51
|
-
|
|
52
|
-
instance?.bridgeHook?.lifecycle?.beforeBridgeDestroy?.emit({
|
|
53
|
-
moduleName,
|
|
54
|
-
dom: renderDom.current,
|
|
55
|
-
basename,
|
|
56
|
-
memoryRoute,
|
|
57
|
-
fallback,
|
|
58
|
-
...resProps,
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
providerInfoRef.current?.destroy({
|
|
62
|
-
moduleName,
|
|
63
|
-
dom: renderDom.current,
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
instance?.bridgeHook?.lifecycle?.afterBridgeDestroy?.emit({
|
|
67
|
-
moduleName,
|
|
68
|
-
dom: renderDom.current,
|
|
69
|
-
basename,
|
|
70
|
-
memoryRoute,
|
|
71
|
-
fallback,
|
|
72
|
-
...resProps,
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
};
|
|
76
|
-
}, [moduleName]);
|
|
77
|
-
|
|
78
|
-
// trigger render after props updated
|
|
79
|
-
useEffect(() => {
|
|
80
|
-
if (!initialized || !providerInfoRef.current) return;
|
|
81
|
-
|
|
82
|
-
let renderProps = {
|
|
83
|
-
moduleName,
|
|
84
|
-
dom: rootRef.current,
|
|
85
|
-
basename,
|
|
86
|
-
memoryRoute,
|
|
87
|
-
fallback,
|
|
88
|
-
...resProps,
|
|
89
|
-
};
|
|
90
|
-
renderDom.current = rootRef.current;
|
|
91
|
-
|
|
92
|
-
const beforeBridgeRenderRes =
|
|
93
|
-
instance?.bridgeHook?.lifecycle?.beforeBridgeRender?.emit(renderProps) ||
|
|
94
|
-
{};
|
|
95
|
-
// @ts-ignore
|
|
96
|
-
renderProps = { ...renderProps, ...beforeBridgeRenderRes.extraProps };
|
|
97
|
-
providerInfoRef.current.render(renderProps);
|
|
98
|
-
instance?.bridgeHook?.lifecycle?.afterBridgeRender?.emit(renderProps);
|
|
99
|
-
}, [initialized, ...Object.values(props)]);
|
|
100
|
-
|
|
101
|
-
// bridge-remote-root
|
|
102
|
-
const rootComponentClassName = `${getRootDomDefaultClassName(moduleName)} ${className || ''}`;
|
|
103
|
-
return (
|
|
104
|
-
<div className={rootComponentClassName} style={style} ref={rootRef}>
|
|
105
|
-
{loading}
|
|
106
|
-
</div>
|
|
107
|
-
);
|
|
108
|
-
});
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import RemoteApp from './component';
|
|
2
|
-
import {
|
|
3
|
-
createLazyRemoteComponentFactory,
|
|
4
|
-
createRemoteAppComponentFactory,
|
|
5
|
-
createDeprecatedRemoteComponentFactory,
|
|
6
|
-
type LazyRemoteComponentInfo,
|
|
7
|
-
} from '../createHelpers';
|
|
8
|
-
|
|
9
|
-
export type { LazyRemoteComponentInfo };
|
|
10
|
-
|
|
11
|
-
const createLazyRemoteComponent = createLazyRemoteComponentFactory(RemoteApp);
|
|
12
|
-
|
|
13
|
-
export const createRemoteAppComponent =
|
|
14
|
-
createRemoteAppComponentFactory(RemoteApp);
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* @deprecated createRemoteComponent is deprecated, please use createRemoteAppComponent instead!
|
|
18
|
-
*/
|
|
19
|
-
export const createRemoteComponent = createDeprecatedRemoteComponentFactory(
|
|
20
|
-
createRemoteAppComponent,
|
|
21
|
-
);
|
|
22
|
-
|
|
23
|
-
export { createLazyRemoteComponent };
|
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
import React, { forwardRef } from 'react';
|
|
2
|
-
import { ErrorBoundary, FallbackProps } from 'react-error-boundary';
|
|
3
|
-
import { LoggerInstance } from '../utils';
|
|
4
|
-
import {
|
|
5
|
-
RemoteComponentParams,
|
|
6
|
-
RemoteComponentProps,
|
|
7
|
-
RemoteModule,
|
|
8
|
-
} from '../types';
|
|
9
|
-
|
|
10
|
-
export type LazyRemoteComponentInfo<
|
|
11
|
-
T,
|
|
12
|
-
_E extends keyof T,
|
|
13
|
-
> = RemoteComponentParams<T>;
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Creates a factory function for creating lazy remote components
|
|
17
|
-
* @param RemoteApp The RemoteAppWrapper component to use (with or without router)
|
|
18
|
-
*/
|
|
19
|
-
export function createLazyRemoteComponentFactory(
|
|
20
|
-
RemoteApp: React.ComponentType<any>,
|
|
21
|
-
) {
|
|
22
|
-
return function createLazyRemoteComponent<
|
|
23
|
-
T = Record<string, unknown>,
|
|
24
|
-
E extends keyof T = keyof T,
|
|
25
|
-
>(info: LazyRemoteComponentInfo<T, E>) {
|
|
26
|
-
const exportName = info?.export || 'default';
|
|
27
|
-
return React.lazy(async () => {
|
|
28
|
-
LoggerInstance.debug(
|
|
29
|
-
`createRemoteAppComponent LazyComponent create >>>`,
|
|
30
|
-
{
|
|
31
|
-
lazyComponent: info.loader,
|
|
32
|
-
exportName,
|
|
33
|
-
},
|
|
34
|
-
);
|
|
35
|
-
|
|
36
|
-
try {
|
|
37
|
-
const m = (await info.loader()) as RemoteModule;
|
|
38
|
-
// @ts-ignore
|
|
39
|
-
const moduleName = m && m[Symbol.for('mf_module_id')];
|
|
40
|
-
LoggerInstance.debug(
|
|
41
|
-
`createRemoteAppComponent LazyComponent loadRemote info >>>`,
|
|
42
|
-
{ name: moduleName, module: m, exportName },
|
|
43
|
-
);
|
|
44
|
-
|
|
45
|
-
// @ts-ignore
|
|
46
|
-
const exportFn = m[exportName];
|
|
47
|
-
if (exportName in m && typeof exportFn === 'function') {
|
|
48
|
-
const RemoteAppComponent = forwardRef<
|
|
49
|
-
HTMLDivElement,
|
|
50
|
-
RemoteComponentProps
|
|
51
|
-
>((props, ref) => {
|
|
52
|
-
return (
|
|
53
|
-
<RemoteApp
|
|
54
|
-
// change `name` key to `moduleName` to avoid same property `name` passed by user's props which may cause unexpected issues.
|
|
55
|
-
moduleName={moduleName}
|
|
56
|
-
providerInfo={exportFn}
|
|
57
|
-
exportName={info.export || 'default'}
|
|
58
|
-
fallback={info.fallback}
|
|
59
|
-
loading={info.loading}
|
|
60
|
-
ref={ref}
|
|
61
|
-
{...props}
|
|
62
|
-
/>
|
|
63
|
-
);
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
return {
|
|
67
|
-
default: RemoteAppComponent,
|
|
68
|
-
};
|
|
69
|
-
} else {
|
|
70
|
-
LoggerInstance.debug(
|
|
71
|
-
`createRemoteAppComponent LazyComponent module not found >>>`,
|
|
72
|
-
{ name: moduleName, module: m, exportName },
|
|
73
|
-
);
|
|
74
|
-
throw Error(
|
|
75
|
-
`Make sure that ${moduleName} has the correct export when export is ${String(
|
|
76
|
-
exportName,
|
|
77
|
-
)}`,
|
|
78
|
-
);
|
|
79
|
-
}
|
|
80
|
-
} catch (error) {
|
|
81
|
-
throw error;
|
|
82
|
-
}
|
|
83
|
-
});
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Creates a factory function for creating remote app components
|
|
89
|
-
* @param RemoteApp The RemoteAppWrapper component to use (with or without router)
|
|
90
|
-
*/
|
|
91
|
-
export function createRemoteAppComponentFactory(
|
|
92
|
-
RemoteApp: React.ComponentType<any>,
|
|
93
|
-
) {
|
|
94
|
-
const ErrorBoundaryComponent =
|
|
95
|
-
ErrorBoundary as unknown as React.ComponentType<any>;
|
|
96
|
-
const createLazyRemoteComponent = createLazyRemoteComponentFactory(RemoteApp);
|
|
97
|
-
|
|
98
|
-
return function createRemoteAppComponent<
|
|
99
|
-
T = Record<string, unknown>,
|
|
100
|
-
E extends keyof T = keyof T,
|
|
101
|
-
>(info: LazyRemoteComponentInfo<T, E>) {
|
|
102
|
-
const LazyComponent = createLazyRemoteComponent(info);
|
|
103
|
-
return forwardRef<HTMLDivElement, RemoteComponentProps>((props, ref) => {
|
|
104
|
-
return (
|
|
105
|
-
<ErrorBoundaryComponent
|
|
106
|
-
FallbackComponent={
|
|
107
|
-
info.fallback as React.ComponentType<FallbackProps>
|
|
108
|
-
}
|
|
109
|
-
>
|
|
110
|
-
<React.Suspense fallback={info.loading}>
|
|
111
|
-
<LazyComponent {...props} ref={ref} />
|
|
112
|
-
</React.Suspense>
|
|
113
|
-
</ErrorBoundaryComponent>
|
|
114
|
-
);
|
|
115
|
-
});
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* Creates the deprecated createRemoteComponent function
|
|
121
|
-
*/
|
|
122
|
-
export function createDeprecatedRemoteComponentFactory<
|
|
123
|
-
T = Record<string, unknown>,
|
|
124
|
-
E extends keyof T = keyof T,
|
|
125
|
-
>(createFn: (info: LazyRemoteComponentInfo<T, E>) => any) {
|
|
126
|
-
return function createRemoteComponent(info: LazyRemoteComponentInfo<T, E>) {
|
|
127
|
-
LoggerInstance.warn(
|
|
128
|
-
`createRemoteComponent is deprecated, please use createRemoteAppComponent instead!`,
|
|
129
|
-
);
|
|
130
|
-
return createFn(info);
|
|
131
|
-
};
|
|
132
|
-
}
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
import React, { useContext, useEffect, useState, forwardRef } from 'react';
|
|
2
|
-
import * as ReactRouterDOM from 'react-router-dom';
|
|
3
|
-
import { dispatchPopstateEnv } from '@module-federation/bridge-shared';
|
|
4
|
-
import { LoggerInstance, pathJoin } from '../../utils';
|
|
5
|
-
import { RemoteAppWrapper } from '../RemoteAppWrapper';
|
|
6
|
-
|
|
7
|
-
interface ExtraDataProps {
|
|
8
|
-
basename?: string;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export function withRouterData<
|
|
12
|
-
P extends Parameters<typeof RemoteAppWrapper>[0],
|
|
13
|
-
>(
|
|
14
|
-
WrappedComponent: React.ComponentType<P & ExtraDataProps>,
|
|
15
|
-
): React.FC<Omit<P, keyof ExtraDataProps>> {
|
|
16
|
-
const Component = forwardRef(function (props: any, ref) {
|
|
17
|
-
if (props?.basename) {
|
|
18
|
-
return (
|
|
19
|
-
<WrappedComponent {...props} basename={props.basename} ref={ref} />
|
|
20
|
-
);
|
|
21
|
-
}
|
|
22
|
-
let enableDispathPopstate = false;
|
|
23
|
-
let routerContextVal: any;
|
|
24
|
-
try {
|
|
25
|
-
ReactRouterDOM.useLocation();
|
|
26
|
-
enableDispathPopstate = true;
|
|
27
|
-
} catch {
|
|
28
|
-
enableDispathPopstate = false;
|
|
29
|
-
}
|
|
30
|
-
let basename = '/';
|
|
31
|
-
|
|
32
|
-
if (!props.basename && enableDispathPopstate) {
|
|
33
|
-
const ReactRouterDOMAny: any = ReactRouterDOM;
|
|
34
|
-
// Avoid building tools checking references
|
|
35
|
-
const useRouteMatch = ReactRouterDOMAny['use' + 'RouteMatch']; //v5
|
|
36
|
-
const useHistory = ReactRouterDOMAny['use' + 'History']; //v5
|
|
37
|
-
const useHref = ReactRouterDOMAny['use' + 'Href'];
|
|
38
|
-
const UNSAFE_RouteContext = ReactRouterDOMAny['UNSAFE_' + 'RouteContext'];
|
|
39
|
-
|
|
40
|
-
if (UNSAFE_RouteContext /* react-router@6 */) {
|
|
41
|
-
if (useHref) {
|
|
42
|
-
basename = useHref?.('/');
|
|
43
|
-
}
|
|
44
|
-
routerContextVal = useContext(UNSAFE_RouteContext);
|
|
45
|
-
if (
|
|
46
|
-
routerContextVal &&
|
|
47
|
-
routerContextVal.matches &&
|
|
48
|
-
routerContextVal.matches.length > 0
|
|
49
|
-
) {
|
|
50
|
-
const matchIndex = routerContextVal.matches.length - 1;
|
|
51
|
-
const pathnameBase =
|
|
52
|
-
routerContextVal.matches[matchIndex].pathnameBase;
|
|
53
|
-
basename = pathJoin(basename, pathnameBase || '/');
|
|
54
|
-
}
|
|
55
|
-
} /* react-router@5 */ else {
|
|
56
|
-
const match = useRouteMatch?.(); // v5
|
|
57
|
-
if (useHistory /* react-router@5 */) {
|
|
58
|
-
// there is no dynamic switching of the router version in the project
|
|
59
|
-
// so hooks can be used in conditional judgment
|
|
60
|
-
const history = useHistory?.();
|
|
61
|
-
// To be compatible to history@4.10.1 and @5.3.0 we cannot write like this `history.createHref(pathname)`
|
|
62
|
-
basename = history?.createHref?.({ pathname: '/' });
|
|
63
|
-
}
|
|
64
|
-
if (match /* react-router@5 */) {
|
|
65
|
-
basename = pathJoin(basename, match?.path || '/');
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
LoggerInstance.debug(`createRemoteAppComponent withRouterData >>>`, {
|
|
71
|
-
...props,
|
|
72
|
-
basename,
|
|
73
|
-
routerContextVal,
|
|
74
|
-
enableDispathPopstate,
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
if (enableDispathPopstate) {
|
|
78
|
-
const location = ReactRouterDOM.useLocation();
|
|
79
|
-
const [pathname, setPathname] = useState(location.pathname);
|
|
80
|
-
|
|
81
|
-
useEffect(() => {
|
|
82
|
-
if (pathname !== '' && pathname !== location.pathname) {
|
|
83
|
-
LoggerInstance.debug(
|
|
84
|
-
`createRemoteAppComponent dispatchPopstateEnv >>>`,
|
|
85
|
-
{
|
|
86
|
-
name: props.name,
|
|
87
|
-
pathname: location.pathname,
|
|
88
|
-
},
|
|
89
|
-
);
|
|
90
|
-
dispatchPopstateEnv();
|
|
91
|
-
}
|
|
92
|
-
setPathname(location.pathname);
|
|
93
|
-
}, [location]);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
return <WrappedComponent {...(props as P)} basename={basename} ref={ref} />;
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
return forwardRef(function (props, ref) {
|
|
100
|
-
return <Component {...props} ref={ref} />;
|
|
101
|
-
}) as any;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
export default withRouterData(RemoteAppWrapper);
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import RemoteApp from './component';
|
|
2
|
-
import {
|
|
3
|
-
createLazyRemoteComponentFactory,
|
|
4
|
-
createRemoteAppComponentFactory,
|
|
5
|
-
createDeprecatedRemoteComponentFactory,
|
|
6
|
-
type LazyRemoteComponentInfo,
|
|
7
|
-
} from '../createHelpers';
|
|
8
|
-
|
|
9
|
-
export type { LazyRemoteComponentInfo };
|
|
10
|
-
|
|
11
|
-
const createLazyRemoteComponent = createLazyRemoteComponentFactory(RemoteApp);
|
|
12
|
-
|
|
13
|
-
export const createRemoteAppComponent =
|
|
14
|
-
createRemoteAppComponentFactory(RemoteApp);
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* @deprecated createRemoteComponent is deprecated, please use createRemoteAppComponent instead!
|
|
18
|
-
*/
|
|
19
|
-
export const createRemoteComponent = createDeprecatedRemoteComponentFactory(
|
|
20
|
-
createRemoteAppComponent,
|
|
21
|
-
);
|
|
22
|
-
|
|
23
|
-
export { createLazyRemoteComponent };
|
package/src/router/default.tsx
DELETED
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import React, { useContext } from 'react';
|
|
2
|
-
// The upper alias react-router-dom$ into this file avoids the loop
|
|
3
|
-
import * as ReactRouterDom from 'react-router-dom/';
|
|
4
|
-
import { RouterContext } from '../provider/context';
|
|
5
|
-
import { LoggerInstance } from '../utils';
|
|
6
|
-
|
|
7
|
-
function WrapperRouter(
|
|
8
|
-
props:
|
|
9
|
-
| Parameters<typeof ReactRouterDom.BrowserRouter>[0]
|
|
10
|
-
| Parameters<typeof ReactRouterDom.MemoryRouter>[0],
|
|
11
|
-
) {
|
|
12
|
-
const { basename, ...propsRes } = props;
|
|
13
|
-
const routerContextProps = useContext(RouterContext) || {};
|
|
14
|
-
|
|
15
|
-
LoggerInstance.debug(`WrapperRouter info >>>`, {
|
|
16
|
-
...routerContextProps,
|
|
17
|
-
routerContextProps,
|
|
18
|
-
WrapperRouterProps: props,
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
if (routerContextProps?.memoryRoute) {
|
|
22
|
-
return (
|
|
23
|
-
<ReactRouterDom.MemoryRouter
|
|
24
|
-
{...props}
|
|
25
|
-
initialEntries={[routerContextProps?.memoryRoute.entryPath]}
|
|
26
|
-
/>
|
|
27
|
-
);
|
|
28
|
-
}
|
|
29
|
-
return (
|
|
30
|
-
<ReactRouterDom.BrowserRouter
|
|
31
|
-
{...propsRes}
|
|
32
|
-
basename={routerContextProps?.basename || basename}
|
|
33
|
-
/>
|
|
34
|
-
);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function WrapperRouterProvider(
|
|
38
|
-
props: Parameters<typeof ReactRouterDom.RouterProvider>[0],
|
|
39
|
-
) {
|
|
40
|
-
const { router, ...propsRes } = props;
|
|
41
|
-
const routerContextProps = useContext(RouterContext) || {};
|
|
42
|
-
const routers = router.routes;
|
|
43
|
-
LoggerInstance.debug(`WrapperRouterProvider info >>>`, {
|
|
44
|
-
...routerContextProps,
|
|
45
|
-
routerContextProps,
|
|
46
|
-
WrapperRouterProviderProps: props,
|
|
47
|
-
router,
|
|
48
|
-
});
|
|
49
|
-
const RouterProvider = (ReactRouterDom as any)['Router' + 'Provider'];
|
|
50
|
-
const createMemoryRouter = (ReactRouterDom as any)['create' + 'MemoryRouter'];
|
|
51
|
-
const createBrowserRouter = (ReactRouterDom as any)[
|
|
52
|
-
'create' + 'BrowserRouter'
|
|
53
|
-
];
|
|
54
|
-
|
|
55
|
-
if (routerContextProps.memoryRoute) {
|
|
56
|
-
const MemeoryRouterInstance = createMemoryRouter(routers, {
|
|
57
|
-
initialEntries: [routerContextProps?.memoryRoute.entryPath],
|
|
58
|
-
});
|
|
59
|
-
return <RouterProvider router={MemeoryRouterInstance} />;
|
|
60
|
-
} else {
|
|
61
|
-
const BrowserRouterInstance = createBrowserRouter(routers, {
|
|
62
|
-
basename: routerContextProps.basename || router?.basename,
|
|
63
|
-
future: router.future,
|
|
64
|
-
window: router.window,
|
|
65
|
-
});
|
|
66
|
-
return <RouterProvider {...propsRes} router={BrowserRouterInstance} />;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
export * from 'react-router-dom/';
|
|
71
|
-
|
|
72
|
-
export { WrapperRouter as BrowserRouter };
|
|
73
|
-
export { WrapperRouterProvider as RouterProvider };
|