@@ -84,6 +84,31 @@ fn get_remote_entry_name(compilation: &Compilation, container_name: &str) -> Opt
8484 }
8585 None
8686}
87+ fn derive_module_name ( alias : & str , internal_request : Option < & str > ) -> String {
88+ if let Some ( req) = internal_request {
89+ let trimmed = req. trim_start_matches ( "./" ) ;
90+ if trimmed. is_empty ( ) {
91+ req. to_string ( )
92+ } else {
93+ trimmed. to_string ( )
94+ }
95+ } else {
96+ let seg = alias. rsplit ( '/' ) . next ( ) . unwrap_or ( "" ) ;
97+ if seg. is_empty ( ) || seg == alias {
98+ "." . to_string ( )
99+ } else {
100+ seg. to_string ( )
101+ }
102+ }
103+ }
104+ fn normalize_used_in_entry ( name : & str ) -> String {
105+ let base = name. split ( " + " ) . next ( ) . unwrap_or ( name) ;
106+ std:: path:: Path :: new ( base)
107+ . file_name ( )
108+ . and_then ( |f| f. to_str ( ) )
109+ . unwrap_or ( base)
110+ . to_string ( )
111+ }
87112#[ plugin_hook( CompilationProcessAssets for ModuleFederationManifestPlugin ) ]
88113async fn process_assets ( & self , compilation : & mut Compilation ) -> Result < ( ) > {
89114 // Prepare entrypoint names
@@ -141,7 +166,7 @@ async fn process_assets(&self, compilation: &mut Compilation) -> Result<()> {
141166 } ,
142167 r#type : None ,
143168 } ;
144- let ( exposes, shared, remote_list) = if self . options . disable_assets_analyze {
169+ let ( exposes, shared, mut remote_list) = if self . options . disable_assets_analyze {
145170 let exposes = self
146171 . options
147172 . exposes
@@ -181,11 +206,12 @@ async fn process_assets(&self, compilation: &mut Compilation) -> Result<()> {
181206 } else {
182207 target. name . clone ( )
183208 } ;
209+ let module_name = derive_module_name ( alias, None ) ;
184210 StatsRemote {
185211 alias : alias. clone ( ) ,
186212 consumingFederationContainerName : container_name. clone ( ) ,
187213 federationContainerName : remote_container_name. clone ( ) ,
188- moduleName : remote_container_name ,
214+ moduleName : module_name ,
189215 entry : target. entry . clone ( ) ,
190216 usedIn : vec ! [ "UNKNOWN" . to_string( ) ] ,
191217 }
@@ -464,14 +490,7 @@ async fn process_assets(&self, compilation: &mut Compilation) -> Result<()> {
464490 continue ;
465491 } ;
466492 let alias = remote_module. remote_key . clone ( ) ;
467- let module_name = {
468- let trimmed = remote_module. internal_request . trim_start_matches ( "./" ) ;
469- if trimmed. is_empty ( ) {
470- remote_module. internal_request . clone ( )
471- } else {
472- trimmed. to_string ( )
473- }
474- } ;
493+ let module_name = derive_module_name ( & alias, Some ( remote_module. internal_request . as_str ( ) ) ) ;
475494 let ( entry, federation_container_name) =
476495 if let Some ( target) = provided_remote_alias_map. get ( & alias) {
477496 let remote_container_name = if target. name . is_empty ( ) {
@@ -487,7 +506,10 @@ async fn process_assets(&self, compilation: &mut Compilation) -> Result<()> {
487506 ( None , alias. clone ( ) )
488507 } ;
489508 let used_in =
490- collect_usage_files_for_module ( compilation, & module_graph, & module_id, & entry_point_names) ;
509+ collect_usage_files_for_module ( compilation, & module_graph, & module_id, & entry_point_names)
510+ . into_iter ( )
511+ . map ( |s| normalize_used_in_entry ( & s) )
512+ . collect ( ) ;
491513 remote_list. push ( StatsRemote {
492514 alias : alias. clone ( ) ,
493515 consumingFederationContainerName : container_name. clone ( ) ,
@@ -502,13 +524,36 @@ async fn process_assets(&self, compilation: &mut Compilation) -> Result<()> {
502524 let shared = shared_map
503525 . into_values ( )
504526 . map ( |mut v| {
527+ v. usedIn = v
528+ . usedIn
529+ . into_iter ( )
530+ . map ( |s| normalize_used_in_entry ( & s) )
531+ . collect ( ) ;
505532 v. usedIn . sort ( ) ;
506533 v. usedIn . dedup ( ) ;
507534 v
508535 } )
509536 . collect :: < Vec < _ > > ( ) ;
510537 ( exposes, shared, remote_list)
511538 } ;
539+ for ( alias, target) in self . options . remote_alias_map . iter ( ) {
540+ let exists = remote_list. iter ( ) . any ( |r| r. alias == * alias) ;
541+ if !exists {
542+ let remote_container_name = if target. name . is_empty ( ) {
543+ alias. clone ( )
544+ } else {
545+ target. name . clone ( )
546+ } ;
547+ remote_list. push ( StatsRemote {
548+ alias : alias. clone ( ) ,
549+ consumingFederationContainerName : container_name. clone ( ) ,
550+ federationContainerName : remote_container_name. clone ( ) ,
551+ moduleName : "UNKNOWN" . to_string ( ) ,
552+ entry : target. entry . clone ( ) . filter ( |e| !e. is_empty ( ) ) ,
553+ usedIn : vec ! [ "UNKNOWN" . to_string( ) ] ,
554+ } ) ;
555+ }
556+ }
512557 let stats_root = StatsRoot {
513558 id : container_name. clone ( ) ,
514559 name : container_name. clone ( ) ,
@@ -527,7 +572,7 @@ async fn process_assets(&self, compilation: &mut Compilation) -> Result<()> {
527572 ) ,
528573 ) ;
529574 // Build manifest from stats
530- let manifest = ManifestRoot {
575+ let mut manifest = ManifestRoot {
531576 id : stats_root. id . clone ( ) ,
532577 name : stats_root. name . clone ( ) ,
533578 metaData : stats_root. metaData . clone ( ) ,
@@ -562,6 +607,24 @@ async fn process_assets(&self, compilation: &mut Compilation) -> Result<()> {
562607 } )
563608 . collect ( ) ,
564609 } ;
610+ // Supplement manifest.remotes with registered options if missing
611+ for ( alias, target) in self . options . remote_alias_map . iter ( ) {
612+ let exists = manifest. remotes . iter ( ) . any ( |r| r. alias == * alias) ;
613+ if !exists {
614+ let remote_container_name = if target. name . is_empty ( ) {
615+ alias. clone ( )
616+ } else {
617+ target. name . clone ( )
618+ } ;
619+ let module_name = derive_module_name ( alias, None ) ;
620+ manifest. remotes . push ( ManifestRemote {
621+ federationContainerName : remote_container_name. clone ( ) ,
622+ moduleName : module_name,
623+ alias : alias. clone ( ) ,
624+ entry : target. entry . clone ( ) . filter ( |e| !e. is_empty ( ) ) ,
625+ } ) ;
626+ }
627+ }
565628 let manifest_json: String = serde_json:: to_string_pretty ( & manifest) . expect ( "serialize manifest" ) ;
566629 compilation. emit_asset (
567630 self . options . manifest_file_name . clone ( ) ,
0 commit comments