1
1
import {
2
- composeKeyWithSeparator ,
3
2
loadScript ,
4
3
loadScriptNode ,
5
- CreateScriptHookReturn ,
4
+ composeKeyWithSeparator ,
5
+ isBrowserEnv ,
6
6
} from '@module-federation/sdk' ;
7
- import { assert } from '../utils/logger' ;
8
- import { getRemoteEntryExports , globalLoading } from '../global' ;
9
- import { Remote , RemoteEntryExports , RemoteInfo } from '../type' ;
10
7
import { DEFAULT_REMOTE_TYPE , DEFAULT_SCOPE } from '../constant' ;
8
+ import { FederationHost } from '../core' ;
9
+ import { globalLoading , getRemoteEntryExports } from '../global' ;
10
+ import { Remote , RemoteEntryExports , RemoteInfo } from '../type' ;
11
+ import { assert } from '../utils' ;
11
12
12
- export async function loadEsmEntry ( {
13
+ async function loadEsmEntry ( {
13
14
entry,
14
15
remoteEntryExports,
15
16
} : {
@@ -33,7 +34,7 @@ export async function loadEsmEntry({
33
34
} ) ;
34
35
}
35
36
36
- export async function loadSystemJsEntry ( {
37
+ async function loadSystemJsEntry ( {
37
38
entry,
38
39
remoteEntryExports,
39
40
} : {
@@ -57,7 +58,7 @@ export async function loadSystemJsEntry({
57
58
} ) ;
58
59
}
59
60
60
- export async function loadEntryScript ( {
61
+ async function loadEntryScript ( {
61
62
name,
62
63
globalName,
63
64
entry,
@@ -66,10 +67,7 @@ export async function loadEntryScript({
66
67
name : string ;
67
68
globalName : string ;
68
69
entry : string ;
69
- createScriptHook ?: (
70
- url : string ,
71
- attrs ?: Record < string , any > | undefined ,
72
- ) => CreateScriptHookReturn ;
70
+ createScriptHook : FederationHost [ 'loaderHook' ] [ 'lifecycle' ] [ 'createScript' ] ;
73
71
} ) : Promise < RemoteEntryExports > {
74
72
const { entryExports : remoteEntryExports } = getRemoteEntryExports (
75
73
name ,
@@ -80,35 +78,99 @@ export async function loadEntryScript({
80
78
return remoteEntryExports ;
81
79
}
82
80
83
- if ( typeof document === 'undefined' ) {
84
- return loadScriptNode ( entry , {
85
- attrs : { name, globalName } ,
86
- createScriptHook,
81
+ return loadScript ( entry , {
82
+ attrs : { } ,
83
+ createScriptHook : ( url , attrs ) => {
84
+ const res = createScriptHook . emit ( { url, attrs } ) ;
85
+
86
+ if ( ! res ) return ;
87
+
88
+ if ( res instanceof HTMLScriptElement ) {
89
+ return res ;
90
+ }
91
+
92
+ if ( 'script' in res || 'timeout' in res ) {
93
+ return res ;
94
+ }
95
+
96
+ return ;
97
+ } ,
98
+ } )
99
+ . then ( ( ) => {
100
+ const { remoteEntryKey, entryExports } = getRemoteEntryExports (
101
+ name ,
102
+ globalName ,
103
+ ) ;
104
+
105
+ assert (
106
+ entryExports ,
107
+ `
108
+ Unable to use the ${ name } 's '${ entry } ' URL with ${ remoteEntryKey } 's globalName to get remoteEntry exports.
109
+ Possible reasons could be:\n
110
+ 1. '${ entry } ' is not the correct URL, or the remoteEntry resource or name is incorrect.\n
111
+ 2. ${ remoteEntryKey } cannot be used to get remoteEntry exports in the window object.
112
+ ` ,
113
+ ) ;
114
+
115
+ return entryExports ;
87
116
} )
88
- . then ( ( ) => {
89
- const { remoteEntryKey, entryExports } = getRemoteEntryExports (
90
- name ,
91
- globalName ,
92
- ) ;
93
-
94
- assert (
95
- entryExports ,
96
- `
97
- Unable to use the ${ name } 's '${ entry } ' URL with ${ remoteEntryKey } 's globalName to get remoteEntry exports.
98
- Possible reasons could be:\n
99
- 1. '${ entry } ' is not the correct URL, or the remoteEntry resource or name is incorrect.\n
100
- 2. ${ remoteEntryKey } cannot be used to get remoteEntry exports in the window object.
101
- ` ,
102
- ) ;
103
-
104
- return entryExports ;
105
- } )
106
- . catch ( ( e ) => {
107
- throw e ;
108
- } ) ;
117
+ . catch ( ( e ) => {
118
+ throw e ;
119
+ } ) ;
120
+ }
121
+
122
+ async function loadEntryDom ( {
123
+ remoteInfo,
124
+ remoteEntryExports,
125
+ createScriptHook,
126
+ } : {
127
+ remoteInfo : RemoteInfo ;
128
+ remoteEntryExports ?: RemoteEntryExports ;
129
+ createScriptHook : FederationHost [ 'loaderHook' ] [ 'lifecycle' ] [ 'createScript' ] ;
130
+ } ) {
131
+ const { entry, entryGlobalName : globalName , name, type } = remoteInfo ;
132
+ switch ( type ) {
133
+ case 'esm' :
134
+ case 'module' :
135
+ return loadEsmEntry ( { entry, remoteEntryExports } ) ;
136
+ case 'system' :
137
+ return loadSystemJsEntry ( { entry, remoteEntryExports } ) ;
138
+ default :
139
+ return loadEntryScript ( { entry, globalName, name, createScriptHook } ) ;
140
+ }
141
+ }
142
+
143
+ async function loadEntryNode ( {
144
+ remoteInfo,
145
+ createScriptHook,
146
+ } : {
147
+ remoteInfo : RemoteInfo ;
148
+ createScriptHook : FederationHost [ 'loaderHook' ] [ 'lifecycle' ] [ 'createScript' ] ;
149
+ } ) {
150
+ const { entry, entryGlobalName : globalName , name } = remoteInfo ;
151
+ const { entryExports : remoteEntryExports } = getRemoteEntryExports (
152
+ name ,
153
+ globalName ,
154
+ ) ;
155
+
156
+ if ( remoteEntryExports ) {
157
+ return remoteEntryExports ;
109
158
}
110
159
111
- return loadScript ( entry , { attrs : { } , createScriptHook } )
160
+ return loadScriptNode ( entry , {
161
+ attrs : { name, globalName } ,
162
+ createScriptHook : ( url , attrs ) => {
163
+ const res = createScriptHook . emit ( { url, attrs } ) ;
164
+
165
+ if ( ! res ) return ;
166
+
167
+ if ( 'url' in res ) {
168
+ return res ;
169
+ }
170
+
171
+ return ;
172
+ } ,
173
+ } )
112
174
. then ( ( ) => {
113
175
const { remoteEntryKey, entryExports } = getRemoteEntryExports (
114
176
name ,
@@ -138,43 +200,46 @@ export function getRemoteEntryUniqueKey(remoteInfo: RemoteInfo): string {
138
200
}
139
201
140
202
export async function getRemoteEntry ( {
203
+ origin,
141
204
remoteEntryExports,
142
205
remoteInfo,
143
- createScriptHook,
144
206
} : {
207
+ origin : FederationHost ;
145
208
remoteInfo : RemoteInfo ;
146
209
remoteEntryExports ?: RemoteEntryExports | undefined ;
147
- createScriptHook ?: (
148
- url : string ,
149
- attrs ?: Record < string , any > | undefined ,
150
- ) => CreateScriptHookReturn ;
151
- } ) : Promise < RemoteEntryExports | void > {
152
- const { entry, name, type, entryGlobalName } = remoteInfo ;
210
+ } ) : Promise < RemoteEntryExports | false | void > {
153
211
const uniqueKey = getRemoteEntryUniqueKey ( remoteInfo ) ;
154
212
if ( remoteEntryExports ) {
155
213
return remoteEntryExports ;
156
214
}
157
215
158
216
if ( ! globalLoading [ uniqueKey ] ) {
159
- if ( [ 'esm' , 'module' ] . includes ( type ) ) {
160
- globalLoading [ uniqueKey ] = loadEsmEntry ( {
161
- entry,
162
- remoteEntryExports,
163
- } ) ;
164
- } else if ( type === 'system' ) {
165
- globalLoading [ uniqueKey ] = loadSystemJsEntry ( {
166
- entry,
167
- remoteEntryExports,
168
- } ) ;
217
+ const loadEntryHook = origin . remoteHandler . hooks . lifecycle . loadEntry ;
218
+ if ( loadEntryHook . listeners . size ) {
219
+ globalLoading [ uniqueKey ] = loadEntryHook
220
+ . emit ( {
221
+ createScriptHook : origin . loaderHook . lifecycle . createScript ,
222
+ remoteInfo,
223
+ remoteEntryExports,
224
+ } )
225
+ . then ( ( res ) => res || undefined ) ;
169
226
} else {
170
- globalLoading [ uniqueKey ] = loadEntryScript ( {
171
- name,
172
- globalName : entryGlobalName ,
173
- entry,
174
- createScriptHook,
175
- } ) ;
227
+ const createScriptHook = origin . loaderHook . lifecycle . createScript ;
228
+ if ( ! isBrowserEnv ( ) ) {
229
+ globalLoading [ uniqueKey ] = loadEntryNode ( {
230
+ remoteInfo,
231
+ createScriptHook,
232
+ } ) ;
233
+ } else {
234
+ globalLoading [ uniqueKey ] = loadEntryDom ( {
235
+ remoteInfo,
236
+ remoteEntryExports,
237
+ createScriptHook,
238
+ } ) ;
239
+ }
176
240
}
177
241
}
242
+
178
243
return globalLoading [ uniqueKey ] ;
179
244
}
180
245
0 commit comments