1
- import React from 'react' ;
1
+ import React , { useState , useEffect , Suspense } from 'react' ;
2
+
2
3
import { init , loadRemote } from '@module-federation/runtime'
3
4
4
5
init ( {
@@ -16,104 +17,40 @@ init({
16
17
} )
17
18
18
19
19
- function loadComponent ( scope , module ) {
20
- return async ( ) => {
21
- // Initializes the share scope. This fills it with known provided modules from this build and all remotes
22
- const Module = await loadRemote ( `${ scope } /${ module . slice ( 2 ) } ` ) ;
23
- return Module ;
24
- } ;
25
- }
26
-
27
- const urlCache = new Set ( ) ;
28
- const useDynamicScript = url => {
29
- const [ ready , setReady ] = React . useState ( false ) ;
30
- const [ errorLoading , setErrorLoading ] = React . useState ( false ) ;
31
-
32
- React . useEffect ( ( ) => {
33
- if ( ! url ) return ;
34
-
35
- if ( urlCache . has ( url ) ) {
36
- setReady ( true ) ;
37
- setErrorLoading ( false ) ;
38
- return ;
39
- }
40
-
41
- setReady ( false ) ;
42
- setErrorLoading ( false ) ;
43
-
44
- const element = document . createElement ( 'script' ) ;
45
-
46
- element . src = url ;
47
- element . type = 'text/javascript' ;
48
- element . async = true ;
49
-
50
- element . onload = ( ) => {
51
- urlCache . add ( url ) ;
52
- setReady ( true ) ;
53
- } ;
20
+ function useDynamicImport ( { module, scope} ) {
21
+ console . log ( module , scope )
22
+ const [ component , setComponent ] = useState ( null ) ;
54
23
55
- element . onerror = ( ) => {
56
- setReady ( false ) ;
57
- setErrorLoading ( true ) ;
24
+ useEffect ( ( ) => {
25
+ if ( ! module && ! scope ) return
26
+ const loadComponent = async ( ) => {
27
+ const { default : component } = await loadRemote ( `${ scope } /${ module } ` ) ;
28
+ setComponent ( ( ) => component ) ;
58
29
} ;
59
-
60
- document . head . appendChild ( element ) ;
61
-
62
- return ( ) => {
63
- urlCache . delete ( url ) ;
64
- document . head . removeChild ( element ) ;
65
- } ;
66
- } , [ url ] ) ;
67
-
68
- return {
69
- errorLoading,
70
- ready,
71
- } ;
72
- } ;
73
-
74
- const componentCache = new Map ( ) ;
75
- export const useFederatedComponent = ( remoteUrl , scope , module ) => {
76
- const key = `${ remoteUrl } -${ scope } -${ module } ` ;
77
- const [ Component , setComponent ] = React . useState ( null ) ;
78
-
79
- const { ready, errorLoading } = useDynamicScript ( remoteUrl ) ;
80
- React . useEffect ( ( ) => {
81
- if ( Component ) setComponent ( null ) ;
82
- // Only recalculate when key changes
83
- } , [ key ] ) ;
84
-
85
- React . useEffect ( ( ) => {
86
- if ( ready && ! Component ) {
87
- const Comp = React . lazy ( loadComponent ( scope , module ) ) ;
88
- componentCache . set ( key , Comp ) ;
89
- setComponent ( Comp ) ;
90
- }
91
- // key includes all dependencies (scope/module)
92
- } , [ Component , ready , key ] ) ;
93
-
94
- return { errorLoading, Component } ;
95
- } ;
30
+ loadComponent ( ) ;
31
+ } , [ module , scope ] ) ;
32
+ const fallback = ( ) => null
33
+ return component || fallback
34
+ }
96
35
97
36
function App ( ) {
98
- const [ { module, scope, url } , setSystem ] = React . useState ( { } ) ;
37
+ const [ { module, scope } , setSystem ] = React . useState ( { } ) ;
99
38
100
39
function setApp2 ( ) {
101
40
setSystem ( {
102
- url : 'http://localhost:3002/remoteEntry.js' ,
103
41
scope : 'app2' ,
104
- module : './ Widget' ,
42
+ module : 'Widget' ,
105
43
} ) ;
106
44
}
107
45
108
46
function setApp3 ( ) {
109
47
setSystem ( {
110
- url : 'http://localhost:3003/remoteEntry.js' ,
111
48
scope : 'app3' ,
112
- module : './ Widget' ,
49
+ module : 'Widget' ,
113
50
} ) ;
114
51
}
115
52
116
- const { Component : FederatedComponent , errorLoading } = useFederatedComponent ( url , scope , module ) ;
53
+ const Component = useDynamicImport ( { module , scope} ) ;
117
54
118
55
return (
119
56
< div
@@ -132,9 +69,7 @@ function App() {
132
69
< button onClick = { setApp3 } > Load App 3 Widget</ button >
133
70
< div style = { { marginTop : '2em' } } >
134
71
< React . Suspense fallback = "Loading System" >
135
- { errorLoading
136
- ? `Error loading module "${ module } "`
137
- : FederatedComponent && < FederatedComponent /> }
72
+ < Component />
138
73
</ React . Suspense >
139
74
</ div >
140
75
</ div >
0 commit comments