@module-federation/bridge-react 0.0.0-next-20240822090000 → 0.0.0-next-20240823062237

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 CHANGED
@@ -1,11 +1,24 @@
1
1
  # @module-federation/bridge-react
2
2
 
3
- ## 0.0.0-next-20240822090000
3
+ ## 0.0.0-next-20240823062237
4
4
 
5
5
  ### Patch Changes
6
6
 
7
- - 3082116: feat: support module isolated reported
8
- - @module-federation/bridge-shared@0.0.0-next-20240822090000
7
+ - @module-federation/bridge-shared@0.0.0-next-20240823062237
8
+
9
+ ## 0.5.1
10
+
11
+ ### Patch Changes
12
+
13
+ - @module-federation/bridge-shared@0.5.1
14
+
15
+ ## 0.5.0
16
+
17
+ ### Patch Changes
18
+
19
+ - 49d6135: feat(@module-federation/bridge): enhance Bridge capabilities and fix some issues
20
+ - Updated dependencies [49d6135]
21
+ - @module-federation/bridge-shared@0.5.0
9
22
 
10
23
  ## 0.4.0
11
24
 
@@ -45,8 +45,8 @@ describe('bridge', () => {
45
45
  });
46
46
 
47
47
  it('createRemoteComponent', async () => {
48
- function Component(info: { msg: string }) {
49
- return <div>life cycle render {info.msg}</div>;
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,45 @@ describe('bridge', () => {
61
61
  loading: <div>loading</div>,
62
62
  });
63
63
 
64
- const { container } = render(<RemoteComponent msg={'hello world'} />);
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 and obtain ref property', async () => {
75
+ const ref = {
76
+ current: null,
77
+ };
78
+
79
+ function Component({ props }: { props?: Record<string, any> }) {
80
+ return <div>life cycle render {props?.msg}</div>;
81
+ }
82
+ const BridgeComponent = createBridgeComponent({
83
+ rootComponent: Component,
84
+ });
85
+ const RemoteComponent = createRemoteComponent({
86
+ loader: async () => {
87
+ return {
88
+ default: BridgeComponent,
89
+ };
90
+ },
91
+ fallback: () => <div></div>,
92
+ loading: <div>loading</div>,
93
+ });
94
+
95
+ const { container } = render(
96
+ <RemoteComponent ref={ref} props={{ msg: 'hello world' }} />,
97
+ );
65
98
  expect(getHtml(container)).toMatch('loading');
66
99
 
67
100
  await sleep(200);
68
101
  expect(getHtml(container)).toMatch('life cycle render');
69
102
  expect(getHtml(container)).toMatch('hello world');
103
+ expect(ref.current).not.toBeNull();
70
104
  });
71
105
  });
package/dist/index.cjs.js CHANGED
@@ -117,55 +117,71 @@ function hasArrayChanged() {
117
117
  let b = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : [];
118
118
  return a.length !== b.length || a.some((item, index) => !Object.is(item, b[index]));
119
119
  }
120
- const RemoteApp = ({
121
- name,
122
- memoryRoute,
123
- basename,
124
- providerInfo,
125
- ...resProps
126
- }) => {
127
- const rootRef = React.useRef(null);
128
- const renderDom = React.useRef(null);
129
- const providerInfoRef = React.useRef(null);
130
- React.useEffect(() => {
131
- const renderTimeout = setTimeout(() => {
132
- const providerReturn = providerInfo();
133
- providerInfoRef.current = providerReturn;
134
- const renderProps = {
135
- name,
136
- dom: rootRef.current,
137
- basename,
138
- memoryRoute,
139
- ...resProps
140
- };
141
- renderDom.current = rootRef.current;
142
- context.LoggerInstance.log(
143
- `createRemoteComponent LazyComponent render >>>`,
144
- renderProps
145
- );
146
- providerReturn.render(renderProps);
147
- });
148
- return () => {
149
- clearTimeout(renderTimeout);
150
- setTimeout(() => {
151
- var _a, _b;
152
- if ((_a = providerInfoRef.current) == null ? void 0 : _a.destroy) {
153
- context.LoggerInstance.log(
154
- `createRemoteComponent LazyComponent destroy >>>`,
155
- { name, basename, dom: renderDom.current }
156
- );
157
- (_b = providerInfoRef.current) == null ? void 0 : _b.destroy({
158
- dom: renderDom.current
159
- });
160
- }
120
+ const RemoteAppWrapper = React.forwardRef(function(props, ref) {
121
+ const RemoteApp2 = () => {
122
+ context.LoggerInstance.log(`RemoteAppWrapper RemoteApp props >>>`, { props });
123
+ const {
124
+ moduleName,
125
+ memoryRoute,
126
+ basename,
127
+ providerInfo,
128
+ className,
129
+ style,
130
+ fallback,
131
+ ...resProps
132
+ } = props;
133
+ const rootRef = ref && "current" in ref ? ref : React.useRef(null);
134
+ const renderDom = React.useRef(null);
135
+ const providerInfoRef = React.useRef(null);
136
+ React.useEffect(() => {
137
+ const renderTimeout = setTimeout(() => {
138
+ const providerReturn = providerInfo();
139
+ providerInfoRef.current = providerReturn;
140
+ const renderProps = {
141
+ moduleName,
142
+ dom: rootRef.current,
143
+ basename,
144
+ memoryRoute,
145
+ fallback,
146
+ ...resProps
147
+ };
148
+ renderDom.current = rootRef.current;
149
+ context.LoggerInstance.log(
150
+ `createRemoteComponent LazyComponent render >>>`,
151
+ renderProps
152
+ );
153
+ providerReturn.render(renderProps);
161
154
  });
162
- };
163
- }, []);
164
- return /* @__PURE__ */ React.createElement("div", { ref: rootRef });
165
- };
166
- RemoteApp["__APP_VERSION__"] = "0.4.0";
155
+ return () => {
156
+ clearTimeout(renderTimeout);
157
+ setTimeout(() => {
158
+ var _a, _b;
159
+ if ((_a = providerInfoRef.current) == null ? void 0 : _a.destroy) {
160
+ context.LoggerInstance.log(
161
+ `createRemoteComponent LazyComponent destroy >>>`,
162
+ { moduleName, basename, dom: renderDom.current }
163
+ );
164
+ (_b = providerInfoRef.current) == null ? void 0 : _b.destroy({
165
+ dom: renderDom.current
166
+ });
167
+ }
168
+ });
169
+ };
170
+ }, []);
171
+ return /* @__PURE__ */ React.createElement(
172
+ "div",
173
+ {
174
+ className: props == null ? void 0 : props.className,
175
+ style: props == null ? void 0 : props.style,
176
+ ref: rootRef
177
+ }
178
+ );
179
+ };
180
+ RemoteApp2["__APP_VERSION__"] = "0.5.1";
181
+ return /* @__PURE__ */ React.createElement(RemoteApp2, null);
182
+ });
167
183
  function withRouterData(WrappedComponent) {
168
- return (props) => {
184
+ const Component = React.forwardRef(function(props, ref) {
169
185
  var _a;
170
186
  let enableDispathPopstate = false;
171
187
  let routerContextVal;
@@ -223,10 +239,13 @@ function withRouterData(WrappedComponent) {
223
239
  setPathname(location.pathname);
224
240
  }, [location]);
225
241
  }
226
- return /* @__PURE__ */ React.createElement(WrappedComponent, { ...props, basename });
227
- };
242
+ return /* @__PURE__ */ React.createElement(WrappedComponent, { ...props, basename, ref });
243
+ });
244
+ return React.forwardRef(function(props, ref) {
245
+ return /* @__PURE__ */ React.createElement(Component, { ...props, ref });
246
+ });
228
247
  }
229
- const RemoteApp$1 = withRouterData(RemoteApp);
248
+ const RemoteApp = withRouterData(RemoteAppWrapper);
230
249
  function createLazyRemoteComponent(info) {
231
250
  const exportName = (info == null ? void 0 : info.export) || "default";
232
251
  return React.lazy(async () => {
@@ -243,13 +262,15 @@ function createLazyRemoteComponent(info) {
243
262
  );
244
263
  const exportFn = m2[exportName];
245
264
  if (exportName in m2 && typeof exportFn === "function") {
246
- const RemoteAppComponent = React.forwardRef((props, _ref) => {
265
+ const RemoteAppComponent = React.forwardRef((props, ref) => {
247
266
  return /* @__PURE__ */ React.createElement(
248
- RemoteApp$1,
267
+ RemoteApp,
249
268
  {
250
- name: moduleName,
269
+ moduleName,
251
270
  providerInfo: exportFn,
252
271
  exportName: info.export || "default",
272
+ fallback: info.fallback,
273
+ ref,
253
274
  ...props
254
275
  }
255
276
  );
@@ -274,10 +295,12 @@ function createLazyRemoteComponent(info) {
274
295
  });
275
296
  }
276
297
  function createRemoteComponent(info) {
277
- const LazyComponent = createLazyRemoteComponent(info);
278
- return (props) => {
279
- return /* @__PURE__ */ React.createElement(ErrorBoundary, { FallbackComponent: info.fallback }, /* @__PURE__ */ React.createElement(React.Suspense, { fallback: info.loading }, /* @__PURE__ */ React.createElement(LazyComponent, { ...props })));
280
- };
298
+ return React.forwardRef(
299
+ (props, ref) => {
300
+ const LazyComponent = createLazyRemoteComponent(info);
301
+ return /* @__PURE__ */ React.createElement(ErrorBoundary, { FallbackComponent: info.fallback }, /* @__PURE__ */ React.createElement(React.Suspense, { fallback: info.loading }, /* @__PURE__ */ React.createElement(LazyComponent, { ...props, ref })));
302
+ }
303
+ );
281
304
  }
282
305
  var client = {};
283
306
  var m = ReactDOM;
@@ -304,69 +327,76 @@ if (process.env.NODE_ENV === "production") {
304
327
  };
305
328
  }
306
329
  function createBridgeComponent(bridgeInfo) {
307
- let provider;
308
330
  return () => {
309
331
  const rootMap = /* @__PURE__ */ new Map();
310
332
  const RawComponent = (info) => {
311
- const { appInfo, propsInfo } = info;
312
- const { name, memoryRoute, basename = "/" } = appInfo;
313
- return /* @__PURE__ */ React__namespace.createElement(context.RouterContext.Provider, { value: { name, basename, memoryRoute } }, /* @__PURE__ */ React__namespace.createElement(bridgeInfo.rootComponent, { ...propsInfo, basename }));
333
+ const { appInfo, propsInfo, ...restProps } = info;
334
+ const { moduleName, memoryRoute, basename = "/" } = appInfo;
335
+ return /* @__PURE__ */ React__namespace.createElement(context.RouterContext.Provider, { value: { moduleName, basename, memoryRoute } }, /* @__PURE__ */ React__namespace.createElement(
336
+ bridgeInfo.rootComponent,
337
+ {
338
+ ...propsInfo,
339
+ basename,
340
+ ...restProps
341
+ }
342
+ ));
314
343
  };
315
- if (!provider) {
316
- provider = {
317
- render(info) {
318
- context.LoggerInstance.log(`createBridgeComponent render Info`, info);
319
- const { name, basename, memoryRoute, ...propsInfo } = info;
320
- if (context.atLeastReact18(React__namespace)) {
344
+ return {
345
+ async render(info) {
346
+ context.LoggerInstance.log(`createBridgeComponent render Info`, info);
347
+ const {
348
+ moduleName,
349
+ dom,
350
+ basename,
351
+ memoryRoute,
352
+ fallback,
353
+ ...propsInfo
354
+ } = info;
355
+ const rootComponentWithErrorBoundary = (
356
+ // set ErrorBoundary for RawComponent rendering error, usually caused by user app rendering error
357
+ /* @__PURE__ */ React__namespace.createElement(ErrorBoundary, { FallbackComponent: fallback }, /* @__PURE__ */ React__namespace.createElement(
358
+ RawComponent,
359
+ {
360
+ appInfo: {
361
+ moduleName,
362
+ basename,
363
+ memoryRoute
364
+ },
365
+ propsInfo
366
+ }
367
+ ))
368
+ );
369
+ if (context.atLeastReact18(React__namespace)) {
370
+ if (bridgeInfo == null ? void 0 : bridgeInfo.render) {
371
+ Promise.resolve(
372
+ bridgeInfo == null ? void 0 : bridgeInfo.render(rootComponentWithErrorBoundary, dom)
373
+ ).then((root) => rootMap.set(info.dom, root));
374
+ } else {
321
375
  const root = client.createRoot(info.dom);
376
+ root.render(rootComponentWithErrorBoundary);
322
377
  rootMap.set(info.dom, root);
323
- root.render(
324
- /* @__PURE__ */ React__namespace.createElement(
325
- RawComponent,
326
- {
327
- propsInfo,
328
- appInfo: {
329
- name,
330
- basename,
331
- memoryRoute
332
- }
333
- }
334
- )
335
- );
336
- } else {
337
- ReactDOM.render(
338
- /* @__PURE__ */ React__namespace.createElement(
339
- RawComponent,
340
- {
341
- propsInfo,
342
- appInfo: {
343
- name,
344
- basename,
345
- memoryRoute
346
- }
347
- }
348
- ),
349
- info.dom
350
- );
351
378
  }
352
- },
353
- destroy(info) {
354
- context.LoggerInstance.log(`createBridgeComponent destroy Info`, {
355
- dom: info.dom
356
- });
357
- if (context.atLeastReact18(React__namespace)) {
358
- const root = rootMap.get(info.dom);
359
- root == null ? void 0 : root.unmount();
360
- } else {
361
- ReactDOM.unmountComponentAtNode(info.dom);
362
- }
363
- },
364
- rawComponent: bridgeInfo.rootComponent,
365
- __BRIDGE_FN__: (_args) => {
379
+ } else {
380
+ const renderFn = (bridgeInfo == null ? void 0 : bridgeInfo.render) || ReactDOM.render;
381
+ renderFn == null ? void 0 : renderFn(rootComponentWithErrorBoundary, info.dom);
366
382
  }
367
- };
368
- }
369
- return provider;
383
+ },
384
+ async destroy(info) {
385
+ context.LoggerInstance.log(`createBridgeComponent destroy Info`, {
386
+ dom: info.dom
387
+ });
388
+ if (context.atLeastReact18(React__namespace)) {
389
+ const root = rootMap.get(info.dom);
390
+ root == null ? void 0 : root.unmount();
391
+ rootMap.delete(info.dom);
392
+ } else {
393
+ ReactDOM.unmountComponentAtNode(info.dom);
394
+ }
395
+ },
396
+ rawComponent: bridgeInfo.rootComponent,
397
+ __BRIDGE_FN__: (_args) => {
398
+ }
399
+ };
370
400
  };
371
401
  }
372
402
  exports.createBridgeComponent = createBridgeComponent;
package/dist/index.d.ts CHANGED
@@ -1,20 +1,25 @@
1
1
  import { ComponentType } from 'react';
2
2
  import { default as default_2 } from 'react';
3
+ import { default as default_3 } from 'react-dom/client';
3
4
  import { ErrorInfo } from 'react';
4
5
  import { PropsWithChildren } from 'react';
5
6
  import * as React_2 from 'react';
6
7
 
7
- export declare function createBridgeComponent<T>(bridgeInfo: ProviderFnParams<T>): () => Provider<T>;
8
+ export declare function createBridgeComponent<T>(bridgeInfo: ProviderFnParams<T>): () => {
9
+ render(info: RenderFnParams & any): Promise<void>;
10
+ destroy(info: {
11
+ dom: HTMLElement;
12
+ }): Promise<void>;
13
+ rawComponent: React_2.ComponentType<T>;
14
+ __BRIDGE_FN__: (_args: T) => void;
15
+ };
8
16
 
9
17
  export declare function createRemoteComponent<T, E extends keyof T>(info: {
10
18
  loader: () => Promise<T>;
11
19
  loading: default_2.ReactNode;
12
20
  fallback: ErrorBoundaryPropsWithComponent['FallbackComponent'];
13
21
  export?: E;
14
- }): (props: {
15
- basename?: ProviderParams['basename'];
16
- memoryRoute?: ProviderParams['memoryRoute'];
17
- } & ("__BRIDGE_FN__" extends keyof (T[E] extends (...args: any) => any ? ReturnType<T[E]> : never) ? (T[E] extends (...args: any) => any ? ReturnType<T[E]> : never)["__BRIDGE_FN__"] extends (...args: any) => any ? Parameters<(T[E] extends (...args: any) => any ? ReturnType<T[E]> : never)["__BRIDGE_FN__"]>[0] : {} : {})) => default_2.JSX.Element;
22
+ }): default_2.ForwardRefExoticComponent<default_2.PropsWithoutRef<ProviderParams & ("__BRIDGE_FN__" extends keyof (T[E] extends (...args: any) => any ? ReturnType<T[E]> : never) ? (T[E] extends (...args: any) => any ? ReturnType<T[E]> : never)["__BRIDGE_FN__"] extends (...args: any) => any ? Parameters<(T[E] extends (...args: any) => any ? ReturnType<T[E]> : never)["__BRIDGE_FN__"]>[0] : {} : {})> & default_2.RefAttributes<HTMLDivElement>>;
18
23
 
19
24
  declare type ErrorBoundaryPropsWithComponent = ErrorBoundarySharedProps & {
20
25
  fallback?: never;
@@ -40,29 +45,25 @@ declare type FallbackProps = {
40
45
  resetErrorBoundary: (...args: any[]) => void;
41
46
  };
42
47
 
43
- declare interface Provider<T> {
44
- render(info: any): void;
45
- destroy(info: {
46
- dom: HTMLElement;
47
- }): void;
48
- rawComponent: React_2.ComponentType;
49
- __BRIDGE_FN__: (_args: T) => void;
50
- }
51
-
52
48
  declare type ProviderFnParams<T> = {
53
49
  rootComponent: React_2.ComponentType<T>;
50
+ render?: (App: React_2.ReactElement, id?: HTMLElement | string) => RootType | Promise<RootType>;
54
51
  };
55
52
 
56
53
  export declare interface ProviderParams {
57
- name?: string;
54
+ moduleName?: string;
58
55
  basename?: string;
59
56
  memoryRoute?: {
60
57
  entryPath: string;
61
58
  };
59
+ style?: React.CSSProperties;
60
+ className?: string;
62
61
  }
63
62
 
64
63
  export declare interface RenderFnParams extends ProviderParams {
65
64
  dom: HTMLElement;
66
65
  }
67
66
 
67
+ declare type RootType = HTMLElement | default_3.Root;
68
+
68
69
  export { }