@@ -3,20 +3,23 @@ use std::hash::Hash;
3
3
use rspack_core:: rspack_sources:: { ConcatSource , RawSource , SourceExt } ;
4
4
use rspack_core:: {
5
5
merge_runtime, to_identifier, ApplyContext , ChunkUkey , CodeGenerationExportsFinalNames ,
6
- Compilation , CompilationOptimizeChunkModules , CompilationParams , CompilerCompilation ,
7
- CompilerOptions , ConcatenatedModule , ConcatenatedModuleExportsDefinitions , LibraryOptions ,
8
- ModuleIdentifier , Plugin , PluginContext ,
6
+ Compilation , CompilationFinishModules , CompilationOptimizeChunkModules , CompilationParams ,
7
+ CompilerCompilation , CompilerOptions , ConcatenatedModule , ConcatenatedModuleExportsDefinitions ,
8
+ DependenciesBlock , Dependency , ExternalModule , LibraryOptions , ModuleIdentifier , Plugin ,
9
+ PluginContext ,
9
10
} ;
10
11
use rspack_error:: { error_bail, Result } ;
11
12
use rspack_hash:: RspackHash ;
12
13
use rspack_hook:: { plugin, plugin_hook} ;
14
+ use rspack_plugin_javascript:: dependency:: ImportDependency ;
13
15
use rspack_plugin_javascript:: ModuleConcatenationPlugin ;
14
16
use rspack_plugin_javascript:: {
15
17
ConcatConfiguration , JavascriptModulesChunkHash , JavascriptModulesRenderStartup , JsPlugin ,
16
18
RenderSource ,
17
19
} ;
18
20
use rustc_hash:: FxHashSet as HashSet ;
19
21
22
+ use super :: modern_module:: ModernModuleImportDependency ;
20
23
use crate :: utils:: { get_options_for_chunk, COMMON_LIBRARY_NAME_MESSAGE } ;
21
24
22
25
const PLUGIN_NAME : & str = "rspack.ModernModuleLibraryPlugin" ;
@@ -189,6 +192,80 @@ fn render_startup(
189
192
Ok ( ( ) )
190
193
}
191
194
195
+ #[ plugin_hook( CompilationFinishModules for ModernModuleLibraryPlugin ) ]
196
+ async fn finish_modules ( & self , compilation : & mut Compilation ) -> Result < ( ) > {
197
+ let mut mg = compilation. get_module_graph_mut ( ) ;
198
+ let modules = mg. modules ( ) ;
199
+ let module_ids = modules. keys ( ) . cloned ( ) . collect :: < Vec < _ > > ( ) ;
200
+
201
+ for module_id in module_ids {
202
+ let mut deps_to_replace = Vec :: new ( ) ;
203
+ let module = mg
204
+ . module_by_identifier ( & module_id)
205
+ . expect ( "should have mgm" ) ;
206
+ let connections = mg. get_outgoing_connections ( & module_id) ;
207
+ let block_ids = module. get_blocks ( ) ;
208
+
209
+ for block_id in block_ids {
210
+ let block = mg. block_by_id ( block_id) . expect ( "should have block" ) ;
211
+ for block_dep_id in block. get_dependencies ( ) {
212
+ let block_dep = mg. dependency_by_id ( block_dep_id) ;
213
+ if let Some ( block_dep) = block_dep {
214
+ if let Some ( import_dependency) = block_dep. as_any ( ) . downcast_ref :: < ImportDependency > ( ) {
215
+ // TODO: do not use find
216
+ // Try find the connection that marks import dependency as an external module.
217
+ let connection_to_external = connections. iter ( ) . find ( |c| {
218
+ let module_id = c. module_identifier ( ) ;
219
+ let module = mg. module_by_identifier ( module_id) . expect ( "should have mgm" ) ;
220
+ if let Some ( external_module) = module. as_any ( ) . downcast_ref :: < ExternalModule > ( ) {
221
+ import_dependency. request == external_module. user_request
222
+ } else {
223
+ false
224
+ }
225
+ } ) ;
226
+
227
+ if let Some ( connection_to_external) = connection_to_external {
228
+ let external_module_id = connection_to_external. module_identifier ( ) ;
229
+ let external_module = mg
230
+ . module_by_identifier ( external_module_id)
231
+ . expect ( "should have mgm" ) ;
232
+
233
+ if let Some ( external_module) = external_module. as_external_module ( ) {
234
+ let new_dep = ModernModuleImportDependency :: new (
235
+ import_dependency. request . as_str ( ) . into ( ) ,
236
+ external_module. request . clone ( ) ,
237
+ external_module. external_type . clone ( ) ,
238
+ import_dependency. range . clone ( ) ,
239
+ None ,
240
+ ) ;
241
+
242
+ deps_to_replace. push ( (
243
+ * block_id,
244
+ block_dep. clone ( ) ,
245
+ new_dep. clone ( ) ,
246
+ connection_to_external. id ,
247
+ ) ) ;
248
+ }
249
+ }
250
+ }
251
+ }
252
+ }
253
+ }
254
+
255
+ for ( block_id, dep, new_dep, connection_id) in deps_to_replace. iter ( ) {
256
+ let block = mg. block_by_id_mut ( block_id) . expect ( "should have block" ) ;
257
+ let dep_id = dep. id ( ) ;
258
+ block. remove_dependency_id ( * dep_id) ;
259
+ let boxed_dep = Box :: new ( new_dep. clone ( ) ) as Box < dyn rspack_core:: Dependency > ;
260
+ block. add_dependency_id ( * new_dep. id ( ) ) ;
261
+ mg. add_dependency ( boxed_dep) ;
262
+ mg. revoke_connection ( connection_id, true ) ;
263
+ }
264
+ }
265
+
266
+ Ok ( ( ) )
267
+ }
268
+
192
269
#[ plugin_hook( JavascriptModulesChunkHash for ModernModuleLibraryPlugin ) ]
193
270
async fn js_chunk_hash (
194
271
& self ,
@@ -256,6 +333,11 @@ impl Plugin for ModernModuleLibraryPlugin {
256
333
. compilation_hooks
257
334
. optimize_chunk_modules
258
335
. tap ( optimize_chunk_modules:: new ( self ) ) ;
336
+ ctx
337
+ . context
338
+ . compilation_hooks
339
+ . finish_modules
340
+ . tap ( finish_modules:: new ( self ) ) ;
259
341
260
342
Ok ( ( ) )
261
343
}
0 commit comments