11import type {
2+ Chunk ,
23 Compiler ,
34 Compilation ,
4- Chunk ,
55 WebpackPluginInstance ,
66 Module ,
77 Dependency ,
@@ -10,6 +10,8 @@ import { normalizeWebpackPath } from '@module-federation/sdk/normalize-webpack-p
1010import FederationModulesPlugin from './runtime/FederationModulesPlugin' ;
1111import ContainerEntryDependency from './ContainerEntryDependency' ;
1212import FederationRuntimeDependency from './runtime/FederationRuntimeDependency' ;
13+ import RemoteToExternalDependency from './RemoteToExternalDependency' ;
14+ import FallbackDependency from './FallbackDependency' ;
1315
1416const { AsyncDependenciesBlock, ExternalModule } = require (
1517 normalizeWebpackPath ( 'webpack' ) ,
@@ -18,16 +20,19 @@ const { AsyncDependenciesBlock, ExternalModule } = require(
1820const PLUGIN_NAME = 'HoistContainerReferences' ;
1921
2022/**
21- * This class is used to hoist container references in the code .
23+ * This plugin hoists container-related modules into runtime chunks when using runtimeChunk: single configuration .
2224 */
23- export class HoistContainerReferences implements WebpackPluginInstance {
25+ class HoistContainerReferences implements WebpackPluginInstance {
2426 apply ( compiler : Compiler ) : void {
2527 compiler . hooks . thisCompilation . tap (
2628 PLUGIN_NAME ,
2729 ( compilation : Compilation ) => {
2830 const logger = compilation . getLogger ( PLUGIN_NAME ) ;
2931 const hooks = FederationModulesPlugin . getCompilationHooks ( compilation ) ;
3032 const containerEntryDependencies = new Set < Dependency > ( ) ;
33+ const federationRuntimeDependencies = new Set < Dependency > ( ) ;
34+ const remoteDependencies = new Set < Dependency > ( ) ;
35+
3136 hooks . addContainerEntryDependency . tap (
3237 'HoistContainerReferences' ,
3338 ( dep : ContainerEntryDependency ) => {
@@ -37,7 +42,13 @@ export class HoistContainerReferences implements WebpackPluginInstance {
3742 hooks . addFederationRuntimeDependency . tap (
3843 'HoistContainerReferences' ,
3944 ( dep : FederationRuntimeDependency ) => {
40- containerEntryDependencies . add ( dep ) ;
45+ federationRuntimeDependencies . add ( dep ) ;
46+ } ,
47+ ) ;
48+ hooks . addRemoteDependency . tap (
49+ 'HoistContainerReferences' ,
50+ ( dep : RemoteToExternalDependency | FallbackDependency ) => {
51+ remoteDependencies . add ( dep ) ;
4152 } ,
4253 ) ;
4354
@@ -53,9 +64,10 @@ export class HoistContainerReferences implements WebpackPluginInstance {
5364 this . hoistModulesInChunks (
5465 compilation ,
5566 runtimeChunks ,
56- chunks ,
5767 logger ,
5868 containerEntryDependencies ,
69+ federationRuntimeDependencies ,
70+ remoteDependencies ,
5971 ) ;
6072 } ,
6173 ) ;
@@ -67,37 +79,60 @@ export class HoistContainerReferences implements WebpackPluginInstance {
6779 private hoistModulesInChunks (
6880 compilation : Compilation ,
6981 runtimeChunks : Set < Chunk > ,
70- chunks : Iterable < Chunk > ,
7182 logger : ReturnType < Compilation [ 'getLogger' ] > ,
7283 containerEntryDependencies : Set < Dependency > ,
84+ federationRuntimeDependencies : Set < Dependency > ,
85+ remoteDependencies : Set < Dependency > ,
7386 ) : void {
7487 const { chunkGraph, moduleGraph } = compilation ;
75- // when runtimeChunk: single is set - ContainerPlugin will create a "partial" chunk we can use to
76- // move modules into the runtime chunk
88+ const allModulesToHoist = new Set < Module > ( ) ;
89+
90+ // Process container entry dependencies (needed for nextjs-mf exposed modules)
7791 for ( const dep of containerEntryDependencies ) {
7892 const containerEntryModule = moduleGraph . getModule ( dep ) ;
7993 if ( ! containerEntryModule ) continue ;
80- const allReferencedModules = getAllReferencedModules (
94+ const referencedModules = getAllReferencedModules (
8195 compilation ,
8296 containerEntryModule ,
8397 'initial' ,
8498 ) ;
99+ referencedModules . forEach ( ( m : Module ) => allModulesToHoist . add ( m ) ) ;
100+ const moduleRuntimes = chunkGraph . getModuleRuntimes ( containerEntryModule ) ;
101+ const runtimes = new Set < string > ( ) ;
102+ for ( const runtimeSpec of moduleRuntimes ) {
103+ compilation . compiler . webpack . util . runtime . forEachRuntime (
104+ runtimeSpec ,
105+ ( runtimeKey ) => {
106+ if ( runtimeKey ) {
107+ runtimes . add ( runtimeKey ) ;
108+ }
109+ } ,
110+ ) ;
111+ }
112+ for ( const runtime of runtimes ) {
113+ const runtimeChunk = compilation . namedChunks . get ( runtime ) ;
114+ if ( ! runtimeChunk ) continue ;
115+ for ( const module of referencedModules ) {
116+ if ( ! chunkGraph . isModuleInChunk ( module , runtimeChunk ) ) {
117+ chunkGraph . connectChunkAndModule ( runtimeChunk , module ) ;
118+ }
119+ }
120+ }
121+ }
85122
86- const allRemoteReferences = getAllReferencedModules (
123+ // Federation Runtime Dependencies: use 'initial' (not 'all')
124+ for ( const dep of federationRuntimeDependencies ) {
125+ const runtimeModule = moduleGraph . getModule ( dep ) ;
126+ if ( ! runtimeModule ) continue ;
127+ const referencedModules = getAllReferencedModules (
87128 compilation ,
88- containerEntryModule ,
89- 'external ' ,
129+ runtimeModule ,
130+ 'initial ' ,
90131 ) ;
91-
92- for ( const remote of allRemoteReferences ) {
93- allReferencedModules . add ( remote ) ;
94- }
95-
96- const containerRuntimes =
97- chunkGraph . getModuleRuntimes ( containerEntryModule ) ;
132+ referencedModules . forEach ( ( m : Module ) => allModulesToHoist . add ( m ) ) ;
133+ const moduleRuntimes = chunkGraph . getModuleRuntimes ( runtimeModule ) ;
98134 const runtimes = new Set < string > ( ) ;
99-
100- for ( const runtimeSpec of containerRuntimes ) {
135+ for ( const runtimeSpec of moduleRuntimes ) {
101136 compilation . compiler . webpack . util . runtime . forEachRuntime (
102137 runtimeSpec ,
103138 ( runtimeKey ) => {
@@ -107,19 +142,49 @@ export class HoistContainerReferences implements WebpackPluginInstance {
107142 } ,
108143 ) ;
109144 }
110-
111145 for ( const runtime of runtimes ) {
112146 const runtimeChunk = compilation . namedChunks . get ( runtime ) ;
113147 if ( ! runtimeChunk ) continue ;
148+ for ( const module of referencedModules ) {
149+ if ( ! chunkGraph . isModuleInChunk ( module , runtimeChunk ) ) {
150+ chunkGraph . connectChunkAndModule ( runtimeChunk , module ) ;
151+ }
152+ }
153+ }
154+ }
114155
115- for ( const module of allReferencedModules ) {
156+ // Process remote dependencies
157+ for ( const remoteDep of remoteDependencies ) {
158+ const remoteModule = moduleGraph . getModule ( remoteDep ) ;
159+ if ( ! remoteModule ) continue ;
160+ const referencedRemoteModules = getAllReferencedModules (
161+ compilation ,
162+ remoteModule ,
163+ 'initial' ,
164+ ) ;
165+ referencedRemoteModules . forEach ( ( m : Module ) => allModulesToHoist . add ( m ) ) ;
166+ const remoteModuleRuntimes = chunkGraph . getModuleRuntimes ( remoteModule ) ;
167+ const remoteRuntimes = new Set < string > ( ) ;
168+ for ( const runtimeSpec of remoteModuleRuntimes ) {
169+ compilation . compiler . webpack . util . runtime . forEachRuntime (
170+ runtimeSpec ,
171+ ( runtimeKey ) => {
172+ if ( runtimeKey ) remoteRuntimes . add ( runtimeKey ) ;
173+ } ,
174+ ) ;
175+ }
176+ for ( const runtime of remoteRuntimes ) {
177+ const runtimeChunk = compilation . namedChunks . get ( runtime ) ;
178+ if ( ! runtimeChunk ) continue ;
179+ for ( const module of referencedRemoteModules ) {
116180 if ( ! chunkGraph . isModuleInChunk ( module , runtimeChunk ) ) {
117181 chunkGraph . connectChunkAndModule ( runtimeChunk , module ) ;
118182 }
119183 }
120184 }
121- this . cleanUpChunks ( compilation , allReferencedModules ) ;
122185 }
186+
187+ this . cleanUpChunks ( compilation , allModulesToHoist ) ;
123188 }
124189
125190 // Method to clean up chunks by disconnecting unused modules
@@ -129,31 +194,17 @@ export class HoistContainerReferences implements WebpackPluginInstance {
129194 for ( const chunk of chunkGraph . getModuleChunks ( module ) ) {
130195 if ( ! chunk . hasRuntime ( ) ) {
131196 chunkGraph . disconnectChunkAndModule ( chunk , module ) ;
132- if (
133- chunkGraph . getNumberOfChunkModules ( chunk ) === 0 &&
134- chunkGraph . getNumberOfEntryModules ( chunk ) === 0
135- ) {
136- chunkGraph . disconnectChunk ( chunk ) ;
137- compilation . chunks . delete ( chunk ) ;
138- if ( chunk . name ) {
139- compilation . namedChunks . delete ( chunk . name ) ;
140- }
141- }
142197 }
143198 }
144199 }
145- modules . clear ( ) ;
146200 }
147201
148- // Helper method to get runtime chunks from the compilation
202+ // Method to get runtime chunks
149203 private getRuntimeChunks ( compilation : Compilation ) : Set < Chunk > {
150204 const runtimeChunks = new Set < Chunk > ( ) ;
151- const entries = compilation . entrypoints ;
152-
153- for ( const entrypoint of entries . values ( ) ) {
154- const runtimeChunk = entrypoint . getRuntimeChunk ( ) ;
155- if ( runtimeChunk ) {
156- runtimeChunks . add ( runtimeChunk ) ;
205+ for ( const chunk of compilation . chunks ) {
206+ if ( chunk . hasRuntime ( ) ) {
207+ runtimeChunks . add ( chunk ) ;
157208 }
158209 }
159210 return runtimeChunks ;
0 commit comments