@@ -19,12 +19,12 @@ use std::{
19
19
20
20
use async_trait:: async_trait;
21
21
use rspack_core:: {
22
- Compilation , CompilationOptimizeChunks , CompilerCompilation , Dependency , DependencyId , Module ,
23
- ModuleIdentifier , Plugin ,
22
+ Compilation , CompilationOptimizeChunks , CompilerCompilation , Dependency , DependencyId ,
23
+ ModuleIdentifier , Plugin , incremental :: Mutation ,
24
24
} ;
25
25
use rspack_error:: Result ;
26
26
use rspack_hook:: { plugin, plugin_hook} ;
27
- use rustc_hash:: FxHashSet ;
27
+ use rustc_hash:: { FxHashMap , FxHashSet } ;
28
28
29
29
use super :: {
30
30
container_entry_dependency:: ContainerEntryDependency , fallback_dependency:: FallbackDependency ,
@@ -140,14 +140,13 @@ async fn optimize_chunks(&self, compilation: &mut Compilation) -> Result<Option<
140
140
// Helper: recursively collect all referenced modules
141
141
fn get_all_referenced_modules (
142
142
compilation : & Compilation ,
143
- module : & dyn Module ,
143
+ module_id : ModuleIdentifier ,
144
144
ty : & str ,
145
145
) -> FxHashSet < ModuleIdentifier > {
146
146
let mut collected = FxHashSet :: default ( ) ;
147
147
let mut visited = FxHashSet :: default ( ) ;
148
148
let mut stack = VecDeque :: new ( ) ;
149
149
150
- let module_id = module. identifier ( ) ;
151
150
collected. insert ( module_id) ;
152
151
visited. insert ( module_id) ;
153
152
stack. push_back ( module_id) ;
@@ -181,120 +180,82 @@ async fn optimize_chunks(&self, compilation: &mut Compilation) -> Result<Option<
181
180
collected
182
181
}
183
182
184
- // Helper: get runtime chunks from entrypoints with enhanced detection
185
- fn get_runtime_chunks ( compilation : & Compilation ) -> FxHashSet < rspack_core:: ChunkUkey > {
186
- let mut runtime_chunks = FxHashSet :: default ( ) ;
183
+ let mg = compilation. get_module_graph ( ) ;
187
184
188
- // Get runtime chunks from entrypoints
189
- for entrypoint_ukey in compilation. entrypoints . values ( ) {
190
- if let Some ( entrypoint) = compilation. chunk_group_by_ukey . get ( entrypoint_ukey) {
191
- let runtime_chunk = entrypoint. get_runtime_chunk ( & compilation. chunk_group_by_ukey ) ;
192
- runtime_chunks. insert ( runtime_chunk) ;
193
-
194
- // Enhanced: Also check all chunks for runtime (similar to external PR)
195
- for ( chunk_ukey, chunk) in compilation. chunk_by_ukey . iter ( ) {
196
- if chunk. has_runtime ( & compilation. chunk_group_by_ukey ) {
197
- runtime_chunks. insert ( * chunk_ukey) ;
198
- }
199
- }
200
- }
201
- }
202
-
203
- runtime_chunks
204
- }
205
-
206
- // Helper: clean up chunks by disconnecting unused modules
207
- fn clean_up_chunks ( compilation : & mut Compilation , modules : & mut FxHashSet < ModuleIdentifier > ) {
208
- for module_id in modules. iter ( ) {
209
- let chunks_vec: Vec < _ > = compilation
185
+ // Collect all federation (container, runtime, and remote) referenced modules
186
+ let all_modules_to_hoist = self
187
+ . federation_deps
188
+ . lock ( )
189
+ . expect ( "Failed to lock federation deps" )
190
+ . iter ( )
191
+ . filter_map ( |dep| mg. module_identifier_by_dependency_id ( dep) )
192
+ . flat_map ( |module| get_all_referenced_modules ( compilation, * module, "initial" ) )
193
+ . collect :: < FxHashSet < _ > > ( ) ;
194
+
195
+ // Hoist referenced modules to their runtime chunk
196
+ let entries = compilation
197
+ . get_chunk_graph_entries ( )
198
+ . filter_map ( |entry| {
199
+ compilation
200
+ . chunk_by_ukey
201
+ . get ( & entry)
202
+ . map ( |chunk| ( chunk. runtime ( ) , entry) )
203
+ } )
204
+ . collect :: < FxHashMap < _ , _ > > ( ) ;
205
+ for module in & all_modules_to_hoist {
206
+ let runtime_chunks = compilation
207
+ . chunk_graph
208
+ . get_module_runtimes_iter ( * module, & compilation. chunk_by_ukey )
209
+ . filter_map ( |runtime_spec| entries. get ( & runtime_spec) . copied ( ) )
210
+ . collect :: < Vec < _ > > ( ) ;
211
+ for runtime_chunk in runtime_chunks {
212
+ if !compilation
210
213
. chunk_graph
211
- . get_module_chunks ( * module_id)
212
- . iter ( )
213
- . copied ( )
214
- . collect ( ) ;
215
-
216
- for chunk_ukey in chunks_vec {
217
- let chunk = compilation. chunk_by_ukey . get ( & chunk_ukey) ;
218
- let has_runtime = chunk. is_some_and ( |c| c. has_runtime ( & compilation. chunk_group_by_ukey ) ) ;
219
-
220
- if !has_runtime {
221
- compilation
222
- . chunk_graph
223
- . disconnect_chunk_and_module ( & chunk_ukey, * module_id) ;
224
-
225
- if compilation
226
- . chunk_graph
227
- . get_number_of_chunk_modules ( & chunk_ukey)
228
- == 0
229
- && compilation
230
- . chunk_graph
231
- . get_number_of_entry_modules ( & chunk_ukey)
232
- == 0
233
- && let Some ( mut removed_chunk) = compilation. chunk_by_ukey . remove ( & chunk_ukey)
234
- {
235
- compilation
236
- . chunk_graph
237
- . disconnect_chunk ( & mut removed_chunk, & mut compilation. chunk_group_by_ukey ) ;
238
- compilation. chunk_graph . remove_chunk ( & chunk_ukey) ;
239
-
240
- // Remove from named chunks if it has a name
241
- if let Some ( name) = removed_chunk. name ( ) {
242
- compilation. named_chunks . remove ( name) ;
243
- }
244
- }
245
- }
214
+ . is_module_in_chunk ( module, runtime_chunk)
215
+ {
216
+ compilation
217
+ . chunk_graph
218
+ . connect_chunk_and_module ( runtime_chunk, * module) ;
246
219
}
247
220
}
248
- modules. clear ( ) ;
249
221
}
250
222
251
- let _runtime_chunks = get_runtime_chunks ( compilation) ;
252
- let mut all_modules_to_hoist = FxHashSet :: default ( ) ;
253
-
254
- // Process all federation dependencies (container, runtime, and remote)
255
- for dep_id in self
256
- . federation_deps
257
- . lock ( )
258
- . expect ( "Failed to lock federation deps" )
259
- . iter ( )
260
- {
261
- let module_graph = compilation. get_module_graph ( ) ;
262
- if let Some ( module_id) = module_graph. module_identifier_by_dependency_id ( dep_id)
263
- && let Some ( module) = module_graph. module_by_identifier ( module_id)
264
- {
265
- let referenced_modules = get_all_referenced_modules ( compilation, module. as_ref ( ) , "initial" ) ;
266
- all_modules_to_hoist. extend ( & referenced_modules) ;
267
-
268
- // Get module runtimes and hoist to runtime chunks
269
- let runtime_specs: Vec < _ > = compilation
223
+ // Disconnect hoisted modules from non-runtime chunks, this is safe since we already hoist them to runtime chunk
224
+ let runtime_chunks = entries. values ( ) . copied ( ) . collect :: < FxHashSet < _ > > ( ) ;
225
+ for module in all_modules_to_hoist {
226
+ let non_runtime_chunks = compilation
227
+ . chunk_graph
228
+ . get_module_chunks ( module)
229
+ . iter ( )
230
+ . filter ( |chunk| !runtime_chunks. contains ( chunk) )
231
+ . copied ( )
232
+ . collect :: < Vec < _ > > ( ) ;
233
+ for chunk in non_runtime_chunks {
234
+ compilation
270
235
. chunk_graph
271
- . get_module_runtimes_iter ( * module_id, & compilation. chunk_by_ukey )
272
- . cloned ( )
273
- . collect ( ) ;
274
-
275
- for runtime_spec in runtime_specs {
276
- // Find runtime chunks by name
277
- for runtime_name in runtime_spec. iter ( ) {
278
- if let Some ( runtime_chunk) = compilation. named_chunks . get ( runtime_name. as_str ( ) ) {
279
- for & ref_module_id in & referenced_modules {
280
- if !compilation
281
- . chunk_graph
282
- . is_module_in_chunk ( & ref_module_id, * runtime_chunk)
283
- {
284
- compilation
285
- . chunk_graph
286
- . connect_chunk_and_module ( * runtime_chunk, ref_module_id) ;
287
- }
288
- }
289
- }
236
+ . disconnect_chunk_and_module ( & chunk, module) ;
237
+
238
+ if compilation. chunk_graph . get_number_of_chunk_modules ( & chunk) == 0
239
+ && compilation. chunk_graph . get_number_of_entry_modules ( & chunk) == 0
240
+ && let Some ( mut removed_chunk) = compilation. chunk_by_ukey . remove ( & chunk)
241
+ {
242
+ compilation
243
+ . chunk_graph
244
+ . disconnect_chunk ( & mut removed_chunk, & mut compilation. chunk_group_by_ukey ) ;
245
+ compilation. chunk_graph . remove_chunk ( & chunk) ;
246
+
247
+ // Remove from named chunks if it has a name
248
+ if let Some ( name) = removed_chunk. name ( ) {
249
+ compilation. named_chunks . remove ( name) ;
250
+ }
251
+ // Record mutation
252
+ if let Some ( mutations) = compilation. incremental . mutations_write ( ) {
253
+ mutations. add ( Mutation :: ChunkRemove { chunk } ) ;
290
254
}
291
255
}
292
256
}
293
257
}
294
258
295
- // Cleanup: disconnect hoisted modules from non-runtime chunks
296
- clean_up_chunks ( compilation, & mut all_modules_to_hoist) ;
297
-
298
259
Ok ( None )
299
260
}
300
261
0 commit comments