remote-reload-utils 0.0.10 → 0.0.12

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
@@ -7,6 +7,20 @@
7
7
 
8
8
  ## [未发布]
9
9
 
10
+ ## [0.0.12] - 2026-03-16
11
+
12
+ ### Release
13
+
14
+ - Published version 0.0.12 with patch bump
15
+
16
+
17
+ ## [0.0.11] - 2026-03-16
18
+
19
+ ### Release
20
+
21
+ - Published version 0.0.11 with patch bump
22
+
23
+
10
24
  ## [0.0.10] - 2026-03-15
11
25
 
12
26
  ### Release
@@ -130,6 +144,10 @@
130
144
 
131
145
  | 版本 | 日期 | 主要变更 |
132
146
  |------|------|----------|
147
+ | 0.0.12 | 2026-03-16 | patch 版本发布 |
148
+ |------|------|----------|
149
+ | 0.0.11 | 2026-03-16 | patch 版本发布 |
150
+ |------|------|----------|
133
151
  | 0.0.10 | 2026-03-15 | patch 版本发布 |
134
152
  |------|------|----------|
135
153
  | 0.0.9 | 2026-03-15 | patch 版本发布 |
package/README.md CHANGED
@@ -24,6 +24,8 @@ pnpm dev
24
24
 
25
25
  ### 使用方式
26
26
 
27
+ #### 1. 基础加载远程模块
28
+
27
29
  ```ts
28
30
  import { loadRemoteMultiVersion } from 'remote-reload-utils';
29
31
  const [comp, setComp] = useState(null);
@@ -52,3 +54,63 @@ useEffect(() => {
52
54
  init();
53
55
  }, []);
54
56
  ```
57
+
58
+ #### 2. 使用 React 组件加载远程模块
59
+
60
+ ```tsx
61
+ import { RemoteModuleProvider, ErrorBoundary, lazyRemote } from 'remote-reload-utils';
62
+ import React, { Suspense } from 'react';
63
+
64
+ // 方式一:使用 RemoteModuleProvider 组件(推荐)
65
+ function App() {
66
+ return (
67
+ <RemoteModuleProvider
68
+ pkg="@myorg/remote-app"
69
+ version="^1.0.0"
70
+ moduleName="Dashboard"
71
+ scopeName="myorg"
72
+ loadingFallback={<Spinner />}
73
+ errorFallback={(error, reset) => (
74
+ <div>
75
+ <p>加载失败:{error.message}</p>
76
+ <button onClick={reset}>重试</button>
77
+ </div>
78
+ )}
79
+ componentProps={{ userId: 123 }}
80
+ />
81
+ );
82
+ }
83
+
84
+ // 方式二:使用 lazy + Suspense
85
+ const LazyDashboard = lazyRemote({
86
+ pkg: "@myorg/remote-app",
87
+ version: "^1.0.0",
88
+ moduleName: "Dashboard",
89
+ scopeName: "myorg"
90
+ });
91
+
92
+ function App() {
93
+ return (
94
+ <ErrorBoundary fallback={(error) => <div>错误:{error.message}</div>}>
95
+ <Suspense fallback={<Spinner />}>
96
+ <LazyDashboard userId={123} />
97
+ </Suspense>
98
+ </ErrorBoundary>
99
+ );
100
+ }
101
+
102
+ // 方式三:使用 SuspenseRemoteLoader(一体化方案)
103
+ function App() {
104
+ return (
105
+ <SuspenseRemoteLoader
106
+ pkg="@myorg/remote-app"
107
+ version="^1.0.0"
108
+ moduleName="Dashboard"
109
+ scopeName="myorg"
110
+ fallback={<Spinner />}
111
+ errorFallback={(error) => <div>错误:{error.message}</div>}
112
+ componentProps={{ userId: 123 }}
113
+ />
114
+ );
115
+ }
116
+ ```
@@ -0,0 +1,34 @@
1
+ import React from 'react';
2
+ export interface ErrorBoundaryProps {
3
+ children: React.ReactNode;
4
+ fallback?: React.ReactNode | ((error: Error, resetError: () => void) => React.ReactNode);
5
+ onError?: (error: Error, errorInfo: React.ErrorInfo) => void;
6
+ onReset?: () => void;
7
+ }
8
+ interface ErrorBoundaryState {
9
+ hasError: boolean;
10
+ error: Error | null;
11
+ errorInfo?: React.ErrorInfo | null;
12
+ }
13
+ /**
14
+ * 错误边界组件
15
+ * 用于捕获子组件树中的错误,并显示降级 UI
16
+ *
17
+ * @example
18
+ * ```tsx
19
+ * <ErrorBoundary
20
+ * fallback={(error, reset) => <div onClick={reset}>Error: {error.message}</div>}
21
+ * onError={(error, info) => console.error(error, info)}
22
+ * >
23
+ * <MyComponent />
24
+ * </ErrorBoundary>
25
+ * ```
26
+ */
27
+ export declare class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> {
28
+ constructor(props: ErrorBoundaryProps);
29
+ static getDerivedStateFromError(error: Error): ErrorBoundaryState;
30
+ componentDidCatch(error: Error, errorInfo: React.ErrorInfo): void;
31
+ handleReset: () => void;
32
+ render(): string | number | boolean | Iterable<React.ReactNode> | import("react/jsx-runtime").JSX.Element | null | undefined;
33
+ }
34
+ export {};
@@ -0,0 +1,95 @@
1
+ import React from 'react';
2
+ import type { ErrorBoundaryProps } from './ErrorBoundary';
3
+ export interface RemoteModuleCardProps {
4
+ /** 包名称 */
5
+ pkg: string;
6
+ /** 版本号,支持 semver 范围 */
7
+ version: string;
8
+ /** 远程模块名称(导出名) */
9
+ moduleName: string;
10
+ /** 作用域名称 */
11
+ scopeName: string;
12
+ /** 加载中的占位内容 */
13
+ loadingFallback?: React.ReactNode;
14
+ /** 错误状态的占位内容 */
15
+ errorFallback?: React.ReactNode | ((error: Error, resetError: () => void) => React.ReactNode);
16
+ /** 传递给远程组件的 props */
17
+ componentProps?: Record<string, any>;
18
+ /** 容器类名 */
19
+ className?: string;
20
+ /** 容器样式 */
21
+ style?: React.CSSProperties;
22
+ /** 加载成功回调 */
23
+ onLoad?: (component: React.ComponentType<any>) => void;
24
+ /** 加载失败回调 */
25
+ onError?: (error: Error) => void;
26
+ /** 是否禁用错误边界 */
27
+ disableErrorBoundary?: boolean;
28
+ /** 错误边界配置 */
29
+ errorBoundaryOptions?: Omit<ErrorBoundaryProps, 'children' | 'fallback'>;
30
+ }
31
+ interface ModuleState {
32
+ loading: boolean;
33
+ error: Error | null;
34
+ component: React.ComponentType<any> | null;
35
+ }
36
+ /**
37
+ * Hook 选项:加载远程模块
38
+ */
39
+ export interface UseRemoteModuleOptions {
40
+ pkg: string;
41
+ version: string;
42
+ moduleName: string;
43
+ scopeName: string;
44
+ onError?: (error: Error) => void;
45
+ onLoad?: (component: React.ComponentType<any>) => void;
46
+ retryKey?: number;
47
+ }
48
+ /**
49
+ * Hook:加载远程模块
50
+ */
51
+ export declare function useRemoteModule({ pkg, version, moduleName, scopeName, onError, onLoad, retryKey, }: UseRemoteModuleOptions): ModuleState;
52
+ /**
53
+ * 远程模块渲染器:纯内容渲染(不含 Suspense/ErrorBoundary)
54
+ */
55
+ export declare function RemoteModuleRenderer({ pkg, version, moduleName, scopeName, loadingFallback, errorFallback, componentProps, className, style, onError, onLoad, }: RemoteModuleCardProps): import("react/jsx-runtime").JSX.Element | null;
56
+ /**
57
+ * 远程模块提供者:带 Suspense 和 ErrorBoundary 的完整组件
58
+ *
59
+ * @features
60
+ * - 自动加载远程模块
61
+ * - 内置加载状态和错误处理
62
+ * - 支持 Suspense 惰性加载
63
+ * - 可配置的错误边界
64
+ * - 支持重试机制
65
+ *
66
+ * @example
67
+ * ```tsx
68
+ * <RemoteModuleProvider
69
+ * pkg="@myorg/remote-app"
70
+ * version="^1.0.0"
71
+ * moduleName="Dashboard"
72
+ * scopeName="myorg"
73
+ * loadingFallback={<Spinner />}
74
+ * errorFallback={(error, reset) => <Button onClick={reset}>Retry</Button>}
75
+ * componentProps={{ userId: 123 }}
76
+ * />
77
+ * ```
78
+ *
79
+ * @example
80
+ * ```tsx
81
+ * // 使用 lazy + Suspense 模式
82
+ * const LazyRemote = lazyRemote({
83
+ * pkg: "@myorg/remote-app",
84
+ * version: "^1.0.0",
85
+ * moduleName: "Dashboard",
86
+ * scopeName: "myorg"
87
+ * });
88
+ *
89
+ * <Suspense fallback={<Spinner />}>
90
+ * <LazyRemote userId={123} />
91
+ * </Suspense>
92
+ * ```
93
+ */
94
+ export declare function RemoteModuleProvider(props: RemoteModuleCardProps): import("react/jsx-runtime").JSX.Element;
95
+ export {};
@@ -0,0 +1,131 @@
1
+ import React, { type ComponentType, type ReactNode } from 'react';
2
+ export interface LazyRemoteOptions {
3
+ /** 包名称 */
4
+ pkg: string;
5
+ /** 版本号 */
6
+ version?: string;
7
+ /** 模块名称 */
8
+ moduleName: string;
9
+ /** 作用域名称 */
10
+ scopeName: string;
11
+ /** 加载失败时的最大重试次数 */
12
+ maxRetries?: number;
13
+ /** 重试延迟(毫秒) */
14
+ retryDelay?: number;
15
+ }
16
+ export interface SuspenseRemoteProps {
17
+ /** 加载中的占位内容 */
18
+ fallback?: ReactNode;
19
+ children: ReactNode;
20
+ }
21
+ export interface SuspenseRemoteWithPropsProps extends LazyRemoteOptions {
22
+ /** 加载中的占位内容 */
23
+ fallback?: ReactNode;
24
+ /** 错误状态的占位内容 */
25
+ errorFallback?: ReactNode | ((error: Error) => ReactNode);
26
+ /** 传递给远程组件的 props */
27
+ componentProps?: Record<string, any>;
28
+ }
29
+ /**
30
+ * 创建一个惰性加载的远程组件
31
+ * 返回一个可用于 React.lazy() 的 Promise
32
+ *
33
+ * @example
34
+ * ```tsx
35
+ * const LazyDashboard = lazyRemote({
36
+ * pkg: "@myorg/remote-app",
37
+ * version: "^1.0.0",
38
+ * moduleName: "Dashboard",
39
+ * scopeName: "myorg"
40
+ * });
41
+ *
42
+ * function App() {
43
+ * return (
44
+ * <Suspense fallback={<Spinner />}>
45
+ * <LazyDashboard userId={123} />
46
+ * </Suspense>
47
+ * );
48
+ * }
49
+ * ```
50
+ */
51
+ export declare function lazyRemote(options: LazyRemoteOptions): React.LazyExoticComponent<React.ComponentType<any>>;
52
+ /**
53
+ * 带 Suspense 和错误处理的远程组件包装器
54
+ * 注意:错误处理需要与 ErrorBoundary 配合使用
55
+ *
56
+ * @example
57
+ * ```tsx
58
+ * // 与 ErrorBoundary 配合使用
59
+ * <ErrorBoundary fallback={(error) => <div>Error: {error.message}</div>}>
60
+ * <SuspenseRemote fallback={<Spinner />}>
61
+ * <RemoteModuleProvider pkg="@myorg/remote-app" version="^1.0.0" moduleName="Dashboard" scopeName="myorg" />
62
+ * </SuspenseRemote>
63
+ * </ErrorBoundary>
64
+ * ```
65
+ */
66
+ export declare function SuspenseRemote({ fallback, children, }: {
67
+ fallback?: ReactNode;
68
+ children: ReactNode;
69
+ }): import("react/jsx-runtime").JSX.Element;
70
+ /**
71
+ * 一体化的远程组件加载器(包含 Suspense 和 ErrorBoundary)
72
+ *
73
+ * @example
74
+ * ```tsx
75
+ * <SuspenseRemoteLoader
76
+ * pkg="@myorg/remote-app"
77
+ * version="^1.0.0"
78
+ * moduleName="Dashboard"
79
+ * scopeName="myorg"
80
+ * fallback={<Spinner />}
81
+ * errorFallback={(error) => <div>Error: {error.message}</div>}
82
+ * componentProps={{ userId: 123 }}
83
+ * />
84
+ * ```
85
+ */
86
+ export declare function SuspenseRemoteLoader({ pkg, version, moduleName, scopeName, fallback, errorFallback, componentProps, }: SuspenseRemoteWithPropsProps): import("react/jsx-runtime").JSX.Element;
87
+ /**
88
+ * HOC:为组件添加远程加载能力
89
+ *
90
+ * @example
91
+ * ```tsx
92
+ * const EnhancedComponent = withRemote(
93
+ * (props) => <div>{props.message}</div>,
94
+ * {
95
+ * pkg: "@myorg/remote-app",
96
+ * version: "^1.0.0",
97
+ * moduleName: "RemoteComponent",
98
+ * scopeName: "myorg"
99
+ * }
100
+ * );
101
+ *
102
+ * <EnhancedComponent message="Hello" />
103
+ * ```
104
+ */
105
+ export declare function withRemote<P extends object>(WrappedComponent: ComponentType<P>, options: LazyRemoteOptions): (props: P) => import("react/jsx-runtime").JSX.Element;
106
+ /**
107
+ * Hook:在函数组件中加载远程模块
108
+ *
109
+ * @example
110
+ * ```tsx
111
+ * function MyComponent() {
112
+ * const { component: RemoteComp, loading, error } = useRemoteModule({
113
+ * pkg: "@myorg/remote-app",
114
+ * version: "^1.0.0",
115
+ * moduleName: "Dashboard",
116
+ * scopeName: "myorg"
117
+ * });
118
+ *
119
+ * if (loading) return <Spinner />;
120
+ * if (error) return <div>Error: {error.message}</div>;
121
+ * if (!RemoteComp) return null;
122
+ *
123
+ * return <RemoteComp userId={123} />;
124
+ * }
125
+ * ```
126
+ */
127
+ export declare function useRemoteModuleHook(options: LazyRemoteOptions): {
128
+ component: ComponentType<any> | null;
129
+ loading: boolean;
130
+ error: Error | null;
131
+ };
@@ -0,0 +1,6 @@
1
+ export { ErrorBoundary } from './ErrorBoundary';
2
+ export type { ErrorBoundaryProps } from './ErrorBoundary';
3
+ export { RemoteModuleProvider, RemoteModuleRenderer, useRemoteModule } from './RemoteModuleProvider';
4
+ export type { RemoteModuleCardProps, UseRemoteModuleOptions } from './RemoteModuleProvider';
5
+ export { lazyRemote, SuspenseRemote, SuspenseRemoteLoader, withRemote, useRemoteModuleHook, } from './SuspenseLoader';
6
+ export type { LazyRemoteOptions, SuspenseRemoteProps, SuspenseRemoteWithPropsProps } from './SuspenseLoader';
package/dist/index.d.ts CHANGED
@@ -8,3 +8,5 @@ export { checkRemoteHealth, checkModuleLoadable, getRemoteHealthReport, formatHe
8
8
  export { eventBus, createEventBus, } from './event-bus';
9
9
  export type { LoadRemoteOptions, VersionCache, PreloadOptions, PreloadCacheItem, PreloadStatus, } from './types';
10
10
  export { fallbackPlugin } from './plugins/fallback';
11
+ export { ErrorBoundary, RemoteModuleProvider, RemoteModuleRenderer, useRemoteModule, lazyRemote, SuspenseRemote, SuspenseRemoteLoader, withRemote, useRemoteModuleHook, } from './components';
12
+ export type { ErrorBoundaryProps, RemoteModuleCardProps, UseRemoteModuleOptions, LazyRemoteOptions, SuspenseRemoteProps, SuspenseRemoteWithPropsProps, } from './components';
package/dist/main.cjs CHANGED
@@ -1,5 +1,14 @@
1
1
  "use strict";
2
2
  var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.n = (module)=>{
5
+ var getter = module && module.__esModule ? ()=>module['default'] : ()=>module;
6
+ __webpack_require__.d(getter, {
7
+ a: getter
8
+ });
9
+ return getter;
10
+ };
11
+ })();
3
12
  (()=>{
4
13
  __webpack_require__.d = (exports1, definition)=>{
5
14
  for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
@@ -27,31 +36,39 @@ __webpack_require__.d(__webpack_exports__, {
27
36
  compareVersions: ()=>compareVersions,
28
37
  fetchAvailableVersions: ()=>fetchAvailableVersions,
29
38
  sortVersions: ()=>sortVersions,
39
+ useRemoteModuleHook: ()=>useRemoteModuleHook,
30
40
  registerRemoteInstance: ()=>registerRemoteInstance,
31
41
  fallbackPlugin: ()=>fallbackPlugin,
32
42
  createEventBus: ()=>createEventBus,
43
+ withRemote: ()=>withRemote,
33
44
  getPreloadStatus: ()=>getPreloadStatus,
34
45
  parseVersion: ()=>parseVersion,
35
46
  resolveFinalVersion: ()=>resolveFinalVersion,
36
47
  buildFinalUrls: ()=>buildFinalUrls,
37
48
  fetchLatestVersion: ()=>fetchLatestVersion,
38
- isRemoteLoaded: ()=>isRemoteLoaded,
49
+ ErrorBoundary: ()=>ErrorBoundary,
39
50
  getFinalSharedConfig: ()=>getFinalSharedConfig,
51
+ isRemoteLoaded: ()=>isRemoteLoaded,
40
52
  tryLoadRemote: ()=>tryLoadRemote,
41
53
  getVersionCache: ()=>getVersionCache,
42
54
  eventBus: ()=>eventBus,
43
- loadRemoteMultiVersion: ()=>loadRemoteMultiVersion,
55
+ RemoteModuleRenderer: ()=>RemoteModuleRenderer,
44
56
  clearPreloadCache: ()=>clearPreloadCache,
45
- loadReactVersion: ()=>loadReactVersion,
57
+ loadRemoteMultiVersion: ()=>loadRemoteMultiVersion,
46
58
  getRemoteHealthReport: ()=>getRemoteHealthReport,
47
- getStableVersions: ()=>getStableVersions,
48
59
  checkModuleLoadable: ()=>checkModuleLoadable,
49
- buildCdnUrls: ()=>buildCdnUrls,
60
+ getStableVersions: ()=>getStableVersions,
50
61
  extractMajorVersion: ()=>extractMajorVersion,
62
+ buildCdnUrls: ()=>buildCdnUrls,
63
+ loadReactVersion: ()=>loadReactVersion,
51
64
  preloadRemoteList: ()=>preloadRemoteList,
65
+ SuspenseRemoteLoader: ()=>SuspenseRemoteLoader,
52
66
  registerLoadedModule: ()=>registerLoadedModule,
53
- unloadRemote: ()=>unloadRemote,
54
67
  getCompatibleReactVersions: ()=>getCompatibleReactVersions,
68
+ SuspenseRemote: ()=>SuspenseRemote,
69
+ unloadRemote: ()=>unloadRemote,
70
+ useRemoteModule: ()=>useRemoteModule,
71
+ RemoteModuleProvider: ()=>RemoteModuleProvider,
55
72
  cancelPreload: ()=>cancelPreload,
56
73
  findCompatibleVersion: ()=>findCompatibleVersion,
57
74
  getLoadedRemotes: ()=>getLoadedRemotes,
@@ -61,8 +78,9 @@ __webpack_require__.d(__webpack_exports__, {
61
78
  formatHealthStatus: ()=>formatHealthStatus,
62
79
  unloadAll: ()=>unloadAll,
63
80
  setVersionCache: ()=>setVersionCache,
64
- isPrerelease: ()=>isPrerelease,
81
+ lazyRemote: ()=>lazyRemote,
65
82
  checkRemoteHealth: ()=>checkRemoteHealth,
83
+ isPrerelease: ()=>isPrerelease,
66
84
  checkVersionCompatibility: ()=>checkVersionCompatibility
67
85
  });
68
86
  const runtime_namespaceObject = require("@module-federation/enhanced/runtime");
@@ -751,6 +769,303 @@ const eventBus = EventBusClass.create();
751
769
  function createEventBus() {
752
770
  return EventBusClass.create();
753
771
  }
772
+ const external_react_namespaceObject = require("react");
773
+ var external_react_default = /*#__PURE__*/ __webpack_require__.n(external_react_namespaceObject);
774
+ class ErrorBoundary extends external_react_default().Component {
775
+ constructor(props){
776
+ super(props);
777
+ this.state = {
778
+ hasError: false,
779
+ error: null,
780
+ errorInfo: null
781
+ };
782
+ }
783
+ static getDerivedStateFromError(error) {
784
+ return {
785
+ hasError: true,
786
+ error,
787
+ errorInfo: null
788
+ };
789
+ }
790
+ componentDidCatch(error, errorInfo) {
791
+ this.setState({
792
+ errorInfo
793
+ });
794
+ this.props.onError?.(error, errorInfo);
795
+ console.error('[RemoteReloadUtils] ErrorBoundary caught error:', error, errorInfo);
796
+ }
797
+ handleReset = ()=>{
798
+ this.setState({
799
+ hasError: false,
800
+ error: null,
801
+ errorInfo: null
802
+ });
803
+ this.props.onReset?.();
804
+ };
805
+ render() {
806
+ if (this.state.hasError && this.state.error) {
807
+ if ('function' == typeof this.props.fallback) return this.props.fallback(this.state.error, this.handleReset);
808
+ if (void 0 !== this.props.fallback) return this.props.fallback;
809
+ return /*#__PURE__*/ external_react_default().createElement("div", {
810
+ role: "alert",
811
+ style: {
812
+ padding: '16px',
813
+ border: '1px solid #ffcccc',
814
+ backgroundColor: '#fff5f5',
815
+ borderRadius: '4px'
816
+ }
817
+ }, /*#__PURE__*/ external_react_default().createElement("h3", null, "Something went wrong"), /*#__PURE__*/ external_react_default().createElement("p", null, this.state.error.message), /*#__PURE__*/ external_react_default().createElement("button", {
818
+ onClick: this.handleReset,
819
+ style: {
820
+ marginTop: '8px',
821
+ padding: '8px 16px',
822
+ cursor: 'pointer'
823
+ }
824
+ }, "Try again"));
825
+ }
826
+ return this.props.children;
827
+ }
828
+ }
829
+ function useRemoteModule({ pkg, version, moduleName, scopeName, onError, onLoad, retryKey = 0 }) {
830
+ const [moduleState, setModuleState] = (0, external_react_namespaceObject.useState)({
831
+ loading: true,
832
+ error: null,
833
+ component: null
834
+ });
835
+ (0, external_react_namespaceObject.useEffect)(()=>{
836
+ let mounted = true;
837
+ async function loadModule() {
838
+ try {
839
+ setModuleState((prev)=>({
840
+ ...prev,
841
+ loading: true,
842
+ error: null
843
+ }));
844
+ const { mf } = await loadRemoteMultiVersion({
845
+ name: scopeName,
846
+ pkg,
847
+ version
848
+ }, []);
849
+ if (!mf || !mounted) return;
850
+ const mod = await mf.loadRemote(`${scopeName}/${moduleName}`);
851
+ if (!mounted) return;
852
+ if (mod && 'object' == typeof mod && 'default' in mod) {
853
+ const Component = mod.default;
854
+ setModuleState({
855
+ loading: false,
856
+ error: null,
857
+ component: Component
858
+ });
859
+ onLoad?.(Component);
860
+ } else throw new Error(`Module "${scopeName}/${moduleName}" does not export a default component`);
861
+ } catch (err) {
862
+ if (mounted) {
863
+ const error = err instanceof Error ? err : new Error(String(err));
864
+ setModuleState({
865
+ loading: false,
866
+ error,
867
+ component: null
868
+ });
869
+ onError?.(error);
870
+ }
871
+ }
872
+ }
873
+ loadModule();
874
+ return ()=>{
875
+ mounted = false;
876
+ };
877
+ }, [
878
+ pkg,
879
+ version,
880
+ moduleName,
881
+ scopeName,
882
+ onError,
883
+ onLoad,
884
+ retryKey
885
+ ]);
886
+ return moduleState;
887
+ }
888
+ function RemoteModuleRenderer({ pkg, version, moduleName, scopeName, loadingFallback, errorFallback, componentProps, className, style, onError, onLoad }) {
889
+ const moduleState = useRemoteModule({
890
+ pkg,
891
+ version,
892
+ moduleName,
893
+ scopeName,
894
+ onError,
895
+ onLoad
896
+ });
897
+ const [retryKey, setRetryKey] = (0, external_react_namespaceObject.useState)(0);
898
+ const handleRetry = (0, external_react_namespaceObject.useCallback)(()=>{
899
+ setRetryKey((prev)=>prev + 1);
900
+ }, []);
901
+ (0, external_react_namespaceObject.useEffect)(()=>{}, [
902
+ retryKey
903
+ ]);
904
+ if (moduleState.loading) return /*#__PURE__*/ external_react_default().createElement("div", {
905
+ className: className,
906
+ style: style,
907
+ role: "status",
908
+ "aria-live": "polite"
909
+ }, loadingFallback || /*#__PURE__*/ external_react_default().createElement("div", {
910
+ className: "module-card module-card--loading"
911
+ }, /*#__PURE__*/ external_react_default().createElement("div", {
912
+ className: "loading-spinner",
913
+ "aria-hidden": "true"
914
+ }), /*#__PURE__*/ external_react_default().createElement("span", null, "Loading ", moduleName, "...")));
915
+ if (moduleState.error) {
916
+ if ('function' == typeof errorFallback) return /*#__PURE__*/ external_react_default().createElement(external_react_default().Fragment, null, errorFallback(moduleState.error, handleRetry));
917
+ if (void 0 !== errorFallback) return /*#__PURE__*/ external_react_default().createElement(external_react_default().Fragment, null, errorFallback);
918
+ return /*#__PURE__*/ external_react_default().createElement("div", {
919
+ className: className,
920
+ style: style,
921
+ role: "alert"
922
+ }, /*#__PURE__*/ external_react_default().createElement("div", {
923
+ className: "module-card module-card--error"
924
+ }, /*#__PURE__*/ external_react_default().createElement("span", {
925
+ className: "error-icon",
926
+ "aria-hidden": "true"
927
+ }, "!"), /*#__PURE__*/ external_react_default().createElement("span", null, "Failed to load ", moduleName), /*#__PURE__*/ external_react_default().createElement("p", {
928
+ className: "error-message"
929
+ }, moduleState.error.message), /*#__PURE__*/ external_react_default().createElement("button", {
930
+ onClick: handleRetry,
931
+ className: "retry-button",
932
+ type: "button"
933
+ }, "Retry")));
934
+ }
935
+ if (!moduleState.component) return null;
936
+ const Component = moduleState.component;
937
+ return /*#__PURE__*/ external_react_default().createElement("div", {
938
+ className: className,
939
+ style: style
940
+ }, /*#__PURE__*/ external_react_default().createElement(Component, componentProps));
941
+ }
942
+ function RemoteModuleProvider(props) {
943
+ const { disableErrorBoundary, errorFallback, loadingFallback, errorBoundaryOptions } = props;
944
+ if (disableErrorBoundary) return /*#__PURE__*/ external_react_default().createElement(external_react_namespaceObject.Suspense, {
945
+ fallback: loadingFallback || /*#__PURE__*/ external_react_default().createElement("div", null, "Loading...")
946
+ }, /*#__PURE__*/ external_react_default().createElement(RemoteModuleRenderer, props));
947
+ return /*#__PURE__*/ external_react_default().createElement(ErrorBoundary, {
948
+ fallback: errorFallback,
949
+ onError: errorBoundaryOptions?.onError,
950
+ onReset: errorBoundaryOptions?.onReset
951
+ }, /*#__PURE__*/ external_react_default().createElement(external_react_namespaceObject.Suspense, {
952
+ fallback: loadingFallback || /*#__PURE__*/ external_react_default().createElement("div", null, "Loading...")
953
+ }, /*#__PURE__*/ external_react_default().createElement(RemoteModuleRenderer, props)));
954
+ }
955
+ function lazyRemote(options) {
956
+ const { pkg, version = 'latest', moduleName, scopeName, maxRetries = 3, retryDelay = 1000 } = options;
957
+ let retryCount = 0;
958
+ const loadComponent = async ()=>{
959
+ try {
960
+ const { mf } = await loadRemoteMultiVersion({
961
+ name: scopeName,
962
+ pkg,
963
+ version
964
+ }, []);
965
+ if (!mf) throw new Error(`[RemoteReloadUtils] Failed to get Module Federation instance for ${scopeName}`);
966
+ const mod = await mf.loadRemote(`${scopeName}/${moduleName}`);
967
+ if (!mod || 'object' != typeof mod || !('default' in mod)) throw new Error(`[RemoteReloadUtils] Module "${scopeName}/${moduleName}" does not export a default component`);
968
+ return {
969
+ default: mod.default
970
+ };
971
+ } catch (error) {
972
+ if (retryCount < maxRetries) {
973
+ retryCount++;
974
+ await new Promise((resolve)=>setTimeout(resolve, retryDelay * retryCount));
975
+ return loadComponent();
976
+ }
977
+ throw error;
978
+ }
979
+ };
980
+ return /*#__PURE__*/ (0, external_react_namespaceObject.lazy)(loadComponent);
981
+ }
982
+ function SuspenseRemote({ fallback, children }) {
983
+ return /*#__PURE__*/ external_react_default().createElement(external_react_namespaceObject.Suspense, {
984
+ fallback: fallback || /*#__PURE__*/ external_react_default().createElement("div", null, "Loading...")
985
+ }, children);
986
+ }
987
+ function SuspenseRemoteLoader({ pkg, version = 'latest', moduleName, scopeName, fallback, errorFallback, componentProps }) {
988
+ const RemoteComponent = lazyRemote({
989
+ pkg,
990
+ version,
991
+ moduleName,
992
+ scopeName
993
+ });
994
+ if (errorFallback) return /*#__PURE__*/ external_react_default().createElement(ErrorBoundary, {
995
+ fallback: errorFallback
996
+ }, /*#__PURE__*/ external_react_default().createElement(external_react_namespaceObject.Suspense, {
997
+ fallback: fallback || /*#__PURE__*/ external_react_default().createElement("div", null, "Loading...")
998
+ }, /*#__PURE__*/ external_react_default().createElement(RemoteComponent, componentProps)));
999
+ return /*#__PURE__*/ external_react_default().createElement(external_react_namespaceObject.Suspense, {
1000
+ fallback: fallback || /*#__PURE__*/ external_react_default().createElement("div", null, "Loading...")
1001
+ }, /*#__PURE__*/ external_react_default().createElement(RemoteComponent, componentProps));
1002
+ }
1003
+ function withRemote(WrappedComponent, options) {
1004
+ const RemoteComponent = lazyRemote(options);
1005
+ return function(props) {
1006
+ return /*#__PURE__*/ external_react_default().createElement(external_react_namespaceObject.Suspense, {
1007
+ fallback: /*#__PURE__*/ external_react_default().createElement("div", null, "Loading...")
1008
+ }, /*#__PURE__*/ external_react_default().createElement(RemoteComponent, props));
1009
+ };
1010
+ }
1011
+ function useRemoteModuleHook(options) {
1012
+ const { pkg, version = 'latest', moduleName, scopeName } = options;
1013
+ const [state, setState] = (0, external_react_namespaceObject.useState)({
1014
+ component: null,
1015
+ loading: true,
1016
+ error: null
1017
+ });
1018
+ (0, external_react_namespaceObject.useEffect)(()=>{
1019
+ let mounted = true;
1020
+ async function load() {
1021
+ try {
1022
+ setState((prev)=>({
1023
+ ...prev,
1024
+ loading: true,
1025
+ error: null
1026
+ }));
1027
+ const { mf } = await loadRemoteMultiVersion({
1028
+ name: scopeName,
1029
+ pkg,
1030
+ version
1031
+ }, []);
1032
+ if (!mf) throw new Error(`[RemoteReloadUtils] Failed to get Module Federation instance for ${scopeName}`);
1033
+ const mod = await mf.loadRemote(`${scopeName}/${moduleName}`);
1034
+ if (mounted) if (mod && 'object' == typeof mod && 'default' in mod) setState({
1035
+ component: mod.default,
1036
+ loading: false,
1037
+ error: null
1038
+ });
1039
+ else throw new Error(`[RemoteReloadUtils] Module "${scopeName}/${moduleName}" does not export a default component`);
1040
+ } catch (err) {
1041
+ if (mounted) setState({
1042
+ component: null,
1043
+ loading: false,
1044
+ error: err instanceof Error ? err : new Error(String(err))
1045
+ });
1046
+ }
1047
+ }
1048
+ load();
1049
+ return ()=>{
1050
+ mounted = false;
1051
+ };
1052
+ }, [
1053
+ pkg,
1054
+ version,
1055
+ moduleName,
1056
+ scopeName
1057
+ ]);
1058
+ return {
1059
+ component: state.component,
1060
+ loading: state.loading,
1061
+ error: state.error
1062
+ };
1063
+ }
1064
+ exports.ErrorBoundary = __webpack_exports__.ErrorBoundary;
1065
+ exports.RemoteModuleProvider = __webpack_exports__.RemoteModuleProvider;
1066
+ exports.RemoteModuleRenderer = __webpack_exports__.RemoteModuleRenderer;
1067
+ exports.SuspenseRemote = __webpack_exports__.SuspenseRemote;
1068
+ exports.SuspenseRemoteLoader = __webpack_exports__.SuspenseRemoteLoader;
754
1069
  exports.buildCdnUrls = __webpack_exports__.buildCdnUrls;
755
1070
  exports.buildFinalUrls = __webpack_exports__.buildFinalUrls;
756
1071
  exports.cancelPreload = __webpack_exports__.cancelPreload;
@@ -777,6 +1092,7 @@ exports.getStableVersions = __webpack_exports__.getStableVersions;
777
1092
  exports.getVersionCache = __webpack_exports__.getVersionCache;
778
1093
  exports.isPrerelease = __webpack_exports__.isPrerelease;
779
1094
  exports.isRemoteLoaded = __webpack_exports__.isRemoteLoaded;
1095
+ exports.lazyRemote = __webpack_exports__.lazyRemote;
780
1096
  exports.loadReactVersion = __webpack_exports__.loadReactVersion;
781
1097
  exports.loadRemoteMultiVersion = __webpack_exports__.loadRemoteMultiVersion;
782
1098
  exports.parseVersion = __webpack_exports__.parseVersion;
@@ -791,7 +1107,15 @@ exports.sortVersions = __webpack_exports__.sortVersions;
791
1107
  exports.tryLoadRemote = __webpack_exports__.tryLoadRemote;
792
1108
  exports.unloadAll = __webpack_exports__.unloadAll;
793
1109
  exports.unloadRemote = __webpack_exports__.unloadRemote;
1110
+ exports.useRemoteModule = __webpack_exports__.useRemoteModule;
1111
+ exports.useRemoteModuleHook = __webpack_exports__.useRemoteModuleHook;
1112
+ exports.withRemote = __webpack_exports__.withRemote;
794
1113
  for(var __webpack_i__ in __webpack_exports__)if (-1 === [
1114
+ "ErrorBoundary",
1115
+ "RemoteModuleProvider",
1116
+ "RemoteModuleRenderer",
1117
+ "SuspenseRemote",
1118
+ "SuspenseRemoteLoader",
795
1119
  "buildCdnUrls",
796
1120
  "buildFinalUrls",
797
1121
  "cancelPreload",
@@ -818,6 +1142,7 @@ for(var __webpack_i__ in __webpack_exports__)if (-1 === [
818
1142
  "getVersionCache",
819
1143
  "isPrerelease",
820
1144
  "isRemoteLoaded",
1145
+ "lazyRemote",
821
1146
  "loadReactVersion",
822
1147
  "loadRemoteMultiVersion",
823
1148
  "parseVersion",
@@ -831,7 +1156,10 @@ for(var __webpack_i__ in __webpack_exports__)if (-1 === [
831
1156
  "sortVersions",
832
1157
  "tryLoadRemote",
833
1158
  "unloadAll",
834
- "unloadRemote"
1159
+ "unloadRemote",
1160
+ "useRemoteModule",
1161
+ "useRemoteModuleHook",
1162
+ "withRemote"
835
1163
  ].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
836
1164
  Object.defineProperty(exports, '__esModule', {
837
1165
  value: true
package/dist/main.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { createInstance } from "@module-federation/enhanced/runtime";
2
+ import react, { Suspense, lazy, useCallback, useEffect, useState } from "react";
2
3
  async function loadReactVersion(version) {
3
4
  const runtime = await createInstance({
4
5
  name: `react_${version}_runtime`,
@@ -684,4 +685,294 @@ const eventBus = EventBusClass.create();
684
685
  function createEventBus() {
685
686
  return EventBusClass.create();
686
687
  }
687
- export { buildCdnUrls, buildFinalUrls, cancelPreload, checkModuleLoadable, checkRemoteHealth, checkVersionCompatibility, clearPreloadCache, compareVersions, createEventBus, eventBus, extractMajorVersion, fallbackPlugin, fetchAvailableVersions, fetchLatestVersion, findCompatibleVersion, formatHealthStatus, getCompatibleReactVersions, getFinalSharedConfig, getLatestVersion, getLoadedRemotes, getPreloadStatus, getRemoteHealthReport, getStableVersions, getVersionCache, isPrerelease, isRemoteLoaded, loadReactVersion, loadRemoteMultiVersion, parseVersion, preloadRemote, preloadRemoteList, registerLoadedModule, registerRemoteInstance, resolveFinalVersion, satisfiesVersion, setVersionCache, sortVersions, tryLoadRemote, unloadAll, unloadRemote };
688
+ class ErrorBoundary extends react.Component {
689
+ constructor(props){
690
+ super(props);
691
+ this.state = {
692
+ hasError: false,
693
+ error: null,
694
+ errorInfo: null
695
+ };
696
+ }
697
+ static getDerivedStateFromError(error) {
698
+ return {
699
+ hasError: true,
700
+ error,
701
+ errorInfo: null
702
+ };
703
+ }
704
+ componentDidCatch(error, errorInfo) {
705
+ this.setState({
706
+ errorInfo
707
+ });
708
+ this.props.onError?.(error, errorInfo);
709
+ console.error('[RemoteReloadUtils] ErrorBoundary caught error:', error, errorInfo);
710
+ }
711
+ handleReset = ()=>{
712
+ this.setState({
713
+ hasError: false,
714
+ error: null,
715
+ errorInfo: null
716
+ });
717
+ this.props.onReset?.();
718
+ };
719
+ render() {
720
+ if (this.state.hasError && this.state.error) {
721
+ if ('function' == typeof this.props.fallback) return this.props.fallback(this.state.error, this.handleReset);
722
+ if (void 0 !== this.props.fallback) return this.props.fallback;
723
+ return /*#__PURE__*/ react.createElement("div", {
724
+ role: "alert",
725
+ style: {
726
+ padding: '16px',
727
+ border: '1px solid #ffcccc',
728
+ backgroundColor: '#fff5f5',
729
+ borderRadius: '4px'
730
+ }
731
+ }, /*#__PURE__*/ react.createElement("h3", null, "Something went wrong"), /*#__PURE__*/ react.createElement("p", null, this.state.error.message), /*#__PURE__*/ react.createElement("button", {
732
+ onClick: this.handleReset,
733
+ style: {
734
+ marginTop: '8px',
735
+ padding: '8px 16px',
736
+ cursor: 'pointer'
737
+ }
738
+ }, "Try again"));
739
+ }
740
+ return this.props.children;
741
+ }
742
+ }
743
+ function useRemoteModule({ pkg, version, moduleName, scopeName, onError, onLoad, retryKey = 0 }) {
744
+ const [moduleState, setModuleState] = useState({
745
+ loading: true,
746
+ error: null,
747
+ component: null
748
+ });
749
+ useEffect(()=>{
750
+ let mounted = true;
751
+ async function loadModule() {
752
+ try {
753
+ setModuleState((prev)=>({
754
+ ...prev,
755
+ loading: true,
756
+ error: null
757
+ }));
758
+ const { mf } = await loadRemoteMultiVersion({
759
+ name: scopeName,
760
+ pkg,
761
+ version
762
+ }, []);
763
+ if (!mf || !mounted) return;
764
+ const mod = await mf.loadRemote(`${scopeName}/${moduleName}`);
765
+ if (!mounted) return;
766
+ if (mod && 'object' == typeof mod && 'default' in mod) {
767
+ const Component = mod.default;
768
+ setModuleState({
769
+ loading: false,
770
+ error: null,
771
+ component: Component
772
+ });
773
+ onLoad?.(Component);
774
+ } else throw new Error(`Module "${scopeName}/${moduleName}" does not export a default component`);
775
+ } catch (err) {
776
+ if (mounted) {
777
+ const error = err instanceof Error ? err : new Error(String(err));
778
+ setModuleState({
779
+ loading: false,
780
+ error,
781
+ component: null
782
+ });
783
+ onError?.(error);
784
+ }
785
+ }
786
+ }
787
+ loadModule();
788
+ return ()=>{
789
+ mounted = false;
790
+ };
791
+ }, [
792
+ pkg,
793
+ version,
794
+ moduleName,
795
+ scopeName,
796
+ onError,
797
+ onLoad,
798
+ retryKey
799
+ ]);
800
+ return moduleState;
801
+ }
802
+ function RemoteModuleRenderer({ pkg, version, moduleName, scopeName, loadingFallback, errorFallback, componentProps, className, style, onError, onLoad }) {
803
+ const moduleState = useRemoteModule({
804
+ pkg,
805
+ version,
806
+ moduleName,
807
+ scopeName,
808
+ onError,
809
+ onLoad
810
+ });
811
+ const [retryKey, setRetryKey] = useState(0);
812
+ const handleRetry = useCallback(()=>{
813
+ setRetryKey((prev)=>prev + 1);
814
+ }, []);
815
+ useEffect(()=>{}, [
816
+ retryKey
817
+ ]);
818
+ if (moduleState.loading) return /*#__PURE__*/ react.createElement("div", {
819
+ className: className,
820
+ style: style,
821
+ role: "status",
822
+ "aria-live": "polite"
823
+ }, loadingFallback || /*#__PURE__*/ react.createElement("div", {
824
+ className: "module-card module-card--loading"
825
+ }, /*#__PURE__*/ react.createElement("div", {
826
+ className: "loading-spinner",
827
+ "aria-hidden": "true"
828
+ }), /*#__PURE__*/ react.createElement("span", null, "Loading ", moduleName, "...")));
829
+ if (moduleState.error) {
830
+ if ('function' == typeof errorFallback) return /*#__PURE__*/ react.createElement(react.Fragment, null, errorFallback(moduleState.error, handleRetry));
831
+ if (void 0 !== errorFallback) return /*#__PURE__*/ react.createElement(react.Fragment, null, errorFallback);
832
+ return /*#__PURE__*/ react.createElement("div", {
833
+ className: className,
834
+ style: style,
835
+ role: "alert"
836
+ }, /*#__PURE__*/ react.createElement("div", {
837
+ className: "module-card module-card--error"
838
+ }, /*#__PURE__*/ react.createElement("span", {
839
+ className: "error-icon",
840
+ "aria-hidden": "true"
841
+ }, "!"), /*#__PURE__*/ react.createElement("span", null, "Failed to load ", moduleName), /*#__PURE__*/ react.createElement("p", {
842
+ className: "error-message"
843
+ }, moduleState.error.message), /*#__PURE__*/ react.createElement("button", {
844
+ onClick: handleRetry,
845
+ className: "retry-button",
846
+ type: "button"
847
+ }, "Retry")));
848
+ }
849
+ if (!moduleState.component) return null;
850
+ const Component = moduleState.component;
851
+ return /*#__PURE__*/ react.createElement("div", {
852
+ className: className,
853
+ style: style
854
+ }, /*#__PURE__*/ react.createElement(Component, componentProps));
855
+ }
856
+ function RemoteModuleProvider(props) {
857
+ const { disableErrorBoundary, errorFallback, loadingFallback, errorBoundaryOptions } = props;
858
+ if (disableErrorBoundary) return /*#__PURE__*/ react.createElement(Suspense, {
859
+ fallback: loadingFallback || /*#__PURE__*/ react.createElement("div", null, "Loading...")
860
+ }, /*#__PURE__*/ react.createElement(RemoteModuleRenderer, props));
861
+ return /*#__PURE__*/ react.createElement(ErrorBoundary, {
862
+ fallback: errorFallback,
863
+ onError: errorBoundaryOptions?.onError,
864
+ onReset: errorBoundaryOptions?.onReset
865
+ }, /*#__PURE__*/ react.createElement(Suspense, {
866
+ fallback: loadingFallback || /*#__PURE__*/ react.createElement("div", null, "Loading...")
867
+ }, /*#__PURE__*/ react.createElement(RemoteModuleRenderer, props)));
868
+ }
869
+ function lazyRemote(options) {
870
+ const { pkg, version = 'latest', moduleName, scopeName, maxRetries = 3, retryDelay = 1000 } = options;
871
+ let retryCount = 0;
872
+ const loadComponent = async ()=>{
873
+ try {
874
+ const { mf } = await loadRemoteMultiVersion({
875
+ name: scopeName,
876
+ pkg,
877
+ version
878
+ }, []);
879
+ if (!mf) throw new Error(`[RemoteReloadUtils] Failed to get Module Federation instance for ${scopeName}`);
880
+ const mod = await mf.loadRemote(`${scopeName}/${moduleName}`);
881
+ if (!mod || 'object' != typeof mod || !('default' in mod)) throw new Error(`[RemoteReloadUtils] Module "${scopeName}/${moduleName}" does not export a default component`);
882
+ return {
883
+ default: mod.default
884
+ };
885
+ } catch (error) {
886
+ if (retryCount < maxRetries) {
887
+ retryCount++;
888
+ await new Promise((resolve)=>setTimeout(resolve, retryDelay * retryCount));
889
+ return loadComponent();
890
+ }
891
+ throw error;
892
+ }
893
+ };
894
+ return /*#__PURE__*/ lazy(loadComponent);
895
+ }
896
+ function SuspenseRemote({ fallback, children }) {
897
+ return /*#__PURE__*/ react.createElement(Suspense, {
898
+ fallback: fallback || /*#__PURE__*/ react.createElement("div", null, "Loading...")
899
+ }, children);
900
+ }
901
+ function SuspenseRemoteLoader({ pkg, version = 'latest', moduleName, scopeName, fallback, errorFallback, componentProps }) {
902
+ const RemoteComponent = lazyRemote({
903
+ pkg,
904
+ version,
905
+ moduleName,
906
+ scopeName
907
+ });
908
+ if (errorFallback) return /*#__PURE__*/ react.createElement(ErrorBoundary, {
909
+ fallback: errorFallback
910
+ }, /*#__PURE__*/ react.createElement(Suspense, {
911
+ fallback: fallback || /*#__PURE__*/ react.createElement("div", null, "Loading...")
912
+ }, /*#__PURE__*/ react.createElement(RemoteComponent, componentProps)));
913
+ return /*#__PURE__*/ react.createElement(Suspense, {
914
+ fallback: fallback || /*#__PURE__*/ react.createElement("div", null, "Loading...")
915
+ }, /*#__PURE__*/ react.createElement(RemoteComponent, componentProps));
916
+ }
917
+ function withRemote(WrappedComponent, options) {
918
+ const RemoteComponent = lazyRemote(options);
919
+ return function(props) {
920
+ return /*#__PURE__*/ react.createElement(Suspense, {
921
+ fallback: /*#__PURE__*/ react.createElement("div", null, "Loading...")
922
+ }, /*#__PURE__*/ react.createElement(RemoteComponent, props));
923
+ };
924
+ }
925
+ function useRemoteModuleHook(options) {
926
+ const { pkg, version = 'latest', moduleName, scopeName } = options;
927
+ const [state, setState] = useState({
928
+ component: null,
929
+ loading: true,
930
+ error: null
931
+ });
932
+ useEffect(()=>{
933
+ let mounted = true;
934
+ async function load() {
935
+ try {
936
+ setState((prev)=>({
937
+ ...prev,
938
+ loading: true,
939
+ error: null
940
+ }));
941
+ const { mf } = await loadRemoteMultiVersion({
942
+ name: scopeName,
943
+ pkg,
944
+ version
945
+ }, []);
946
+ if (!mf) throw new Error(`[RemoteReloadUtils] Failed to get Module Federation instance for ${scopeName}`);
947
+ const mod = await mf.loadRemote(`${scopeName}/${moduleName}`);
948
+ if (mounted) if (mod && 'object' == typeof mod && 'default' in mod) setState({
949
+ component: mod.default,
950
+ loading: false,
951
+ error: null
952
+ });
953
+ else throw new Error(`[RemoteReloadUtils] Module "${scopeName}/${moduleName}" does not export a default component`);
954
+ } catch (err) {
955
+ if (mounted) setState({
956
+ component: null,
957
+ loading: false,
958
+ error: err instanceof Error ? err : new Error(String(err))
959
+ });
960
+ }
961
+ }
962
+ load();
963
+ return ()=>{
964
+ mounted = false;
965
+ };
966
+ }, [
967
+ pkg,
968
+ version,
969
+ moduleName,
970
+ scopeName
971
+ ]);
972
+ return {
973
+ component: state.component,
974
+ loading: state.loading,
975
+ error: state.error
976
+ };
977
+ }
978
+ export { ErrorBoundary, RemoteModuleProvider, RemoteModuleRenderer, SuspenseRemote, SuspenseRemoteLoader, buildCdnUrls, buildFinalUrls, cancelPreload, checkModuleLoadable, checkRemoteHealth, checkVersionCompatibility, clearPreloadCache, compareVersions, createEventBus, eventBus, extractMajorVersion, fallbackPlugin, fetchAvailableVersions, fetchLatestVersion, findCompatibleVersion, formatHealthStatus, getCompatibleReactVersions, getFinalSharedConfig, getLatestVersion, getLoadedRemotes, getPreloadStatus, getRemoteHealthReport, getStableVersions, getVersionCache, isPrerelease, isRemoteLoaded, lazyRemote, loadReactVersion, loadRemoteMultiVersion, parseVersion, preloadRemote, preloadRemoteList, registerLoadedModule, registerRemoteInstance, resolveFinalVersion, satisfiesVersion, setVersionCache, sortVersions, tryLoadRemote, unloadAll, unloadRemote, useRemoteModule, useRemoteModuleHook, withRemote };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "remote-reload-utils",
3
- "version": "0.0.10",
3
+ "version": "0.0.12",
4
4
  "type": "module",
5
5
  "description": "Utilities for remote reload in Module Federation & React Component",
6
6
  "exports": {