@module-federation/bridge-react 0.0.0-next-20240726084328 → 0.0.0-next-20240731105745
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 +16 -2
- package/__tests__/bridge.spec.tsx +75 -4
- package/__tests__/util.ts +18 -0
- package/dist/index.cjs.js +36 -18
- package/dist/index.es.js +36 -18
- package/package.json +2 -2
- package/src/create.tsx +11 -6
- package/src/provider.tsx +22 -14
- package/src/remote/index.tsx +36 -17
package/CHANGELOG.md
CHANGED
|
@@ -1,10 +1,24 @@
|
|
|
1
1
|
# @module-federation/bridge-react
|
|
2
2
|
|
|
3
|
-
## 0.0.0-next-
|
|
3
|
+
## 0.0.0-next-20240731105745
|
|
4
4
|
|
|
5
5
|
### Patch Changes
|
|
6
6
|
|
|
7
|
-
- @module-federation/bridge
|
|
7
|
+
- 67fa05b: feat(@module-federation/bridge): optimize @module-federation/bridge package
|
|
8
|
+
- Updated dependencies [67fa05b]
|
|
9
|
+
- @module-federation/bridge-shared@0.0.0-next-20240731105745
|
|
10
|
+
|
|
11
|
+
## 0.3.3
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- @module-federation/bridge-shared@0.3.3
|
|
16
|
+
|
|
17
|
+
## 0.3.2
|
|
18
|
+
|
|
19
|
+
### Patch Changes
|
|
20
|
+
|
|
21
|
+
- @module-federation/bridge-shared@0.3.2
|
|
8
22
|
|
|
9
23
|
## 0.3.1
|
|
10
24
|
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
screen,
|
|
9
9
|
waitFor,
|
|
10
10
|
} from '@testing-library/react';
|
|
11
|
-
import { createContainer, getHtml, sleep } from './util';
|
|
11
|
+
import { createContainer, createCustomContainer, getHtml, sleep } from './util';
|
|
12
12
|
|
|
13
13
|
describe('bridge', () => {
|
|
14
14
|
let containerInfo: ReturnType<typeof createContainer>;
|
|
@@ -45,8 +45,8 @@ describe('bridge', () => {
|
|
|
45
45
|
});
|
|
46
46
|
|
|
47
47
|
it('createRemoteComponent', async () => {
|
|
48
|
-
function Component(
|
|
49
|
-
return <div>life cycle render {
|
|
48
|
+
function Component({ props }: { props?: Record<string, any> }) {
|
|
49
|
+
return <div>life cycle render {props?.msg}</div>;
|
|
50
50
|
}
|
|
51
51
|
const BridgeComponent = createBridgeComponent({
|
|
52
52
|
rootComponent: Component,
|
|
@@ -61,11 +61,82 @@ describe('bridge', () => {
|
|
|
61
61
|
loading: <div>loading</div>,
|
|
62
62
|
});
|
|
63
63
|
|
|
64
|
-
const { container } = render(
|
|
64
|
+
const { container } = render(
|
|
65
|
+
<RemoteComponent props={{ msg: 'hello world' }} />,
|
|
66
|
+
);
|
|
67
|
+
expect(getHtml(container)).toMatch('loading');
|
|
68
|
+
|
|
69
|
+
await sleep(200);
|
|
70
|
+
expect(getHtml(container)).toMatch('life cycle render');
|
|
71
|
+
expect(getHtml(container)).toMatch('hello world');
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('createRemoteComponent with dom provided, will render on the provided dom', async () => {
|
|
75
|
+
containerInfo = createCustomContainer();
|
|
76
|
+
|
|
77
|
+
function Component({ props }: { props?: Record<string, any> }) {
|
|
78
|
+
return <div>life cycle render {props?.msg}</div>;
|
|
79
|
+
}
|
|
80
|
+
const BridgeComponent = createBridgeComponent({
|
|
81
|
+
rootComponent: Component,
|
|
82
|
+
});
|
|
83
|
+
const RemoteComponent = createRemoteComponent({
|
|
84
|
+
loader: async () => {
|
|
85
|
+
return {
|
|
86
|
+
default: BridgeComponent,
|
|
87
|
+
};
|
|
88
|
+
},
|
|
89
|
+
fallback: () => <div></div>,
|
|
90
|
+
loading: <div>loading</div>,
|
|
91
|
+
dom: '#container-custom',
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
const { container } = render(
|
|
95
|
+
<RemoteComponent props={{ msg: 'hello there' }} />,
|
|
96
|
+
);
|
|
97
|
+
expect(getHtml(container)).toMatch('loading');
|
|
98
|
+
|
|
99
|
+
await sleep(200);
|
|
100
|
+
|
|
101
|
+
const element = screen.getByTestId('container-custom');
|
|
102
|
+
expect(element.children.length).toBeGreaterThan(0);
|
|
103
|
+
expect(element.innerHTML).toContain('life cycle render');
|
|
104
|
+
expect(element.innerHTML).toContain('hello there');
|
|
105
|
+
|
|
106
|
+
const elementDefault = screen.getByTestId('container');
|
|
107
|
+
expect(elementDefault.children.length).toBe(0);
|
|
108
|
+
expect(elementDefault.innerHTML).toContain('');
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it('createRemoteComponent and obtain ref property', async () => {
|
|
112
|
+
const ref = {
|
|
113
|
+
current: null,
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
function Component({ props }: { props?: Record<string, any> }) {
|
|
117
|
+
return <div>life cycle render {props?.msg}</div>;
|
|
118
|
+
}
|
|
119
|
+
const BridgeComponent = createBridgeComponent({
|
|
120
|
+
rootComponent: Component,
|
|
121
|
+
});
|
|
122
|
+
const RemoteComponent = createRemoteComponent({
|
|
123
|
+
loader: async () => {
|
|
124
|
+
return {
|
|
125
|
+
default: BridgeComponent,
|
|
126
|
+
};
|
|
127
|
+
},
|
|
128
|
+
fallback: () => <div></div>,
|
|
129
|
+
loading: <div>loading</div>,
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
const { container } = render(
|
|
133
|
+
<RemoteComponent ref={ref} props={{ msg: 'hello world' }} />,
|
|
134
|
+
);
|
|
65
135
|
expect(getHtml(container)).toMatch('loading');
|
|
66
136
|
|
|
67
137
|
await sleep(200);
|
|
68
138
|
expect(getHtml(container)).toMatch('life cycle render');
|
|
69
139
|
expect(getHtml(container)).toMatch('hello world');
|
|
140
|
+
expect(ref.current).not.toBeNull();
|
|
70
141
|
});
|
|
71
142
|
});
|
package/__tests__/util.ts
CHANGED
|
@@ -12,6 +12,24 @@ export async function sleep(time: number) {
|
|
|
12
12
|
export function createContainer() {
|
|
13
13
|
const container = document.createElement('div');
|
|
14
14
|
container.setAttribute('id', 'container');
|
|
15
|
+
container.setAttribute('data-testid', 'container');
|
|
16
|
+
|
|
17
|
+
container.setAttribute('background', 'rgb(255, 112, 127)');
|
|
18
|
+
|
|
19
|
+
document.body.appendChild(container);
|
|
20
|
+
|
|
21
|
+
return {
|
|
22
|
+
clean: () => {
|
|
23
|
+
document.body.removeChild(container);
|
|
24
|
+
},
|
|
25
|
+
container,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function createCustomContainer() {
|
|
30
|
+
const container = document.createElement('div');
|
|
31
|
+
container.setAttribute('id', 'container-custom');
|
|
32
|
+
container.setAttribute('data-testid', 'container-custom');
|
|
15
33
|
document.body.appendChild(container);
|
|
16
34
|
|
|
17
35
|
return {
|
package/dist/index.cjs.js
CHANGED
|
@@ -138,14 +138,16 @@ const RemoteAppWrapper = React.forwardRef(function(props, ref) {
|
|
|
138
138
|
providerInfoRef.current = providerReturn;
|
|
139
139
|
let domElement = null;
|
|
140
140
|
if (dom) {
|
|
141
|
-
domElement = document.
|
|
141
|
+
domElement = document.querySelector(dom);
|
|
142
|
+
if (!domElement || !(domElement instanceof HTMLElement)) {
|
|
143
|
+
throw new Error(`Invalid dom: ${dom}`);
|
|
144
|
+
}
|
|
142
145
|
rootRef.current = domElement;
|
|
143
146
|
} else {
|
|
144
147
|
domElement = rootRef.current;
|
|
145
148
|
}
|
|
146
149
|
const renderProps = {
|
|
147
150
|
name,
|
|
148
|
-
// dom: rootRef.current,
|
|
149
151
|
dom: domElement,
|
|
150
152
|
basename,
|
|
151
153
|
memoryRoute,
|
|
@@ -174,9 +176,16 @@ const RemoteAppWrapper = React.forwardRef(function(props, ref) {
|
|
|
174
176
|
});
|
|
175
177
|
};
|
|
176
178
|
}, []);
|
|
177
|
-
return dom ? null : /* @__PURE__ */ React.createElement(
|
|
179
|
+
return dom ? null : /* @__PURE__ */ React.createElement(
|
|
180
|
+
"div",
|
|
181
|
+
{
|
|
182
|
+
className: props == null ? void 0 : props.className,
|
|
183
|
+
style: props == null ? void 0 : props.style,
|
|
184
|
+
ref: rootRef
|
|
185
|
+
}
|
|
186
|
+
);
|
|
178
187
|
};
|
|
179
|
-
RemoteApp2["__APP_VERSION__"] = "0.3.
|
|
188
|
+
RemoteApp2["__APP_VERSION__"] = "0.3.3";
|
|
180
189
|
return /* @__PURE__ */ React.createElement(RemoteApp2, null);
|
|
181
190
|
});
|
|
182
191
|
function withRouterData(WrappedComponent) {
|
|
@@ -328,7 +337,14 @@ function createBridgeComponent(bridgeInfo) {
|
|
|
328
337
|
const RawComponent = (info) => {
|
|
329
338
|
const { appInfo, propsInfo, ...restProps } = info;
|
|
330
339
|
const { name, memoryRoute, basename = "/" } = appInfo;
|
|
331
|
-
return /* @__PURE__ */ React__namespace.createElement(context.RouterContext.Provider, { value: { name, basename, memoryRoute } }, /* @__PURE__ */ React__namespace.createElement(
|
|
340
|
+
return /* @__PURE__ */ React__namespace.createElement(context.RouterContext.Provider, { value: { name, basename, memoryRoute } }, /* @__PURE__ */ React__namespace.createElement(
|
|
341
|
+
bridgeInfo.rootComponent,
|
|
342
|
+
{
|
|
343
|
+
...propsInfo,
|
|
344
|
+
basename,
|
|
345
|
+
...restProps
|
|
346
|
+
}
|
|
347
|
+
));
|
|
332
348
|
};
|
|
333
349
|
return {
|
|
334
350
|
async render(info) {
|
|
@@ -336,20 +352,22 @@ function createBridgeComponent(bridgeInfo) {
|
|
|
336
352
|
const { name, basename, memoryRoute, ...propsInfo } = info;
|
|
337
353
|
if (context.atLeastReact18(React__namespace)) {
|
|
338
354
|
if (bridgeInfo == null ? void 0 : bridgeInfo.render) {
|
|
339
|
-
Promise.resolve(
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
355
|
+
Promise.resolve(
|
|
356
|
+
bridgeInfo == null ? void 0 : bridgeInfo.render(
|
|
357
|
+
/* @__PURE__ */ React__namespace.createElement(
|
|
358
|
+
RawComponent,
|
|
359
|
+
{
|
|
360
|
+
propsInfo,
|
|
361
|
+
appInfo: {
|
|
362
|
+
name,
|
|
363
|
+
basename,
|
|
364
|
+
memoryRoute
|
|
365
|
+
}
|
|
348
366
|
}
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
)
|
|
367
|
+
),
|
|
368
|
+
info.dom
|
|
369
|
+
)
|
|
370
|
+
).then((root) => rootMap.set(info.dom, root));
|
|
353
371
|
} else {
|
|
354
372
|
const root = client.createRoot(info.dom);
|
|
355
373
|
root.render(
|
package/dist/index.es.js
CHANGED
|
@@ -119,14 +119,16 @@ const RemoteAppWrapper = forwardRef(function(props, ref) {
|
|
|
119
119
|
providerInfoRef.current = providerReturn;
|
|
120
120
|
let domElement = null;
|
|
121
121
|
if (dom) {
|
|
122
|
-
domElement = document.
|
|
122
|
+
domElement = document.querySelector(dom);
|
|
123
|
+
if (!domElement || !(domElement instanceof HTMLElement)) {
|
|
124
|
+
throw new Error(`Invalid dom: ${dom}`);
|
|
125
|
+
}
|
|
123
126
|
rootRef.current = domElement;
|
|
124
127
|
} else {
|
|
125
128
|
domElement = rootRef.current;
|
|
126
129
|
}
|
|
127
130
|
const renderProps = {
|
|
128
131
|
name,
|
|
129
|
-
// dom: rootRef.current,
|
|
130
132
|
dom: domElement,
|
|
131
133
|
basename,
|
|
132
134
|
memoryRoute,
|
|
@@ -155,9 +157,16 @@ const RemoteAppWrapper = forwardRef(function(props, ref) {
|
|
|
155
157
|
});
|
|
156
158
|
};
|
|
157
159
|
}, []);
|
|
158
|
-
return dom ? null : /* @__PURE__ */ React__default.createElement(
|
|
160
|
+
return dom ? null : /* @__PURE__ */ React__default.createElement(
|
|
161
|
+
"div",
|
|
162
|
+
{
|
|
163
|
+
className: props == null ? void 0 : props.className,
|
|
164
|
+
style: props == null ? void 0 : props.style,
|
|
165
|
+
ref: rootRef
|
|
166
|
+
}
|
|
167
|
+
);
|
|
159
168
|
};
|
|
160
|
-
RemoteApp2["__APP_VERSION__"] = "0.3.
|
|
169
|
+
RemoteApp2["__APP_VERSION__"] = "0.3.3";
|
|
161
170
|
return /* @__PURE__ */ React__default.createElement(RemoteApp2, null);
|
|
162
171
|
});
|
|
163
172
|
function withRouterData(WrappedComponent) {
|
|
@@ -309,7 +318,14 @@ function createBridgeComponent(bridgeInfo) {
|
|
|
309
318
|
const RawComponent = (info) => {
|
|
310
319
|
const { appInfo, propsInfo, ...restProps } = info;
|
|
311
320
|
const { name, memoryRoute, basename = "/" } = appInfo;
|
|
312
|
-
return /* @__PURE__ */ React.createElement(RouterContext.Provider, { value: { name, basename, memoryRoute } }, /* @__PURE__ */ React.createElement(
|
|
321
|
+
return /* @__PURE__ */ React.createElement(RouterContext.Provider, { value: { name, basename, memoryRoute } }, /* @__PURE__ */ React.createElement(
|
|
322
|
+
bridgeInfo.rootComponent,
|
|
323
|
+
{
|
|
324
|
+
...propsInfo,
|
|
325
|
+
basename,
|
|
326
|
+
...restProps
|
|
327
|
+
}
|
|
328
|
+
));
|
|
313
329
|
};
|
|
314
330
|
return {
|
|
315
331
|
async render(info) {
|
|
@@ -317,20 +333,22 @@ function createBridgeComponent(bridgeInfo) {
|
|
|
317
333
|
const { name, basename, memoryRoute, ...propsInfo } = info;
|
|
318
334
|
if (atLeastReact18(React)) {
|
|
319
335
|
if (bridgeInfo == null ? void 0 : bridgeInfo.render) {
|
|
320
|
-
Promise.resolve(
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
336
|
+
Promise.resolve(
|
|
337
|
+
bridgeInfo == null ? void 0 : bridgeInfo.render(
|
|
338
|
+
/* @__PURE__ */ React.createElement(
|
|
339
|
+
RawComponent,
|
|
340
|
+
{
|
|
341
|
+
propsInfo,
|
|
342
|
+
appInfo: {
|
|
343
|
+
name,
|
|
344
|
+
basename,
|
|
345
|
+
memoryRoute
|
|
346
|
+
}
|
|
329
347
|
}
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
)
|
|
348
|
+
),
|
|
349
|
+
info.dom
|
|
350
|
+
)
|
|
351
|
+
).then((root) => rootMap.set(info.dom, root));
|
|
334
352
|
} else {
|
|
335
353
|
const root = client.createRoot(info.dom);
|
|
336
354
|
root.render(
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@module-federation/bridge-react",
|
|
3
|
-
"version": "0.0.0-next-
|
|
3
|
+
"version": "0.0.0-next-20240731105745",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@loadable/component": "^5.16.4",
|
|
37
37
|
"react-error-boundary": "^4.0.13",
|
|
38
|
-
"@module-federation/bridge-shared": "0.0.0-next-
|
|
38
|
+
"@module-federation/bridge-shared": "0.0.0-next-20240731105745"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
41
41
|
"react": ">=16.9.0",
|
package/src/create.tsx
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import React, { forwardRef } from 'react';
|
|
2
|
-
import type {
|
|
2
|
+
import type {
|
|
3
|
+
ForwardRefExoticComponent,
|
|
4
|
+
PropsWithoutRef,
|
|
5
|
+
RefAttributes,
|
|
6
|
+
} from 'react';
|
|
3
7
|
import type { ProviderParams } from '@module-federation/bridge-shared';
|
|
4
8
|
import { LoggerInstance } from './utils';
|
|
5
9
|
import {
|
|
@@ -11,11 +15,10 @@ import RemoteApp from './remote';
|
|
|
11
15
|
export interface RenderFnParams extends ProviderParams {
|
|
12
16
|
dom?: any;
|
|
13
17
|
}
|
|
18
|
+
|
|
14
19
|
interface RemoteModule {
|
|
15
20
|
provider: () => {
|
|
16
|
-
render: (
|
|
17
|
-
info: RenderFnParams,
|
|
18
|
-
) => void;
|
|
21
|
+
render: (info: RenderFnParams) => void;
|
|
19
22
|
destroy: (info: { dom: any }) => void;
|
|
20
23
|
};
|
|
21
24
|
}
|
|
@@ -90,7 +93,9 @@ export function createRemoteComponent<T, E extends keyof T>(info: {
|
|
|
90
93
|
fallback: ErrorBoundaryPropsWithComponent['FallbackComponent'];
|
|
91
94
|
export?: E;
|
|
92
95
|
dom?: string;
|
|
93
|
-
}): ForwardRefExoticComponent<
|
|
96
|
+
}): ForwardRefExoticComponent<
|
|
97
|
+
PropsWithoutRef<ProviderParams> & RefAttributes<HTMLElement | HTMLDivElement>
|
|
98
|
+
> {
|
|
94
99
|
// type ExportType = T[E] extends (...args: any) => any
|
|
95
100
|
// ? ReturnType<T[E]>
|
|
96
101
|
// : never;
|
|
@@ -100,7 +105,7 @@ export function createRemoteComponent<T, E extends keyof T>(info: {
|
|
|
100
105
|
// : {}
|
|
101
106
|
// : {};
|
|
102
107
|
|
|
103
|
-
return forwardRef(function (props, ref) {
|
|
108
|
+
return forwardRef(function (props, ref) {
|
|
104
109
|
const LazyComponent = createLazyRemoteComponent(info);
|
|
105
110
|
return (
|
|
106
111
|
<ErrorBoundary FallbackComponent={info.fallback}>
|
package/src/provider.tsx
CHANGED
|
@@ -12,7 +12,10 @@ import { LoggerInstance, atLeastReact18 } from './utils';
|
|
|
12
12
|
type RootType = HTMLElement | ReactDOMClient.Root;
|
|
13
13
|
type ProviderFnParams<T> = {
|
|
14
14
|
rootComponent: React.ComponentType<T>;
|
|
15
|
-
render?: (
|
|
15
|
+
render?: (
|
|
16
|
+
App: React.ReactElement,
|
|
17
|
+
id?: HTMLElement | string,
|
|
18
|
+
) => RootType | Promise<RootType>;
|
|
16
19
|
};
|
|
17
20
|
|
|
18
21
|
export function createBridgeComponent<T>(bridgeInfo: ProviderFnParams<T>) {
|
|
@@ -24,7 +27,11 @@ export function createBridgeComponent<T>(bridgeInfo: ProviderFnParams<T>) {
|
|
|
24
27
|
|
|
25
28
|
return (
|
|
26
29
|
<RouterContext.Provider value={{ name, basename, memoryRoute }}>
|
|
27
|
-
<bridgeInfo.rootComponent
|
|
30
|
+
<bridgeInfo.rootComponent
|
|
31
|
+
{...propsInfo}
|
|
32
|
+
basename={basename}
|
|
33
|
+
{...restProps}
|
|
34
|
+
/>
|
|
28
35
|
</RouterContext.Provider>
|
|
29
36
|
);
|
|
30
37
|
};
|
|
@@ -34,19 +41,20 @@ export function createBridgeComponent<T>(bridgeInfo: ProviderFnParams<T>) {
|
|
|
34
41
|
LoggerInstance.log(`createBridgeComponent render Info`, info);
|
|
35
42
|
const { name, basename, memoryRoute, ...propsInfo } = info;
|
|
36
43
|
if (atLeastReact18(React)) {
|
|
37
|
-
// render is provided by user
|
|
38
44
|
if (bridgeInfo?.render) {
|
|
39
|
-
Promise.resolve(
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
45
|
+
Promise.resolve(
|
|
46
|
+
bridgeInfo?.render(
|
|
47
|
+
<RawComponent
|
|
48
|
+
propsInfo={propsInfo}
|
|
49
|
+
appInfo={{
|
|
50
|
+
name,
|
|
51
|
+
basename,
|
|
52
|
+
memoryRoute,
|
|
53
|
+
}}
|
|
54
|
+
/>,
|
|
55
|
+
info.dom,
|
|
56
|
+
),
|
|
57
|
+
).then((root: RootType) => rootMap.set(info.dom, root));
|
|
50
58
|
} else {
|
|
51
59
|
const root: RootType = ReactDOMClient.createRoot(info.dom);
|
|
52
60
|
root.render(
|
package/src/remote/index.tsx
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, {
|
|
2
|
+
useContext,
|
|
3
|
+
useEffect,
|
|
4
|
+
useRef,
|
|
5
|
+
useState,
|
|
6
|
+
forwardRef,
|
|
7
|
+
} from 'react';
|
|
2
8
|
import * as ReactRouterDOM from 'react-router-dom';
|
|
3
9
|
import type { ProviderParams } from '@module-federation/bridge-shared';
|
|
4
10
|
import { LoggerInstance, pathJoin } from '../utils';
|
|
@@ -24,10 +30,12 @@ interface RemoteAppParams {
|
|
|
24
30
|
name: string;
|
|
25
31
|
providerInfo: NonNullable<RemoteModule['provider']>;
|
|
26
32
|
exportName: string | number | symbol;
|
|
27
|
-
dom?: string;
|
|
28
33
|
}
|
|
29
34
|
|
|
30
|
-
const RemoteAppWrapper = forwardRef(function (
|
|
35
|
+
const RemoteAppWrapper = forwardRef(function (
|
|
36
|
+
props: RemoteAppParams & RenderFnParams,
|
|
37
|
+
ref,
|
|
38
|
+
) {
|
|
31
39
|
const RemoteApp = () => {
|
|
32
40
|
const {
|
|
33
41
|
name,
|
|
@@ -40,19 +48,24 @@ const RemoteAppWrapper = forwardRef(function (props: RemoteAppParams & ProviderP
|
|
|
40
48
|
...resProps
|
|
41
49
|
} = props;
|
|
42
50
|
|
|
43
|
-
const rootRef: React.MutableRefObject<HTMLElement | null> =
|
|
51
|
+
const rootRef: React.MutableRefObject<HTMLElement | null> =
|
|
52
|
+
ref && 'current' in ref
|
|
53
|
+
? (ref as React.MutableRefObject<HTMLElement | null>)
|
|
54
|
+
: useRef(null);
|
|
44
55
|
const renderDom: React.MutableRefObject<HTMLElement | null> = useRef(null);
|
|
45
56
|
const providerInfoRef = useRef<any>(null);
|
|
46
|
-
|
|
57
|
+
|
|
47
58
|
useEffect(() => {
|
|
48
59
|
const renderTimeout = setTimeout(() => {
|
|
49
60
|
const providerReturn = providerInfo();
|
|
50
61
|
providerInfoRef.current = providerReturn;
|
|
51
|
-
|
|
62
|
+
|
|
52
63
|
let domElement = null;
|
|
53
64
|
if (dom) {
|
|
54
|
-
domElement = document.
|
|
55
|
-
|
|
65
|
+
domElement = document.querySelector(dom);
|
|
66
|
+
if (!domElement || !(domElement instanceof HTMLElement)) {
|
|
67
|
+
throw new Error(`Invalid dom: ${dom}`);
|
|
68
|
+
}
|
|
56
69
|
rootRef.current = domElement;
|
|
57
70
|
} else {
|
|
58
71
|
domElement = rootRef.current;
|
|
@@ -60,7 +73,6 @@ const RemoteAppWrapper = forwardRef(function (props: RemoteAppParams & ProviderP
|
|
|
60
73
|
|
|
61
74
|
const renderProps = {
|
|
62
75
|
name,
|
|
63
|
-
// dom: rootRef.current,
|
|
64
76
|
dom: domElement,
|
|
65
77
|
basename,
|
|
66
78
|
memoryRoute,
|
|
@@ -73,7 +85,7 @@ const RemoteAppWrapper = forwardRef(function (props: RemoteAppParams & ProviderP
|
|
|
73
85
|
);
|
|
74
86
|
providerReturn.render(renderProps);
|
|
75
87
|
});
|
|
76
|
-
|
|
88
|
+
|
|
77
89
|
return () => {
|
|
78
90
|
clearTimeout(renderTimeout);
|
|
79
91
|
setTimeout(() => {
|
|
@@ -90,23 +102,30 @@ const RemoteAppWrapper = forwardRef(function (props: RemoteAppParams & ProviderP
|
|
|
90
102
|
};
|
|
91
103
|
}, []);
|
|
92
104
|
|
|
93
|
-
return dom ? null :
|
|
94
|
-
|
|
105
|
+
return dom ? null : (
|
|
106
|
+
<div
|
|
107
|
+
className={props?.className}
|
|
108
|
+
style={props?.style}
|
|
109
|
+
ref={rootRef}
|
|
110
|
+
></div>
|
|
111
|
+
);
|
|
112
|
+
};
|
|
95
113
|
|
|
96
114
|
(RemoteApp as any)['__APP_VERSION__'] = __APP_VERSION__;
|
|
97
|
-
return <RemoteApp
|
|
115
|
+
return <RemoteApp />;
|
|
98
116
|
});
|
|
99
117
|
|
|
100
118
|
interface ExtraDataProps {
|
|
101
119
|
basename?: string;
|
|
102
120
|
}
|
|
103
121
|
|
|
104
|
-
export function withRouterData<
|
|
122
|
+
export function withRouterData<
|
|
123
|
+
P extends Parameters<typeof RemoteAppWrapper>[0],
|
|
124
|
+
>(
|
|
105
125
|
WrappedComponent: React.ComponentType<P & ExtraDataProps>,
|
|
106
126
|
): React.FC<Omit<P, keyof ExtraDataProps>> {
|
|
107
|
-
|
|
108
127
|
const Component = forwardRef(function (props: any, ref) {
|
|
109
|
-
let enableDispathPopstate = false
|
|
128
|
+
let enableDispathPopstate = false;
|
|
110
129
|
let routerContextVal: any;
|
|
111
130
|
try {
|
|
112
131
|
ReactRouterDOM.useLocation();
|
|
@@ -181,7 +200,7 @@ export function withRouterData<P extends Parameters<typeof RemoteAppWrapper>[0]>
|
|
|
181
200
|
});
|
|
182
201
|
|
|
183
202
|
return forwardRef(function (props, ref) {
|
|
184
|
-
return <Component {...props} ref={ref}
|
|
203
|
+
return <Component {...props} ref={ref} />;
|
|
185
204
|
}) as any;
|
|
186
205
|
}
|
|
187
206
|
|