@module-federation/bridge-react 0.10.0 → 0.11.1
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/CHANGELOG.md +19 -0
- package/__tests__/bridge.spec.tsx +32 -0
- package/dist/index.cjs.js +34 -31
- package/dist/index.d.ts +72 -47
- package/dist/index.es.js +34 -31
- package/dist/router-v5.cjs.js +4 -5
- package/dist/router-v6.cjs.js +4 -5
- package/dist/router.cjs.js +4 -5
- package/package.json +5 -5
- package/src/index.ts +3 -1
- package/src/provider/compat.ts +11 -16
- package/src/provider/context.tsx +1 -1
- package/src/provider/create.tsx +24 -32
- package/src/remote/component.tsx +2 -27
- package/src/remote/create.tsx +25 -53
- package/src/types.ts +128 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# @module-federation/bridge-react
|
|
2
2
|
|
|
3
|
+
## 0.11.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 790bdea: fix(bridge-react): export DestroyParams and RenderParams types
|
|
8
|
+
- @module-federation/sdk@0.11.1
|
|
9
|
+
- @module-federation/bridge-shared@0.11.1
|
|
10
|
+
|
|
11
|
+
## 0.11.0
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- 4d67b8f: feat(bridge-react): enable custom createRoot in bridge-react
|
|
16
|
+
- 2d086fc: Fix react-bridge version check for React versions earlier than 16.13.0
|
|
17
|
+
- 4d67b8f: refactor(bridge-react): centralize type definitions into a single file for better maintainability and consistency
|
|
18
|
+
- Updated dependencies [fce107e]
|
|
19
|
+
- @module-federation/sdk@0.11.0
|
|
20
|
+
- @module-federation/bridge-shared@0.11.0
|
|
21
|
+
|
|
3
22
|
## 0.10.0
|
|
4
23
|
|
|
5
24
|
### Minor Changes
|
|
@@ -102,4 +102,36 @@ describe('bridge', () => {
|
|
|
102
102
|
expect(getHtml(container)).toMatch('hello world');
|
|
103
103
|
expect(ref.current).not.toBeNull();
|
|
104
104
|
});
|
|
105
|
+
|
|
106
|
+
it('createRemoteComponent with custom createRoot prop', async () => {
|
|
107
|
+
const renderMock = vi.fn();
|
|
108
|
+
|
|
109
|
+
function Component({ props }: { props?: Record<string, any> }) {
|
|
110
|
+
return <div>life cycle render {props?.msg}</div>;
|
|
111
|
+
}
|
|
112
|
+
const BridgeComponent = createBridgeComponent({
|
|
113
|
+
rootComponent: Component,
|
|
114
|
+
createRoot: () => {
|
|
115
|
+
return {
|
|
116
|
+
render: renderMock,
|
|
117
|
+
unmount: vi.fn(),
|
|
118
|
+
};
|
|
119
|
+
},
|
|
120
|
+
});
|
|
121
|
+
const RemoteComponent = createRemoteComponent({
|
|
122
|
+
loader: async () => {
|
|
123
|
+
return {
|
|
124
|
+
default: BridgeComponent,
|
|
125
|
+
};
|
|
126
|
+
},
|
|
127
|
+
fallback: () => <div></div>,
|
|
128
|
+
loading: <div>loading</div>,
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
const { container } = render(<RemoteComponent />);
|
|
132
|
+
expect(getHtml(container)).toMatch('loading');
|
|
133
|
+
|
|
134
|
+
await sleep(200);
|
|
135
|
+
expect(renderMock).toHaveBeenCalledTimes(1);
|
|
136
|
+
});
|
|
105
137
|
});
|
package/dist/index.cjs.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var _a;
|
|
2
3
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
4
|
const React = require("react");
|
|
4
5
|
const context = require("./context-yPtLY2cD.cjs");
|
|
@@ -140,14 +141,13 @@ const RemoteAppWrapper = React.forwardRef(function(props, ref) {
|
|
|
140
141
|
const [initialized, setInitialized] = React.useState(false);
|
|
141
142
|
context.LoggerInstance.debug(`RemoteAppWrapper instance from props >>>`, instance);
|
|
142
143
|
React.useEffect(() => {
|
|
143
|
-
if (initialized)
|
|
144
|
-
return;
|
|
144
|
+
if (initialized) return;
|
|
145
145
|
const providerReturn = providerInfo();
|
|
146
146
|
providerInfoRef.current = providerReturn;
|
|
147
147
|
setInitialized(true);
|
|
148
148
|
return () => {
|
|
149
|
-
var
|
|
150
|
-
if ((
|
|
149
|
+
var _a2, _b, _c, _d, _e, _f, _g, _h;
|
|
150
|
+
if ((_a2 = providerInfoRef.current) == null ? void 0 : _a2.destroy) {
|
|
151
151
|
context.LoggerInstance.debug(
|
|
152
152
|
`createRemoteComponent LazyComponent destroy >>>`,
|
|
153
153
|
{ moduleName, basename, dom: renderDom.current }
|
|
@@ -176,9 +176,8 @@ const RemoteAppWrapper = React.forwardRef(function(props, ref) {
|
|
|
176
176
|
};
|
|
177
177
|
}, [moduleName]);
|
|
178
178
|
React.useEffect(() => {
|
|
179
|
-
var
|
|
180
|
-
if (!initialized || !providerInfoRef.current)
|
|
181
|
-
return;
|
|
179
|
+
var _a2, _b, _c, _d, _e, _f;
|
|
180
|
+
if (!initialized || !providerInfoRef.current) return;
|
|
182
181
|
let renderProps = {
|
|
183
182
|
moduleName,
|
|
184
183
|
dom: rootRef.current,
|
|
@@ -188,7 +187,7 @@ const RemoteAppWrapper = React.forwardRef(function(props, ref) {
|
|
|
188
187
|
...resProps
|
|
189
188
|
};
|
|
190
189
|
renderDom.current = rootRef.current;
|
|
191
|
-
const beforeBridgeRenderRes = ((_c = (_b = (
|
|
190
|
+
const beforeBridgeRenderRes = ((_c = (_b = (_a2 = instance == null ? void 0 : instance.bridgeHook) == null ? void 0 : _a2.lifecycle) == null ? void 0 : _b.beforeBridgeRender) == null ? void 0 : _c.emit(renderProps)) || {};
|
|
192
191
|
renderProps = { ...renderProps, ...beforeBridgeRenderRes.extraProps };
|
|
193
192
|
providerInfoRef.current.render(renderProps);
|
|
194
193
|
(_f = (_e = (_d = instance == null ? void 0 : instance.bridgeHook) == null ? void 0 : _d.lifecycle) == null ? void 0 : _e.afterBridgeRender) == null ? void 0 : _f.emit(renderProps);
|
|
@@ -198,7 +197,7 @@ const RemoteAppWrapper = React.forwardRef(function(props, ref) {
|
|
|
198
197
|
});
|
|
199
198
|
function withRouterData(WrappedComponent) {
|
|
200
199
|
const Component = React.forwardRef(function(props, ref) {
|
|
201
|
-
var
|
|
200
|
+
var _a2;
|
|
202
201
|
if (props == null ? void 0 : props.basename) {
|
|
203
202
|
return /* @__PURE__ */ React.createElement(WrappedComponent, { ...props, basename: props.basename, ref });
|
|
204
203
|
}
|
|
@@ -231,7 +230,7 @@ function withRouterData(WrappedComponent) {
|
|
|
231
230
|
const match = useRouteMatch == null ? void 0 : useRouteMatch();
|
|
232
231
|
if (useHistory) {
|
|
233
232
|
const history = useHistory == null ? void 0 : useHistory();
|
|
234
|
-
basename = (
|
|
233
|
+
basename = (_a2 = history == null ? void 0 : history.createHref) == null ? void 0 : _a2.call(history, { pathname: "/" });
|
|
235
234
|
}
|
|
236
235
|
if (match) {
|
|
237
236
|
basename = context.pathJoin(basename, (match == null ? void 0 : match.path) || "/");
|
|
@@ -318,13 +317,11 @@ function createLazyRemoteComponent(info) {
|
|
|
318
317
|
}
|
|
319
318
|
function createRemoteComponent(info) {
|
|
320
319
|
const LazyComponent = createLazyRemoteComponent(info);
|
|
321
|
-
return React.forwardRef(
|
|
322
|
-
(props, ref)
|
|
323
|
-
|
|
324
|
-
}
|
|
325
|
-
);
|
|
320
|
+
return React.forwardRef((props, ref) => {
|
|
321
|
+
return /* @__PURE__ */ React.createElement(ErrorBoundary, { FallbackComponent: info.fallback }, /* @__PURE__ */ React.createElement(React.Suspense, { fallback: info.loading }, /* @__PURE__ */ React.createElement(LazyComponent, { ...props, ref })));
|
|
322
|
+
});
|
|
326
323
|
}
|
|
327
|
-
const isReact18 = ReactDOM.version.startsWith("18");
|
|
324
|
+
const isReact18 = (_a = ReactDOM.version) == null ? void 0 : _a.startsWith("18");
|
|
328
325
|
function createRoot(container, options) {
|
|
329
326
|
if (isReact18) {
|
|
330
327
|
return ReactDOM.createRoot(container, options);
|
|
@@ -338,7 +335,10 @@ function createRoot(container, options) {
|
|
|
338
335
|
}
|
|
339
336
|
};
|
|
340
337
|
}
|
|
341
|
-
function createBridgeComponent(
|
|
338
|
+
function createBridgeComponent({
|
|
339
|
+
createRoot: createRoot$1 = createRoot,
|
|
340
|
+
...bridgeInfo
|
|
341
|
+
}) {
|
|
342
342
|
return () => {
|
|
343
343
|
const rootMap = /* @__PURE__ */ new Map();
|
|
344
344
|
const instance = plugin.federationRuntime.instance;
|
|
@@ -360,7 +360,7 @@ function createBridgeComponent(bridgeInfo) {
|
|
|
360
360
|
};
|
|
361
361
|
return {
|
|
362
362
|
async render(info) {
|
|
363
|
-
var
|
|
363
|
+
var _a2, _b, _c, _d, _e, _f;
|
|
364
364
|
context.LoggerInstance.debug(`createBridgeComponent render Info`, info);
|
|
365
365
|
const {
|
|
366
366
|
moduleName,
|
|
@@ -370,7 +370,7 @@ function createBridgeComponent(bridgeInfo) {
|
|
|
370
370
|
fallback,
|
|
371
371
|
...propsInfo
|
|
372
372
|
} = info;
|
|
373
|
-
const beforeBridgeRenderRes = ((_c = (_b = (
|
|
373
|
+
const beforeBridgeRenderRes = ((_c = (_b = (_a2 = instance == null ? void 0 : instance.bridgeHook) == null ? void 0 : _a2.lifecycle) == null ? void 0 : _b.beforeBridgeRender) == null ? void 0 : _c.emit(info)) || {};
|
|
374
374
|
const rootComponentWithErrorBoundary = /* @__PURE__ */ React__namespace.createElement(ErrorBoundary, { FallbackComponent: fallback }, /* @__PURE__ */ React__namespace.createElement(
|
|
375
375
|
RawComponent,
|
|
376
376
|
{
|
|
@@ -382,33 +382,36 @@ function createBridgeComponent(bridgeInfo) {
|
|
|
382
382
|
propsInfo: { ...propsInfo, ...beforeBridgeRenderRes == null ? void 0 : beforeBridgeRenderRes.extraProps }
|
|
383
383
|
}
|
|
384
384
|
));
|
|
385
|
-
if (bridgeInfo
|
|
386
|
-
Promise.resolve(
|
|
387
|
-
bridgeInfo
|
|
388
|
-
).then((root) => rootMap.set(
|
|
385
|
+
if (bridgeInfo.render) {
|
|
386
|
+
await Promise.resolve(
|
|
387
|
+
bridgeInfo.render(rootComponentWithErrorBoundary, dom)
|
|
388
|
+
).then((root) => rootMap.set(dom, root));
|
|
389
389
|
} else {
|
|
390
|
-
let root = rootMap.get(
|
|
390
|
+
let root = rootMap.get(dom);
|
|
391
391
|
if (!root) {
|
|
392
|
-
root = createRoot(
|
|
393
|
-
rootMap.set(
|
|
392
|
+
root = createRoot$1(dom);
|
|
393
|
+
rootMap.set(dom, root);
|
|
394
|
+
}
|
|
395
|
+
if ("render" in root) {
|
|
396
|
+
root.render(rootComponentWithErrorBoundary);
|
|
394
397
|
}
|
|
395
|
-
root.render(rootComponentWithErrorBoundary);
|
|
396
398
|
}
|
|
397
399
|
((_f = (_e = (_d = instance == null ? void 0 : instance.bridgeHook) == null ? void 0 : _d.lifecycle) == null ? void 0 : _e.afterBridgeRender) == null ? void 0 : _f.emit(info)) || {};
|
|
398
400
|
},
|
|
399
401
|
destroy(info) {
|
|
400
|
-
var
|
|
402
|
+
var _a2, _b, _c;
|
|
403
|
+
const { dom } = info;
|
|
401
404
|
context.LoggerInstance.debug(`createBridgeComponent destroy Info`, info);
|
|
402
|
-
const root = rootMap.get(
|
|
405
|
+
const root = rootMap.get(dom);
|
|
403
406
|
if (root) {
|
|
404
407
|
if ("unmount" in root) {
|
|
405
408
|
root.unmount();
|
|
406
409
|
} else {
|
|
407
410
|
ReactDOM.unmountComponentAtNode(root);
|
|
408
411
|
}
|
|
409
|
-
rootMap.delete(
|
|
412
|
+
rootMap.delete(dom);
|
|
410
413
|
}
|
|
411
|
-
(_c = (_b = (
|
|
414
|
+
(_c = (_b = (_a2 = instance == null ? void 0 : instance.bridgeHook) == null ? void 0 : _a2.lifecycle) == null ? void 0 : _b.afterBridgeDestroy) == null ? void 0 : _c.emit(info);
|
|
412
415
|
}
|
|
413
416
|
};
|
|
414
417
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,91 +1,116 @@
|
|
|
1
|
-
import { ComponentType } from 'react';
|
|
2
1
|
import { default as default_2 } from 'react';
|
|
3
|
-
import { ErrorInfo } from 'react';
|
|
4
|
-
import { PropsWithChildren } from 'react';
|
|
5
2
|
import * as React_2 from 'react';
|
|
6
3
|
|
|
7
|
-
export declare function createBridgeComponent<T>(bridgeInfo: ProviderFnParams<T>): () => {
|
|
4
|
+
export declare function createBridgeComponent<T>({ createRoot, ...bridgeInfo }: ProviderFnParams<T>): () => {
|
|
8
5
|
render(info: RenderParams): Promise<void>;
|
|
9
6
|
destroy(info: DestroyParams): void;
|
|
10
7
|
};
|
|
11
8
|
|
|
12
|
-
export declare function createRemoteComponent<T, E extends keyof T>(info: LazyRemoteComponentInfo<T, E>): default_2.ForwardRefExoticComponent<
|
|
9
|
+
export declare function createRemoteComponent<T = Record<string, unknown>, E extends keyof T = keyof T>(info: LazyRemoteComponentInfo<T, E>): default_2.ForwardRefExoticComponent<Omit<RemoteComponentProps<Record<string, unknown>>, "ref"> & default_2.RefAttributes<HTMLDivElement>>;
|
|
13
10
|
|
|
14
11
|
/**
|
|
15
|
-
*
|
|
12
|
+
* Options for creating a React root
|
|
16
13
|
*/
|
|
17
|
-
declare function createRoot(container: Element | DocumentFragment, options?: CreateRootOptions): Root;
|
|
18
|
-
|
|
19
14
|
declare interface CreateRootOptions {
|
|
20
15
|
identifierPrefix?: string;
|
|
21
16
|
onRecoverableError?: (error: unknown) => void;
|
|
22
17
|
transitionCallbacks?: unknown;
|
|
23
18
|
}
|
|
24
19
|
|
|
25
|
-
|
|
20
|
+
/**
|
|
21
|
+
* Parameters for the destroy function
|
|
22
|
+
*/
|
|
23
|
+
export declare interface DestroyParams {
|
|
26
24
|
moduleName: string;
|
|
27
25
|
dom: HTMLElement;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
declare type ErrorBoundaryPropsWithComponent = ErrorBoundarySharedProps & {
|
|
31
|
-
fallback?: never;
|
|
32
|
-
FallbackComponent: ComponentType<FallbackProps>;
|
|
33
|
-
fallbackRender?: never;
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
declare type ErrorBoundarySharedProps = PropsWithChildren<{
|
|
37
|
-
onError?: (error: Error, info: ErrorInfo) => void;
|
|
38
|
-
onReset?: (details: {
|
|
39
|
-
reason: "imperative-api";
|
|
40
|
-
args: any[];
|
|
41
|
-
} | {
|
|
42
|
-
reason: "keys";
|
|
43
|
-
prev: any[] | undefined;
|
|
44
|
-
next: any[] | undefined;
|
|
45
|
-
}) => void;
|
|
46
|
-
resetKeys?: any[];
|
|
47
|
-
}>;
|
|
48
|
-
|
|
49
|
-
declare type FallbackProps = {
|
|
50
|
-
error: any;
|
|
51
|
-
resetErrorBoundary: (...args: any[]) => void;
|
|
52
|
-
};
|
|
26
|
+
}
|
|
53
27
|
|
|
54
|
-
declare type LazyRemoteComponentInfo<T, E extends keyof T> =
|
|
55
|
-
loader: () => Promise<T>;
|
|
56
|
-
loading: default_2.ReactNode;
|
|
57
|
-
fallback: ErrorBoundaryPropsWithComponent['FallbackComponent'];
|
|
58
|
-
export?: E;
|
|
59
|
-
};
|
|
28
|
+
declare type LazyRemoteComponentInfo<T, E extends keyof T> = RemoteComponentParams<T>;
|
|
60
29
|
|
|
61
|
-
|
|
30
|
+
/**
|
|
31
|
+
* Parameters for the provider function
|
|
32
|
+
*/
|
|
33
|
+
declare interface ProviderFnParams<T> {
|
|
62
34
|
rootComponent: React_2.ComponentType<T>;
|
|
63
35
|
render?: (App: React_2.ReactElement, id?: HTMLElement | string) => RootType | Promise<RootType>;
|
|
64
|
-
|
|
36
|
+
createRoot?: (container: Element | DocumentFragment, options?: CreateRootOptions) => Root;
|
|
37
|
+
}
|
|
65
38
|
|
|
39
|
+
/**
|
|
40
|
+
* Parameters for the provider function
|
|
41
|
+
*/
|
|
66
42
|
export declare interface ProviderParams {
|
|
67
43
|
moduleName?: string;
|
|
68
44
|
basename?: string;
|
|
69
45
|
memoryRoute?: {
|
|
70
46
|
entryPath: string;
|
|
47
|
+
initialState?: Record<string, unknown>;
|
|
71
48
|
};
|
|
72
|
-
style?:
|
|
49
|
+
style?: React_2.CSSProperties;
|
|
73
50
|
className?: string;
|
|
74
51
|
}
|
|
75
52
|
|
|
53
|
+
/**
|
|
54
|
+
* Parameters for the remote component loader
|
|
55
|
+
*/
|
|
56
|
+
declare interface RemoteComponentParams<T = Record<string, unknown>, E extends keyof T = keyof T> {
|
|
57
|
+
loader: () => Promise<T>;
|
|
58
|
+
loading: React_2.ReactNode;
|
|
59
|
+
fallback: React_2.ComponentType<{
|
|
60
|
+
error: Error;
|
|
61
|
+
}>;
|
|
62
|
+
export?: E;
|
|
63
|
+
props?: T;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Parameters for the remote component
|
|
68
|
+
*/
|
|
69
|
+
declare interface RemoteComponentProps<T = Record<string, unknown>> {
|
|
70
|
+
props?: T;
|
|
71
|
+
fallback?: React_2.ComponentType<{
|
|
72
|
+
error: Error;
|
|
73
|
+
}>;
|
|
74
|
+
loading?: React_2.ReactNode;
|
|
75
|
+
[key: string]: unknown;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Parameters for the render function, extending ProviderParams
|
|
80
|
+
*/
|
|
76
81
|
export declare interface RenderFnParams extends ProviderParams {
|
|
77
82
|
dom: HTMLElement;
|
|
83
|
+
fallback?: React_2.ComponentType<{
|
|
84
|
+
error: Error;
|
|
85
|
+
}>;
|
|
86
|
+
[key: string]: unknown;
|
|
78
87
|
}
|
|
79
88
|
|
|
80
|
-
|
|
89
|
+
/**
|
|
90
|
+
* Parameters for the render function
|
|
91
|
+
*/
|
|
92
|
+
export declare interface RenderParams {
|
|
93
|
+
moduleName?: string;
|
|
94
|
+
basename?: string;
|
|
95
|
+
memoryRoute?: {
|
|
96
|
+
entryPath: string;
|
|
97
|
+
initialState?: Record<string, unknown>;
|
|
98
|
+
};
|
|
99
|
+
dom: HTMLElement;
|
|
81
100
|
[key: string]: unknown;
|
|
82
|
-
}
|
|
101
|
+
}
|
|
83
102
|
|
|
103
|
+
/**
|
|
104
|
+
* Interface for a React root object
|
|
105
|
+
*/
|
|
84
106
|
declare interface Root {
|
|
85
|
-
render(children:
|
|
107
|
+
render(children: React_2.ReactNode): void;
|
|
86
108
|
unmount(): void;
|
|
87
109
|
}
|
|
88
110
|
|
|
89
|
-
|
|
111
|
+
/**
|
|
112
|
+
* Type for a root element, which can be either an HTMLElement or a React root
|
|
113
|
+
*/
|
|
114
|
+
declare type RootType = HTMLElement | Root;
|
|
90
115
|
|
|
91
116
|
export { }
|
package/dist/index.es.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
var _a;
|
|
1
2
|
import * as React from "react";
|
|
2
3
|
import React__default, { createContext, Component, createElement, forwardRef, useRef, useState, useEffect, useContext } from "react";
|
|
3
4
|
import { L as LoggerInstance, g as getRootDomDefaultClassName, p as pathJoin, R as RouterContext } from "./context-YcJWgOAv.js";
|
|
@@ -121,14 +122,13 @@ const RemoteAppWrapper = forwardRef(function(props, ref) {
|
|
|
121
122
|
const [initialized, setInitialized] = useState(false);
|
|
122
123
|
LoggerInstance.debug(`RemoteAppWrapper instance from props >>>`, instance);
|
|
123
124
|
useEffect(() => {
|
|
124
|
-
if (initialized)
|
|
125
|
-
return;
|
|
125
|
+
if (initialized) return;
|
|
126
126
|
const providerReturn = providerInfo();
|
|
127
127
|
providerInfoRef.current = providerReturn;
|
|
128
128
|
setInitialized(true);
|
|
129
129
|
return () => {
|
|
130
|
-
var
|
|
131
|
-
if ((
|
|
130
|
+
var _a2, _b, _c, _d, _e, _f, _g, _h;
|
|
131
|
+
if ((_a2 = providerInfoRef.current) == null ? void 0 : _a2.destroy) {
|
|
132
132
|
LoggerInstance.debug(
|
|
133
133
|
`createRemoteComponent LazyComponent destroy >>>`,
|
|
134
134
|
{ moduleName, basename, dom: renderDom.current }
|
|
@@ -157,9 +157,8 @@ const RemoteAppWrapper = forwardRef(function(props, ref) {
|
|
|
157
157
|
};
|
|
158
158
|
}, [moduleName]);
|
|
159
159
|
useEffect(() => {
|
|
160
|
-
var
|
|
161
|
-
if (!initialized || !providerInfoRef.current)
|
|
162
|
-
return;
|
|
160
|
+
var _a2, _b, _c, _d, _e, _f;
|
|
161
|
+
if (!initialized || !providerInfoRef.current) return;
|
|
163
162
|
let renderProps = {
|
|
164
163
|
moduleName,
|
|
165
164
|
dom: rootRef.current,
|
|
@@ -169,7 +168,7 @@ const RemoteAppWrapper = forwardRef(function(props, ref) {
|
|
|
169
168
|
...resProps
|
|
170
169
|
};
|
|
171
170
|
renderDom.current = rootRef.current;
|
|
172
|
-
const beforeBridgeRenderRes = ((_c = (_b = (
|
|
171
|
+
const beforeBridgeRenderRes = ((_c = (_b = (_a2 = instance == null ? void 0 : instance.bridgeHook) == null ? void 0 : _a2.lifecycle) == null ? void 0 : _b.beforeBridgeRender) == null ? void 0 : _c.emit(renderProps)) || {};
|
|
173
172
|
renderProps = { ...renderProps, ...beforeBridgeRenderRes.extraProps };
|
|
174
173
|
providerInfoRef.current.render(renderProps);
|
|
175
174
|
(_f = (_e = (_d = instance == null ? void 0 : instance.bridgeHook) == null ? void 0 : _d.lifecycle) == null ? void 0 : _e.afterBridgeRender) == null ? void 0 : _f.emit(renderProps);
|
|
@@ -179,7 +178,7 @@ const RemoteAppWrapper = forwardRef(function(props, ref) {
|
|
|
179
178
|
});
|
|
180
179
|
function withRouterData(WrappedComponent) {
|
|
181
180
|
const Component2 = forwardRef(function(props, ref) {
|
|
182
|
-
var
|
|
181
|
+
var _a2;
|
|
183
182
|
if (props == null ? void 0 : props.basename) {
|
|
184
183
|
return /* @__PURE__ */ React__default.createElement(WrappedComponent, { ...props, basename: props.basename, ref });
|
|
185
184
|
}
|
|
@@ -212,7 +211,7 @@ function withRouterData(WrappedComponent) {
|
|
|
212
211
|
const match = useRouteMatch == null ? void 0 : useRouteMatch();
|
|
213
212
|
if (useHistory) {
|
|
214
213
|
const history = useHistory == null ? void 0 : useHistory();
|
|
215
|
-
basename = (
|
|
214
|
+
basename = (_a2 = history == null ? void 0 : history.createHref) == null ? void 0 : _a2.call(history, { pathname: "/" });
|
|
216
215
|
}
|
|
217
216
|
if (match) {
|
|
218
217
|
basename = pathJoin(basename, (match == null ? void 0 : match.path) || "/");
|
|
@@ -299,13 +298,11 @@ function createLazyRemoteComponent(info) {
|
|
|
299
298
|
}
|
|
300
299
|
function createRemoteComponent(info) {
|
|
301
300
|
const LazyComponent = createLazyRemoteComponent(info);
|
|
302
|
-
return forwardRef(
|
|
303
|
-
(props, ref)
|
|
304
|
-
|
|
305
|
-
}
|
|
306
|
-
);
|
|
301
|
+
return forwardRef((props, ref) => {
|
|
302
|
+
return /* @__PURE__ */ React__default.createElement(ErrorBoundary, { FallbackComponent: info.fallback }, /* @__PURE__ */ React__default.createElement(React__default.Suspense, { fallback: info.loading }, /* @__PURE__ */ React__default.createElement(LazyComponent, { ...props, ref })));
|
|
303
|
+
});
|
|
307
304
|
}
|
|
308
|
-
const isReact18 = ReactDOM.version.startsWith("18");
|
|
305
|
+
const isReact18 = (_a = ReactDOM.version) == null ? void 0 : _a.startsWith("18");
|
|
309
306
|
function createRoot(container, options) {
|
|
310
307
|
if (isReact18) {
|
|
311
308
|
return ReactDOM.createRoot(container, options);
|
|
@@ -319,7 +316,10 @@ function createRoot(container, options) {
|
|
|
319
316
|
}
|
|
320
317
|
};
|
|
321
318
|
}
|
|
322
|
-
function createBridgeComponent(
|
|
319
|
+
function createBridgeComponent({
|
|
320
|
+
createRoot: createRoot$1 = createRoot,
|
|
321
|
+
...bridgeInfo
|
|
322
|
+
}) {
|
|
323
323
|
return () => {
|
|
324
324
|
const rootMap = /* @__PURE__ */ new Map();
|
|
325
325
|
const instance = federationRuntime.instance;
|
|
@@ -341,7 +341,7 @@ function createBridgeComponent(bridgeInfo) {
|
|
|
341
341
|
};
|
|
342
342
|
return {
|
|
343
343
|
async render(info) {
|
|
344
|
-
var
|
|
344
|
+
var _a2, _b, _c, _d, _e, _f;
|
|
345
345
|
LoggerInstance.debug(`createBridgeComponent render Info`, info);
|
|
346
346
|
const {
|
|
347
347
|
moduleName,
|
|
@@ -351,7 +351,7 @@ function createBridgeComponent(bridgeInfo) {
|
|
|
351
351
|
fallback,
|
|
352
352
|
...propsInfo
|
|
353
353
|
} = info;
|
|
354
|
-
const beforeBridgeRenderRes = ((_c = (_b = (
|
|
354
|
+
const beforeBridgeRenderRes = ((_c = (_b = (_a2 = instance == null ? void 0 : instance.bridgeHook) == null ? void 0 : _a2.lifecycle) == null ? void 0 : _b.beforeBridgeRender) == null ? void 0 : _c.emit(info)) || {};
|
|
355
355
|
const rootComponentWithErrorBoundary = /* @__PURE__ */ React.createElement(ErrorBoundary, { FallbackComponent: fallback }, /* @__PURE__ */ React.createElement(
|
|
356
356
|
RawComponent,
|
|
357
357
|
{
|
|
@@ -363,33 +363,36 @@ function createBridgeComponent(bridgeInfo) {
|
|
|
363
363
|
propsInfo: { ...propsInfo, ...beforeBridgeRenderRes == null ? void 0 : beforeBridgeRenderRes.extraProps }
|
|
364
364
|
}
|
|
365
365
|
));
|
|
366
|
-
if (bridgeInfo
|
|
367
|
-
Promise.resolve(
|
|
368
|
-
bridgeInfo
|
|
369
|
-
).then((root) => rootMap.set(
|
|
366
|
+
if (bridgeInfo.render) {
|
|
367
|
+
await Promise.resolve(
|
|
368
|
+
bridgeInfo.render(rootComponentWithErrorBoundary, dom)
|
|
369
|
+
).then((root) => rootMap.set(dom, root));
|
|
370
370
|
} else {
|
|
371
|
-
let root = rootMap.get(
|
|
371
|
+
let root = rootMap.get(dom);
|
|
372
372
|
if (!root) {
|
|
373
|
-
root = createRoot(
|
|
374
|
-
rootMap.set(
|
|
373
|
+
root = createRoot$1(dom);
|
|
374
|
+
rootMap.set(dom, root);
|
|
375
|
+
}
|
|
376
|
+
if ("render" in root) {
|
|
377
|
+
root.render(rootComponentWithErrorBoundary);
|
|
375
378
|
}
|
|
376
|
-
root.render(rootComponentWithErrorBoundary);
|
|
377
379
|
}
|
|
378
380
|
((_f = (_e = (_d = instance == null ? void 0 : instance.bridgeHook) == null ? void 0 : _d.lifecycle) == null ? void 0 : _e.afterBridgeRender) == null ? void 0 : _f.emit(info)) || {};
|
|
379
381
|
},
|
|
380
382
|
destroy(info) {
|
|
381
|
-
var
|
|
383
|
+
var _a2, _b, _c;
|
|
384
|
+
const { dom } = info;
|
|
382
385
|
LoggerInstance.debug(`createBridgeComponent destroy Info`, info);
|
|
383
|
-
const root = rootMap.get(
|
|
386
|
+
const root = rootMap.get(dom);
|
|
384
387
|
if (root) {
|
|
385
388
|
if ("unmount" in root) {
|
|
386
389
|
root.unmount();
|
|
387
390
|
} else {
|
|
388
391
|
ReactDOM.unmountComponentAtNode(root);
|
|
389
392
|
}
|
|
390
|
-
rootMap.delete(
|
|
393
|
+
rootMap.delete(dom);
|
|
391
394
|
}
|
|
392
|
-
(_c = (_b = (
|
|
395
|
+
(_c = (_b = (_a2 = instance == null ? void 0 : instance.bridgeHook) == null ? void 0 : _a2.lifecycle) == null ? void 0 : _b.afterBridgeDestroy) == null ? void 0 : _c.emit(info);
|
|
393
396
|
}
|
|
394
397
|
};
|
|
395
398
|
};
|
package/dist/router-v5.cjs.js
CHANGED
|
@@ -48,9 +48,8 @@ function WraperRouter(props) {
|
|
|
48
48
|
}
|
|
49
49
|
exports.BrowserRouter = WraperRouter;
|
|
50
50
|
Object.keys(ReactRouterDom).forEach((k) => {
|
|
51
|
-
if (k !== "default" && !Object.prototype.hasOwnProperty.call(exports, k))
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
});
|
|
51
|
+
if (k !== "default" && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
|
52
|
+
enumerable: true,
|
|
53
|
+
get: () => ReactRouterDom[k]
|
|
54
|
+
});
|
|
56
55
|
});
|
package/dist/router-v6.cjs.js
CHANGED
|
@@ -77,9 +77,8 @@ function WraperRouterProvider(props) {
|
|
|
77
77
|
exports.BrowserRouter = WraperRouter;
|
|
78
78
|
exports.RouterProvider = WraperRouterProvider;
|
|
79
79
|
Object.keys(ReactRouterDom).forEach((k) => {
|
|
80
|
-
if (k !== "default" && !Object.prototype.hasOwnProperty.call(exports, k))
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
});
|
|
80
|
+
if (k !== "default" && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
|
81
|
+
enumerable: true,
|
|
82
|
+
get: () => ReactRouterDom[k]
|
|
83
|
+
});
|
|
85
84
|
});
|
package/dist/router.cjs.js
CHANGED
|
@@ -75,9 +75,8 @@ function WrapperRouterProvider(props) {
|
|
|
75
75
|
exports.BrowserRouter = WrapperRouter;
|
|
76
76
|
exports.RouterProvider = WrapperRouterProvider;
|
|
77
77
|
Object.keys(ReactRouterDom).forEach((k) => {
|
|
78
|
-
if (k !== "default" && !Object.prototype.hasOwnProperty.call(exports, k))
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
});
|
|
78
|
+
if (k !== "default" && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
|
79
|
+
enumerable: true,
|
|
80
|
+
get: () => ReactRouterDom[k]
|
|
81
|
+
});
|
|
83
82
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@module-federation/bridge-react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.1",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -46,8 +46,8 @@
|
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"@loadable/component": "^5.16.4",
|
|
48
48
|
"react-error-boundary": "^4.1.2",
|
|
49
|
-
"@module-federation/bridge-shared": "0.
|
|
50
|
-
"@module-federation/sdk": "0.
|
|
49
|
+
"@module-federation/bridge-shared": "0.11.1",
|
|
50
|
+
"@module-federation/sdk": "0.11.1"
|
|
51
51
|
},
|
|
52
52
|
"peerDependencies": {
|
|
53
53
|
"react": ">=16.9.0",
|
|
@@ -66,9 +66,9 @@
|
|
|
66
66
|
"react-dom": "18.3.1",
|
|
67
67
|
"react-router-dom": "6.22.3",
|
|
68
68
|
"typescript": "^5.2.2",
|
|
69
|
-
"vite": "^5.
|
|
69
|
+
"vite": "^5.4.12",
|
|
70
70
|
"vite-plugin-dts": "^4.3.0",
|
|
71
|
-
"@module-federation/runtime": "0.
|
|
71
|
+
"@module-federation/runtime": "0.11.1"
|
|
72
72
|
},
|
|
73
73
|
"scripts": {
|
|
74
74
|
"dev": "vite",
|
package/src/index.ts
CHANGED
package/src/provider/compat.ts
CHANGED
|
@@ -1,17 +1,8 @@
|
|
|
1
1
|
import ReactDOM from 'react-dom';
|
|
2
|
+
import { CreateRootOptions, Root } from '../types';
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
onRecoverableError?: (error: unknown) => void;
|
|
6
|
-
transitionCallbacks?: unknown;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
interface Root {
|
|
10
|
-
render(children: React.ReactNode): void;
|
|
11
|
-
unmount(): void;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const isReact18 = ReactDOM.version.startsWith('18');
|
|
4
|
+
// ReactDOM.version is only available in React 16.13.0 and later
|
|
5
|
+
const isReact18 = ReactDOM.version?.startsWith('18');
|
|
15
6
|
|
|
16
7
|
/**
|
|
17
8
|
* Creates a root for a container element compatible with both React 16 and 18
|
|
@@ -29,7 +20,6 @@ export function createRoot(
|
|
|
29
20
|
// For React 16/17, simulate the new root API using render/unmountComponentAtNode
|
|
30
21
|
return {
|
|
31
22
|
render(children: React.ReactNode) {
|
|
32
|
-
// @ts-ignore - React 17's render method is deprecated but still functional
|
|
33
23
|
ReactDOM.render(children, container);
|
|
34
24
|
},
|
|
35
25
|
unmount() {
|
|
@@ -52,11 +42,16 @@ export function hydrateRoot(
|
|
|
52
42
|
return (ReactDOM as any).hydrateRoot(container, initialChildren, options);
|
|
53
43
|
}
|
|
54
44
|
|
|
55
|
-
// For React 16/17, simulate the new root API using hydrate
|
|
45
|
+
// For React 16/17, simulate the new root API using hydrate/unmountComponentAtNode
|
|
56
46
|
return {
|
|
57
47
|
render(children: React.ReactNode) {
|
|
58
|
-
//
|
|
59
|
-
|
|
48
|
+
// For the initial render, use hydrate
|
|
49
|
+
if (children === initialChildren) {
|
|
50
|
+
ReactDOM.hydrate(children, container);
|
|
51
|
+
} else {
|
|
52
|
+
// For subsequent renders, use regular render
|
|
53
|
+
ReactDOM.render(children, container);
|
|
54
|
+
}
|
|
60
55
|
},
|
|
61
56
|
unmount() {
|
|
62
57
|
ReactDOM.unmountComponentAtNode(container);
|
package/src/provider/context.tsx
CHANGED
package/src/provider/create.tsx
CHANGED
|
@@ -2,32 +2,21 @@ import * as React from 'react';
|
|
|
2
2
|
import ReactDOM from 'react-dom';
|
|
3
3
|
import type {
|
|
4
4
|
ProviderParams,
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
ProviderFnParams,
|
|
6
|
+
RootType,
|
|
7
|
+
DestroyParams,
|
|
8
|
+
RenderParams,
|
|
9
|
+
} from '../types';
|
|
7
10
|
import { ErrorBoundary } from 'react-error-boundary';
|
|
8
11
|
import { RouterContext } from './context';
|
|
9
12
|
import { LoggerInstance } from '../utils';
|
|
10
13
|
import { federationRuntime } from './plugin';
|
|
11
|
-
import { createRoot } from './compat';
|
|
14
|
+
import { createRoot as defaultCreateRoot } from './compat';
|
|
12
15
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
moduleName: string;
|
|
18
|
-
dom: HTMLElement;
|
|
19
|
-
};
|
|
20
|
-
type RootType = HTMLElement | ReturnType<typeof createRoot>;
|
|
21
|
-
|
|
22
|
-
export type ProviderFnParams<T> = {
|
|
23
|
-
rootComponent: React.ComponentType<T>;
|
|
24
|
-
render?: (
|
|
25
|
-
App: React.ReactElement,
|
|
26
|
-
id?: HTMLElement | string,
|
|
27
|
-
) => RootType | Promise<RootType>;
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
export function createBridgeComponent<T>(bridgeInfo: ProviderFnParams<T>) {
|
|
16
|
+
export function createBridgeComponent<T>({
|
|
17
|
+
createRoot = defaultCreateRoot,
|
|
18
|
+
...bridgeInfo
|
|
19
|
+
}: ProviderFnParams<T>) {
|
|
31
20
|
return () => {
|
|
32
21
|
const rootMap = new Map<any, RootType>();
|
|
33
22
|
const instance = federationRuntime.instance;
|
|
@@ -80,34 +69,37 @@ export function createBridgeComponent<T>(bridgeInfo: ProviderFnParams<T>) {
|
|
|
80
69
|
</ErrorBoundary>
|
|
81
70
|
);
|
|
82
71
|
|
|
83
|
-
if (bridgeInfo
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
).then((root: RootType) => rootMap.set(info.dom, root));
|
|
72
|
+
if (bridgeInfo.render) {
|
|
73
|
+
await Promise.resolve(
|
|
74
|
+
bridgeInfo.render(rootComponentWithErrorBoundary, dom),
|
|
75
|
+
).then((root: RootType) => rootMap.set(dom, root));
|
|
88
76
|
} else {
|
|
89
|
-
let root = rootMap.get(
|
|
77
|
+
let root = rootMap.get(dom);
|
|
90
78
|
// do not call createRoot multiple times
|
|
91
79
|
if (!root) {
|
|
92
|
-
root = createRoot(
|
|
93
|
-
rootMap.set(
|
|
80
|
+
root = createRoot(dom);
|
|
81
|
+
rootMap.set(dom, root);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if ('render' in root) {
|
|
85
|
+
root.render(rootComponentWithErrorBoundary);
|
|
94
86
|
}
|
|
95
|
-
root.render(rootComponentWithErrorBoundary);
|
|
96
87
|
}
|
|
97
88
|
|
|
98
89
|
instance?.bridgeHook?.lifecycle?.afterBridgeRender?.emit(info) || {};
|
|
99
90
|
},
|
|
100
91
|
|
|
101
92
|
destroy(info: DestroyParams) {
|
|
93
|
+
const { dom } = info;
|
|
102
94
|
LoggerInstance.debug(`createBridgeComponent destroy Info`, info);
|
|
103
|
-
const root = rootMap.get(
|
|
95
|
+
const root = rootMap.get(dom);
|
|
104
96
|
if (root) {
|
|
105
97
|
if ('unmount' in root) {
|
|
106
98
|
root.unmount();
|
|
107
99
|
} else {
|
|
108
100
|
ReactDOM.unmountComponentAtNode(root as HTMLElement);
|
|
109
101
|
}
|
|
110
|
-
rootMap.delete(
|
|
102
|
+
rootMap.delete(dom);
|
|
111
103
|
}
|
|
112
104
|
instance?.bridgeHook?.lifecycle?.afterBridgeDestroy?.emit(info);
|
|
113
105
|
},
|
package/src/remote/component.tsx
CHANGED
|
@@ -6,38 +6,13 @@ import React, {
|
|
|
6
6
|
forwardRef,
|
|
7
7
|
} from 'react';
|
|
8
8
|
import * as ReactRouterDOM from 'react-router-dom';
|
|
9
|
-
import type { ProviderParams } from '@module-federation/bridge-shared';
|
|
10
9
|
import { dispatchPopstateEnv } from '@module-federation/bridge-shared';
|
|
11
|
-
import { ErrorBoundaryPropsWithComponent } from 'react-error-boundary';
|
|
12
10
|
import { LoggerInstance, pathJoin, getRootDomDefaultClassName } from '../utils';
|
|
13
11
|
import { federationRuntime } from '../provider/plugin';
|
|
14
|
-
|
|
15
|
-
declare const __APP_VERSION__: string;
|
|
16
|
-
export interface RenderFnParams extends ProviderParams {
|
|
17
|
-
dom?: any;
|
|
18
|
-
fallback: ErrorBoundaryPropsWithComponent['FallbackComponent'];
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
interface RemoteModule {
|
|
22
|
-
provider: () => {
|
|
23
|
-
render: (
|
|
24
|
-
info: ProviderParams & {
|
|
25
|
-
dom: any;
|
|
26
|
-
},
|
|
27
|
-
) => void;
|
|
28
|
-
destroy: (info: { dom: any }) => void;
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
interface RemoteAppParams {
|
|
33
|
-
moduleName: string;
|
|
34
|
-
providerInfo: NonNullable<RemoteModule['provider']>;
|
|
35
|
-
exportName: string | number | symbol;
|
|
36
|
-
fallback: ErrorBoundaryPropsWithComponent['FallbackComponent'];
|
|
37
|
-
}
|
|
12
|
+
import { RemoteComponentProps, RemoteAppParams } from '../types';
|
|
38
13
|
|
|
39
14
|
const RemoteAppWrapper = forwardRef(function (
|
|
40
|
-
props: RemoteAppParams &
|
|
15
|
+
props: RemoteAppParams & RemoteComponentProps,
|
|
41
16
|
ref,
|
|
42
17
|
) {
|
|
43
18
|
const {
|
package/src/remote/create.tsx
CHANGED
|
@@ -1,33 +1,19 @@
|
|
|
1
1
|
import React, { forwardRef } from 'react';
|
|
2
|
-
import {
|
|
3
|
-
ErrorBoundary,
|
|
4
|
-
ErrorBoundaryPropsWithComponent,
|
|
5
|
-
} from 'react-error-boundary';
|
|
2
|
+
import { ErrorBoundary } from 'react-error-boundary';
|
|
6
3
|
import { LoggerInstance } from '../utils';
|
|
7
4
|
import RemoteApp from './component';
|
|
8
|
-
import
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
interface RemoteModule {
|
|
15
|
-
provider: () => {
|
|
16
|
-
render: (info: RenderFnParams) => void;
|
|
17
|
-
destroy: (info: { dom: any }) => void;
|
|
18
|
-
};
|
|
19
|
-
}
|
|
5
|
+
import {
|
|
6
|
+
RemoteComponentParams,
|
|
7
|
+
RemoteComponentProps,
|
|
8
|
+
RemoteModule,
|
|
9
|
+
} from '../types';
|
|
20
10
|
|
|
21
|
-
type LazyRemoteComponentInfo<T, E extends keyof T> =
|
|
22
|
-
loader: () => Promise<T>;
|
|
23
|
-
loading: React.ReactNode;
|
|
24
|
-
fallback: ErrorBoundaryPropsWithComponent['FallbackComponent'];
|
|
25
|
-
export?: E;
|
|
26
|
-
};
|
|
11
|
+
type LazyRemoteComponentInfo<T, E extends keyof T> = RemoteComponentParams<T>;
|
|
27
12
|
|
|
28
|
-
function createLazyRemoteComponent<
|
|
29
|
-
|
|
30
|
-
|
|
13
|
+
function createLazyRemoteComponent<
|
|
14
|
+
T = Record<string, unknown>,
|
|
15
|
+
E extends keyof T = keyof T,
|
|
16
|
+
>(info: LazyRemoteComponentInfo<T, E>) {
|
|
31
17
|
const exportName = info?.export || 'default';
|
|
32
18
|
return React.lazy(async () => {
|
|
33
19
|
LoggerInstance.debug(`createRemoteComponent LazyComponent create >>>`, {
|
|
@@ -49,10 +35,7 @@ function createLazyRemoteComponent<T, E extends keyof T>(
|
|
|
49
35
|
if (exportName in m && typeof exportFn === 'function') {
|
|
50
36
|
const RemoteAppComponent = forwardRef<
|
|
51
37
|
HTMLDivElement,
|
|
52
|
-
|
|
53
|
-
basename?: ProviderParams['basename'];
|
|
54
|
-
memoryRoute?: ProviderParams['memoryRoute'];
|
|
55
|
-
}
|
|
38
|
+
RemoteComponentProps
|
|
56
39
|
>((props, ref) => {
|
|
57
40
|
return (
|
|
58
41
|
<RemoteApp
|
|
@@ -87,29 +70,18 @@ function createLazyRemoteComponent<T, E extends keyof T>(
|
|
|
87
70
|
});
|
|
88
71
|
}
|
|
89
72
|
|
|
90
|
-
export function createRemoteComponent<
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
? ReturnType<T[E]>
|
|
95
|
-
: never;
|
|
96
|
-
|
|
97
|
-
type RawComponentType = '__BRIDGE_FN__' extends keyof ExportType
|
|
98
|
-
? ExportType['__BRIDGE_FN__'] extends (...args: any) => any
|
|
99
|
-
? Parameters<ExportType['__BRIDGE_FN__']>[0]
|
|
100
|
-
: {}
|
|
101
|
-
: {};
|
|
102
|
-
|
|
73
|
+
export function createRemoteComponent<
|
|
74
|
+
T = Record<string, unknown>,
|
|
75
|
+
E extends keyof T = keyof T,
|
|
76
|
+
>(info: LazyRemoteComponentInfo<T, E>) {
|
|
103
77
|
const LazyComponent = createLazyRemoteComponent(info);
|
|
104
|
-
return forwardRef<HTMLDivElement,
|
|
105
|
-
(
|
|
106
|
-
|
|
107
|
-
<
|
|
108
|
-
<
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
},
|
|
114
|
-
);
|
|
78
|
+
return forwardRef<HTMLDivElement, RemoteComponentProps>((props, ref) => {
|
|
79
|
+
return (
|
|
80
|
+
<ErrorBoundary FallbackComponent={info.fallback}>
|
|
81
|
+
<React.Suspense fallback={info.loading}>
|
|
82
|
+
<LazyComponent {...props} ref={ref} />
|
|
83
|
+
</React.Suspense>
|
|
84
|
+
</ErrorBoundary>
|
|
85
|
+
);
|
|
86
|
+
});
|
|
115
87
|
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { ErrorBoundaryPropsWithComponent } from 'react-error-boundary';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Options for creating a React root
|
|
6
|
+
*/
|
|
7
|
+
export interface CreateRootOptions {
|
|
8
|
+
identifierPrefix?: string;
|
|
9
|
+
onRecoverableError?: (error: unknown) => void;
|
|
10
|
+
transitionCallbacks?: unknown;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Interface for a React root object
|
|
15
|
+
*/
|
|
16
|
+
export interface Root {
|
|
17
|
+
render(children: React.ReactNode): void;
|
|
18
|
+
unmount(): void;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Type for a root element, which can be either an HTMLElement or a React root
|
|
23
|
+
*/
|
|
24
|
+
export type RootType = HTMLElement | Root;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Parameters for the render function
|
|
28
|
+
*/
|
|
29
|
+
export interface RenderParams {
|
|
30
|
+
moduleName?: string;
|
|
31
|
+
basename?: string;
|
|
32
|
+
memoryRoute?: {
|
|
33
|
+
entryPath: string;
|
|
34
|
+
initialState?: Record<string, unknown>;
|
|
35
|
+
};
|
|
36
|
+
dom: HTMLElement;
|
|
37
|
+
[key: string]: unknown;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Parameters for the destroy function
|
|
42
|
+
*/
|
|
43
|
+
export interface DestroyParams {
|
|
44
|
+
moduleName: string;
|
|
45
|
+
dom: HTMLElement;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Parameters for the provider function
|
|
50
|
+
*/
|
|
51
|
+
export interface ProviderParams {
|
|
52
|
+
moduleName?: string;
|
|
53
|
+
basename?: string;
|
|
54
|
+
memoryRoute?: {
|
|
55
|
+
entryPath: string;
|
|
56
|
+
initialState?: Record<string, unknown>;
|
|
57
|
+
};
|
|
58
|
+
style?: React.CSSProperties;
|
|
59
|
+
className?: string;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Parameters for the render function, extending ProviderParams
|
|
64
|
+
*/
|
|
65
|
+
export interface RenderFnParams extends ProviderParams {
|
|
66
|
+
dom: HTMLElement;
|
|
67
|
+
fallback?: React.ComponentType<{ error: Error }>;
|
|
68
|
+
[key: string]: unknown;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Parameters for the provider function
|
|
73
|
+
*/
|
|
74
|
+
export interface ProviderFnParams<T> {
|
|
75
|
+
rootComponent: React.ComponentType<T>;
|
|
76
|
+
render?: (
|
|
77
|
+
App: React.ReactElement,
|
|
78
|
+
id?: HTMLElement | string,
|
|
79
|
+
) => RootType | Promise<RootType>;
|
|
80
|
+
createRoot?: (
|
|
81
|
+
container: Element | DocumentFragment,
|
|
82
|
+
options?: CreateRootOptions,
|
|
83
|
+
) => Root;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Parameters for the remote component
|
|
88
|
+
*/
|
|
89
|
+
export interface RemoteComponentProps<T = Record<string, unknown>> {
|
|
90
|
+
props?: T;
|
|
91
|
+
fallback?: React.ComponentType<{ error: Error }>;
|
|
92
|
+
loading?: React.ReactNode;
|
|
93
|
+
[key: string]: unknown;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Parameters for the remote component loader
|
|
98
|
+
*/
|
|
99
|
+
export interface RemoteComponentParams<
|
|
100
|
+
T = Record<string, unknown>,
|
|
101
|
+
E extends keyof T = keyof T,
|
|
102
|
+
> {
|
|
103
|
+
loader: () => Promise<T>;
|
|
104
|
+
loading: React.ReactNode;
|
|
105
|
+
fallback: React.ComponentType<{ error: Error }>;
|
|
106
|
+
export?: E;
|
|
107
|
+
props?: T;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Interface for a remote module provider
|
|
112
|
+
*/
|
|
113
|
+
export interface RemoteModule {
|
|
114
|
+
provider: () => {
|
|
115
|
+
render: (info: RenderFnParams) => void;
|
|
116
|
+
destroy: (info: { dom: any }) => void;
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Parameters for a remote app component
|
|
122
|
+
*/
|
|
123
|
+
export interface RemoteAppParams extends ProviderParams {
|
|
124
|
+
moduleName: string;
|
|
125
|
+
providerInfo: NonNullable<RemoteModule['provider']>;
|
|
126
|
+
exportName: string | number | symbol;
|
|
127
|
+
fallback: ErrorBoundaryPropsWithComponent['FallbackComponent'];
|
|
128
|
+
}
|