@@ -2,31 +2,99 @@ import type {
22 ModuleFederationRuntimePlugin ,
33 Shared ,
44} from '@module-federation/runtime/types' ;
5- import { loadScript } from '@module-federation/sdk' ;
5+ import { loadScript , createScript } from '@module-federation/sdk' ;
66
77import { isObject , getUnpkgUrl } from '../index' ;
88import { definePropertyGlobalVal } from '../sdk' ;
9- import { __FEDERATION_DEVTOOLS__ } from '../../template' ;
9+ import {
10+ __FEDERATION_DEVTOOLS__ ,
11+ __EAGER_SHARE__ ,
12+ __ENABLE_FAST_REFRESH__ ,
13+ } from '../../template/constant' ;
14+
15+ const SUPPORT_PKGS = [ 'react' , 'react-dom' ] ;
16+
17+ /**
18+ * Fetch and execute a UMD module synchronously
19+ * @param url - URL of the UMD module to load
20+ * @returns The module exports
21+ */
22+ const fetchAndExecuteUmdSync = ( url : string ) : any => {
23+ try {
24+ const response = new XMLHttpRequest ( ) ;
25+ response . open ( 'GET' , url , false ) ;
26+ response . overrideMimeType ( 'text/plain' ) ;
27+ response . send ( ) ;
28+
29+ if ( response . status === 200 ) {
30+ const scriptContent = response . responseText ;
31+
32+ // Create a new Function constructor to execute the script synchronously
33+ const moduleFunction = new Function ( scriptContent ) ;
34+
35+ // Execute the function and return the module exports
36+ return moduleFunction ( window ) ;
37+ } else {
38+ throw new Error (
39+ `Failed to load module from ${ url } : HTTP ${ response . status } ` ,
40+ ) ;
41+ }
42+ } catch ( error : any ) {
43+ throw new Error ( `Failed to fetch module from ${ url } : ${ error . message } ` ) ;
44+ }
45+ } ;
46+
47+ const getDevtoolsMessage = ( ) => {
48+ const devtoolsMessageStr = localStorage . getItem ( __FEDERATION_DEVTOOLS__ ) ;
49+ if ( devtoolsMessageStr ) {
50+ try {
51+ return JSON . parse ( devtoolsMessageStr ) ;
52+ } catch ( e ) {
53+ console . debug ( 'Fast Refresh Plugin Error: ' , e ) ;
54+ }
55+ }
56+ return null ;
57+ } ;
58+
59+ const devtoolsMessage = getDevtoolsMessage ( ) ;
60+ if (
61+ devtoolsMessage ?. [ __ENABLE_FAST_REFRESH__ ] &&
62+ devtoolsMessage ?. [ __EAGER_SHARE__ ]
63+ ) {
64+ // eagerShare is [react, 19.0.0]
65+ const [ _name , version ] = devtoolsMessage [ __EAGER_SHARE__ ] as [ string , string ] ;
66+ fetchAndExecuteUmdSync ( getUnpkgUrl ( 'react' , version ) as string ) ;
67+ fetchAndExecuteUmdSync ( getUnpkgUrl ( 'react-dom' , version ) as string ) ;
68+ }
1069
1170const fastRefreshPlugin = ( ) : ModuleFederationRuntimePlugin => {
1271 return {
1372 name : 'mf-fast-refresh-plugin' ,
1473 beforeInit ( { userOptions, ...args } ) {
1574 const shareInfo = userOptions . shared ;
1675 const twinsShareInfo = args . shareInfo ;
17- let enableFastRefresh : boolean ;
18- let devtoolsMessage ;
76+ let enableFastRefresh = false ;
77+ let devtoolsMessage : Record < string , unknown > = { } ;
1978
2079 const devtoolsMessageStr = localStorage . getItem ( __FEDERATION_DEVTOOLS__ ) ;
2180 if ( devtoolsMessageStr ) {
2281 try {
2382 devtoolsMessage = JSON . parse ( devtoolsMessageStr ) ;
24- enableFastRefresh = devtoolsMessage ?. enableFastRefresh ;
83+ enableFastRefresh = devtoolsMessage ?. [
84+ __ENABLE_FAST_REFRESH__
85+ ] as boolean ;
2586 } catch ( e ) {
2687 console . debug ( 'Fast Refresh Plugin Error: ' , e ) ;
2788 }
2889 }
2990
91+ if ( ! enableFastRefresh ) {
92+ return {
93+ userOptions,
94+ ...args ,
95+ } ;
96+ }
97+
3098 if ( shareInfo && isObject ( shareInfo ) ) {
3199 let orderResolve : ( value ?: unknown ) => void ;
32100 const orderPromise = new Promise ( ( resolve ) => {
@@ -47,11 +115,37 @@ const fastRefreshPlugin = (): ModuleFederationRuntimePlugin => {
47115 }
48116
49117 sharedArr . forEach ( ( shared , idx ) => {
118+ if ( ! SUPPORT_PKGS . includes ( share ) ) {
119+ return ;
120+ }
121+ if ( shared . shareConfig ?. eager ) {
122+ if ( ! devtoolsMessage ?. [ __EAGER_SHARE__ ] ) {
123+ const eagerShare : string [ ] = [ ] ;
124+ eagerShare . push ( share , shared . version ) ;
125+ devtoolsMessage [ __EAGER_SHARE__ ] = eagerShare ;
126+ localStorage . setItem (
127+ __FEDERATION_DEVTOOLS__ ,
128+ JSON . stringify ( devtoolsMessage ) ,
129+ ) ;
130+ window . location . reload ( ) ;
131+ }
132+ if ( share === 'react-dom' ) {
133+ shared . lib = ( ) => window . ReactDOM ;
134+ }
135+ if ( share === 'react' ) {
136+ shared . lib = ( ) => window . React ;
137+ }
138+ return ;
139+ }
50140 let get : ( ) => any ;
51141 if ( share === 'react' ) {
52142 get = ( ) =>
53143 loadScript ( getUnpkgUrl ( share , shared . version ) as string , {
54- attrs : { defer : true , async : false } ,
144+ attrs : {
145+ defer : false ,
146+ async : false ,
147+ 'data-mf-injected' : 'true' ,
148+ } ,
55149 } ) . then ( ( ) => {
56150 orderResolve ( ) ;
57151 } ) ;
@@ -65,7 +159,7 @@ const fastRefreshPlugin = (): ModuleFederationRuntimePlugin => {
65159 ) ;
66160 }
67161 // @ts -expect-error
68- if ( enableFastRefresh && typeof get === 'function' ) {
162+ if ( typeof get === 'function' ) {
69163 if ( share === 'react' ) {
70164 shared . get = async ( ) => {
71165 if ( ! window . React ) {
0 commit comments