rspack_plugin_remove_empty_chunks/
lib.rs1use rspack_collections::DatabaseItem;
4use rspack_core::{Compilation, CompilationOptimizeChunks, Logger, Plugin, incremental::Mutation};
5use rspack_error::Result;
6use rspack_hook::{plugin, plugin_hook};
7
8#[plugin]
9#[derive(Debug, Default)]
10pub struct RemoveEmptyChunksPlugin;
11
12impl RemoveEmptyChunksPlugin {
13 fn remove_empty_chunks(&self, compilation: &mut Compilation) {
14 let logger = compilation.get_logger(self.name());
15 let start = logger.time("remove empty chunks");
16
17 let chunk_graph = &mut compilation.chunk_graph;
18 let empty_chunks = compilation
19 .chunk_by_ukey
20 .values()
21 .filter(|chunk| {
22 chunk_graph.get_number_of_chunk_modules(&chunk.ukey()) == 0
23 && !chunk.has_runtime(&compilation.chunk_group_by_ukey)
24 && chunk_graph.get_number_of_entry_modules(&chunk.ukey()) == 0
25 })
26 .map(|chunk| chunk.ukey())
27 .collect::<Vec<_>>();
28
29 empty_chunks.iter().for_each(|chunk_ukey| {
30 if let Some(mut chunk) = compilation.chunk_by_ukey.remove(chunk_ukey) {
31 chunk_graph.disconnect_chunk(&mut chunk, &mut compilation.chunk_group_by_ukey);
32 if let Some(mutations) = compilation.incremental.mutations_write() {
33 mutations.add(Mutation::ChunkRemove { chunk: *chunk_ukey });
34 }
35 }
36 });
37
38 logger.time_end(start);
39 }
40}
41
42#[plugin_hook(CompilationOptimizeChunks for RemoveEmptyChunksPlugin, stage = Compilation::OPTIMIZE_CHUNKS_STAGE_ADVANCED)]
43async fn optimize_chunks(&self, compilation: &mut Compilation) -> Result<Option<bool>> {
44 self.remove_empty_chunks(compilation);
45 Ok(None)
46}
47
48impl Plugin for RemoveEmptyChunksPlugin {
49 fn name(&self) -> &'static str {
50 "rspack.RemoveEmptyChunksPlugin"
51 }
52
53 fn apply(&self, ctx: &mut rspack_core::ApplyContext) -> Result<()> {
54 ctx
55 .compilation_hooks
56 .optimize_chunks
57 .tap(optimize_chunks::new(self));
58 Ok(())
59 }
60}