From 9b0a248de7416c435c6f4abf26c2139e6fa2b0af Mon Sep 17 00:00:00 2001 From: Gengkun Date: Wed, 11 Dec 2024 20:07:11 +0800 Subject: [PATCH] feat(incremental): named chunk ids (#8652) --- crates/rspack_binding_values/src/chunk.rs | 15 +- crates/rspack_core/src/chunk.rs | 57 ++-- .../src/chunk_graph/chunk_graph_chunk.rs | 79 ++++- crates/rspack_core/src/chunk_group.rs | 2 +- .../rspack_core/src/compiler/compilation.rs | 21 +- crates/rspack_core/src/compiler/hmr.rs | 20 +- .../src/compiler/module_executor/execute.rs | 4 +- crates/rspack_core/src/context_module.rs | 2 +- .../src/dependency/runtime_template.rs | 14 +- .../rspack_core/src/incremental/mutations.rs | 4 +- crates/rspack_core/src/stats/mod.rs | 46 +-- crates/rspack_core/src/stats/utils.rs | 23 +- crates/rspack_core/src/utils/mod.rs | 22 +- .../src/deterministic_chunk_ids_plugin.rs | 10 +- crates/rspack_ids/src/id_helpers.rs | 162 +---------- .../rspack_ids/src/named_chunk_ids_plugin.rs | 270 +++++++++++++++--- .../rspack_ids/src/named_module_ids_plugin.rs | 15 +- crates/rspack_plugin_banner/src/lib.rs | 4 +- .../src/plugin/impl_plugin_for_css_plugin.rs | 13 +- crates/rspack_plugin_css/src/runtime/mod.rs | 4 +- .../src/source_map_dev_tool_plugin.rs | 4 +- .../src/lib_manifest_plugin.rs | 8 +- .../rspack_plugin_extract_css/src/plugin.rs | 9 +- .../rspack_plugin_extract_css/src/runtime.rs | 5 +- crates/rspack_plugin_hmr/src/lib.rs | 31 +- .../src/dependency/worker/mod.rs | 2 +- .../src/plugin/impl_plugin_for_js_plugin.rs | 6 +- .../src/plugin/mod.rs | 2 +- .../rspack_plugin_javascript/src/runtime.rs | 3 +- .../src/amd_library_plugin.rs | 4 +- .../src/assign_library_plugin.rs | 4 +- .../src/umd_library_plugin.rs | 4 +- .../src/container/remote_runtime_module.rs | 2 +- .../sharing/consume_shared_runtime_module.rs | 2 +- .../src/array_push_callback_chunk_format.rs | 5 +- .../src/common_js_chunk_format.rs | 2 +- crates/rspack_plugin_runtime/src/helpers.rs | 8 +- .../src/module_chunk_format.rs | 2 +- .../src/runtime_module/auto_public_path.rs | 4 +- .../runtime_module/chunk_prefetch_startup.rs | 12 +- .../runtime_module/chunk_prefetch_trigger.rs | 5 +- .../runtime_module/chunk_preload_trigger.rs | 5 +- .../src/runtime_module/get_chunk_filename.rs | 32 ++- .../get_chunk_update_filename.rs | 2 +- .../src/runtime_module/get_main_filename.rs | 4 +- .../startup_chunk_dependencies.rs | 2 +- .../src/runtime_module/utils.rs | 49 +++- .../__snapshots__/output.snap.txt | 28 +- .../__snapshots__/output.snap.txt | 12 +- .../__snapshots__/output.snap.txt | 12 +- .../id-equals-name/0/id-equals-name.js | 1 + .../chunk-ids/id-equals-name/0/index.js | 23 ++ .../chunk-ids/id-equals-name/1/index.js | 23 ++ .../watchCases/chunk-ids/update-module/0/a.js | 1 + .../chunk-ids/update-module/0/index.js | 33 +++ .../watchCases/chunk-ids/update-module/1/a.js | 1 + .../module-ids/ignored-module/0/index.js | 5 +- .../module-ids/ignored-module/1/index.js | 5 +- .../module-ids/update-module/0/index.js | 3 +- .../DeterministicChunkIdsPlugin.ts | 28 +- .../builtin-plugin/NaturalChunkIdsPlugin.ts | 28 +- packages/rspack/src/rspackOptionsApply.ts | 1 + .../StatsTestCases.basictest.js.snap | 10 +- website/docs/en/config/experiments.mdx | 2 + website/docs/zh/config/experiments.mdx | 2 + 65 files changed, 775 insertions(+), 448 deletions(-) create mode 100644 packages/rspack-test-tools/tests/watchCases/chunk-ids/id-equals-name/0/id-equals-name.js create mode 100644 packages/rspack-test-tools/tests/watchCases/chunk-ids/id-equals-name/0/index.js create mode 100644 packages/rspack-test-tools/tests/watchCases/chunk-ids/id-equals-name/1/index.js create mode 100644 packages/rspack-test-tools/tests/watchCases/chunk-ids/update-module/0/a.js create mode 100644 packages/rspack-test-tools/tests/watchCases/chunk-ids/update-module/0/index.js create mode 100644 packages/rspack-test-tools/tests/watchCases/chunk-ids/update-module/1/a.js diff --git a/crates/rspack_binding_values/src/chunk.rs b/crates/rspack_binding_values/src/chunk.rs index 3eb74b0506e..416db1ab26e 100644 --- a/crates/rspack_binding_values/src/chunk.rs +++ b/crates/rspack_binding_values/src/chunk.rs @@ -40,17 +40,22 @@ impl JsChunk { #[napi(getter)] pub fn id(&self) -> napi::Result> { - let (_, chunk) = self.as_ref()?; - Ok(match chunk.id() { - Some(id) => Either::A(id), + let (compilation, chunk) = self.as_ref()?; + Ok(match chunk.id(&compilation.chunk_ids) { + Some(id) => Either::A(id.as_str()), None => Either::B(()), }) } #[napi(getter)] pub fn ids(&self) -> napi::Result> { - let (_, chunk) = self.as_ref()?; - Ok(chunk.id().map(|id| vec![id]).unwrap_or_default()) + let (compilation, chunk) = self.as_ref()?; + Ok( + chunk + .id(&compilation.chunk_ids) + .map(|id| vec![id.as_str()]) + .unwrap_or_default(), + ) } #[napi(getter)] diff --git a/crates/rspack_core/src/chunk.rs b/crates/rspack_core/src/chunk.rs index 8a90e176a16..365cacec879 100644 --- a/crates/rspack_core/src/chunk.rs +++ b/crates/rspack_core/src/chunk.rs @@ -9,6 +9,7 @@ use rspack_error::Diagnostic; use rspack_hash::{RspackHash, RspackHashDigest}; use rustc_hash::{FxHashMap as HashMap, FxHashSet as HashSet, FxHasher}; +use crate::chunk_graph_chunk::ChunkId; use crate::{ compare_chunk_group, merge_runtime, sort_group_by_index, ChunkGraph, ChunkGroupOrderKey, RenderManifestEntry, @@ -58,7 +59,6 @@ pub struct Chunk { // - The name of chunks create by dynamic import is `None` unless users use // magic comment like `import(/* webpackChunkName: "someChunk" * / './someModule.js')` to specify it. name: Option, - id: Option, id_name_hints: HashSet, filename_template: Option, css_filename_template: Option, @@ -108,12 +108,23 @@ impl Chunk { self.css_filename_template = filename_template; } - pub fn id(&self) -> Option<&str> { - self.id.as_deref() + pub fn id<'a>(&self, chunk_ids: &'a UkeyMap) -> Option<&'a ChunkId> { + ChunkGraph::get_chunk_id(chunk_ids, &self.ukey) } - pub fn set_id(&mut self, id: Option) { - self.id = id; + pub fn expect_id<'a>(&self, chunk_ids: &'a UkeyMap) -> &'a ChunkId { + self + .id(chunk_ids) + .expect("Should set id before calling expect_id") + } + + pub fn set_id( + &self, + chunk_ids: &mut UkeyMap, + id: impl Into, + ) -> bool { + let id = id.into(); + ChunkGraph::set_chunk_id(chunk_ids, self.ukey, id) } pub fn prevent_integration(&self) -> bool { @@ -263,7 +274,6 @@ impl Chunk { filename_template: None, css_filename_template: None, ukey: ChunkUkey::new(), - id: None, id_name_hints: Default::default(), prevent_integration: false, files: Default::default(), @@ -578,18 +588,14 @@ impl Chunk { chunks } - pub fn expect_id(&self) -> &str { - self - .id - .as_ref() - .expect("Should set id before calling expect_id") - } - - pub fn name_for_filename_template(&self) -> Option<&str> { + pub fn name_for_filename_template<'a>( + &'a self, + chunk_ids: &'a UkeyMap, + ) -> Option<&'a str> { if self.name.is_some() { self.name.as_deref() } else { - self.id.as_deref() + self.id(chunk_ids).map(|id| id.as_str()) } } @@ -602,7 +608,7 @@ impl Chunk { } pub fn update_hash(&self, hasher: &mut RspackHash, compilation: &Compilation) { - self.id.hash(hasher); + self.id(&compilation.chunk_ids).hash(hasher); for module in compilation .chunk_graph .get_ordered_chunk_modules(&self.ukey, &compilation.get_module_graph()) @@ -716,16 +722,20 @@ impl Chunk { &self, order: &ChunkGroupOrderKey, compilation: &Compilation, - ) -> Option> { + ) -> Option> { self .get_children_of_type_in_order(order, compilation, true) .map(|order_children| { order_children .iter() .flat_map(|(_, child_chunks)| { - child_chunks - .iter() - .filter_map(|chunk_ukey| compilation.chunk_by_ukey.expect_get(chunk_ukey).id.clone()) + child_chunks.iter().filter_map(|chunk_ukey| { + compilation + .chunk_by_ukey + .expect_get(chunk_ukey) + .id(&compilation.chunk_ids) + .cloned() + }) }) .collect_vec() }) @@ -735,7 +745,8 @@ impl Chunk { &self, include_direct_children: bool, compilation: &Compilation, - ) -> HashMap, BuildHasherDefault>> { + ) -> HashMap, BuildHasherDefault>> + { let mut result = HashMap::default(); fn add_child_ids_by_orders_to_map( @@ -743,13 +754,13 @@ impl Chunk { order: &ChunkGroupOrderKey, result: &mut HashMap< ChunkGroupOrderKey, - IndexMap, BuildHasherDefault>, + IndexMap, BuildHasherDefault>, >, compilation: &Compilation, ) { let chunk = compilation.chunk_by_ukey.expect_get(chunk_ukey); if let (Some(chunk_id), Some(child_chunk_ids)) = ( - chunk.id.clone(), + chunk.id(&compilation.chunk_ids).cloned(), chunk.get_child_ids_by_order(order, compilation), ) { result diff --git a/crates/rspack_core/src/chunk_graph/chunk_graph_chunk.rs b/crates/rspack_core/src/chunk_graph/chunk_graph_chunk.rs index 04114a28d66..5b228c01a05 100644 --- a/crates/rspack_core/src/chunk_graph/chunk_graph_chunk.rs +++ b/crates/rspack_core/src/chunk_graph/chunk_graph_chunk.rs @@ -1,10 +1,18 @@ //! There are methods whose verb is `ChunkGraphChunk` +use std::borrow::Borrow; +use std::fmt; +use std::sync::Arc; + use hashlink::LinkedHashMap; use indexmap::IndexSet; use itertools::Itertools; -use rspack_collections::{DatabaseItem, IdentifierLinkedMap, IdentifierMap, IdentifierSet}; +use rspack_cacheable::cacheable; +use rspack_collections::{ + DatabaseItem, IdentifierLinkedMap, IdentifierMap, IdentifierSet, UkeyMap, +}; use rustc_hash::{FxHashMap as HashMap, FxHashSet}; +use serde::{Serialize, Serializer}; use crate::{ find_graph_roots, merge_runtime, BoxModule, Chunk, ChunkByUkey, ChunkGraphModule, @@ -21,6 +29,51 @@ pub struct ChunkSizeOptions { pub entry_chunk_multiplicator: Option, } +#[cacheable] +#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub struct ChunkId { + inner: Arc, +} + +impl From for ChunkId { + fn from(s: String) -> Self { + Self { inner: s.into() } + } +} + +impl From<&str> for ChunkId { + fn from(s: &str) -> Self { + Self { inner: s.into() } + } +} + +impl fmt::Display for ChunkId { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.as_str()) + } +} + +impl Serialize for ChunkId { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl Borrow for ChunkId { + fn borrow(&self) -> &str { + self.as_str() + } +} + +impl ChunkId { + pub fn as_str(&self) -> &str { + &self.inner + } +} + #[derive(Debug, Clone, Default)] pub struct ChunkGraphChunk { /// URI of modules => ChunkGroupUkey @@ -550,7 +603,10 @@ impl ChunkGraph { .iter() { let chunk = compilation.chunk_by_ukey.expect_get(c); - map.insert(chunk.expect_id().to_string(), filter(c, compilation)); + map.insert( + chunk.expect_id(&compilation.chunk_ids).to_string(), + filter(c, compilation), + ); } map @@ -912,4 +968,23 @@ impl ChunkGraph { }) .unwrap_or(module.source_types().iter().copied().collect()) } + + pub fn get_chunk_id<'a>( + chunk_ids: &'a UkeyMap, + chunk_ukey: &ChunkUkey, + ) -> Option<&'a ChunkId> { + chunk_ids.get(chunk_ukey) + } + + pub fn set_chunk_id( + chunk_ids: &mut UkeyMap, + chunk_ukey: ChunkUkey, + id: ChunkId, + ) -> bool { + if let Some(old_id) = chunk_ids.insert(chunk_ukey, id.clone()) { + old_id != id + } else { + true + } + } } diff --git a/crates/rspack_core/src/chunk_group.rs b/crates/rspack_core/src/chunk_group.rs index 4c99c27abaf..166eda5721e 100644 --- a/crates/rspack_core/src/chunk_group.rs +++ b/crates/rspack_core/src/chunk_group.rs @@ -265,7 +265,7 @@ impl ChunkGroup { compilation .chunk_by_ukey .get(chunk) - .and_then(|item| item.id()) + .and_then(|item| item.id(&compilation.chunk_ids)) }) .join("+") } diff --git a/crates/rspack_core/src/compiler/compilation.rs b/crates/rspack_core/src/compiler/compilation.rs index 0e8c651b490..95c999dd612 100644 --- a/crates/rspack_core/src/compiler/compilation.rs +++ b/crates/rspack_core/src/compiler/compilation.rs @@ -34,6 +34,7 @@ use crate::{ cache::Cache, cgm_hash_results::CgmHashResults, cgm_runtime_requirement_results::CgmRuntimeRequirementsResults, + chunk_graph_chunk::ChunkId, chunk_graph_module::ModuleId, get_runtime_key, incremental::{Incremental, IncrementalPasses, Mutation}, @@ -181,6 +182,8 @@ pub struct Compilation { pub dependencies_diagnostics: IdentifierMap>, // artifact for module_ids pub module_ids: IdentifierMap, + // artifact for chunk_ids + pub chunk_ids: UkeyMap, // artifact for code_generation pub code_generation_results: CodeGenerationResults, // artifact for create_module_hashes @@ -201,7 +204,6 @@ pub struct Compilation { pub incremental: Incremental, pub hash: Option, - pub used_chunk_ids: HashSet, pub file_dependencies: IndexSet>, pub context_dependencies: IndexSet>, @@ -289,6 +291,7 @@ impl Compilation { async_modules: Default::default(), dependencies_diagnostics: Default::default(), module_ids: Default::default(), + chunk_ids: Default::default(), code_generation_results: Default::default(), cgm_hash_results: Default::default(), cgm_runtime_requirements_results: Default::default(), @@ -301,8 +304,8 @@ impl Compilation { old_cache, incremental, code_splitting_cache: Default::default(), + hash: None, - used_chunk_ids: Default::default(), file_dependencies: Default::default(), context_dependencies: Default::default(), @@ -1502,6 +1505,7 @@ impl Compilation { entrypoint_ukey: &ChunkGroupUkey, chunk_group_by_ukey: &ChunkGroupByUkey, chunk_by_ukey: &ChunkByUkey, + chunk_ids: &UkeyMap, chunk_graph: &mut ChunkGraph, ) { let entrypoint = chunk_group_by_ukey.expect_get(entrypoint_ukey); @@ -1517,7 +1521,7 @@ impl Compilation { runtime, chunk_by_ukey.get(&entrypoint.get_runtime_chunk(chunk_group_by_ukey)), ) { - chunk_graph.set_runtime_id(runtime, chunk.id().map(ToOwned::to_owned)); + chunk_graph.set_runtime_id(runtime, chunk.id(chunk_ids).map(|id| id.to_string())); } } for i in self.entrypoints.iter() { @@ -1525,6 +1529,7 @@ impl Compilation { i.1, &self.chunk_group_by_ukey, &self.chunk_by_ukey, + &self.chunk_ids, &mut self.chunk_graph, ) } @@ -1533,6 +1538,7 @@ impl Compilation { i, &self.chunk_group_by_ukey, &self.chunk_by_ukey, + &self.chunk_ids, &mut self.chunk_graph, ) } @@ -1862,11 +1868,16 @@ impl Compilation { .filter(|(_, (_, remaining))| *remaining != 0) .map(|(chunk_ukey, _)| self.chunk_by_ukey.expect_get(chunk_ukey)) .collect(); - circular.sort_unstable_by(|a, b| a.id().cmp(&b.id())); + circular.sort_unstable_by(|a, b| a.id(&self.chunk_ids).cmp(&b.id(&self.chunk_ids))); runtime_chunks.extend(circular.iter().map(|chunk| chunk.ukey())); let circular_names = circular .iter() - .map(|chunk| chunk.name().or(chunk.id()).unwrap_or("no id chunk")) + .map(|chunk| { + chunk + .name() + .or(chunk.id(&self.chunk_ids).map(|id| id.as_str())) + .unwrap_or("no id chunk") + }) .join(", "); self.push_diagnostic(diagnostic!(severity = Severity::Warn, "Circular dependency between chunks with runtime ({})\nThis prevents using hashes of each other and should be avoided.", circular_names).boxed().into()); } diff --git a/crates/rspack_core/src/compiler/hmr.rs b/crates/rspack_core/src/compiler/hmr.rs index 181b2619bdf..b3f79ed10a0 100644 --- a/crates/rspack_core/src/compiler/hmr.rs +++ b/crates/rspack_core/src/compiler/hmr.rs @@ -9,8 +9,9 @@ use rspack_sources::Source; use rustc_hash::FxHashSet as HashSet; use crate::{ - chunk_graph_module::ModuleId, fast_set, incremental::IncrementalPasses, ChunkGraph, ChunkKind, - Compilation, Compiler, ModuleExecutor, RuntimeSpec, + chunk_graph_chunk::ChunkId, chunk_graph_module::ModuleId, fast_set, + incremental::IncrementalPasses, ChunkGraph, ChunkKind, Compilation, Compiler, ModuleExecutor, + RuntimeSpec, }; impl Compiler { @@ -32,10 +33,13 @@ impl Compiler { .flat_map(|entry_chunk| entry_chunk.runtime().clone()) .collect(); - let mut old_chunks: Vec<(String, RuntimeSpec)> = vec![]; + let mut old_chunks: Vec<(ChunkId, RuntimeSpec)> = vec![]; for (_, chunk) in old.compilation.chunk_by_ukey.iter() { if chunk.kind() != ChunkKind::HotUpdate { - old_chunks.push((chunk.expect_id().to_string(), chunk.runtime().clone())); + old_chunks.push(( + chunk.expect_id(&old.compilation.chunk_ids).clone(), + chunk.runtime().clone(), + )); } } @@ -123,6 +127,12 @@ impl Compiler { { new_compilation.module_ids = std::mem::take(&mut self.compilation.module_ids); } + if new_compilation + .incremental + .can_read_mutations(IncrementalPasses::CHUNK_IDS) + { + new_compilation.chunk_ids = std::mem::take(&mut self.compilation.chunk_ids); + } if new_compilation .incremental .can_read_mutations(IncrementalPasses::MODULES_HASHES) @@ -184,7 +194,7 @@ impl Compiler { #[derive(Debug)] pub struct CompilationRecords { - pub old_chunks: Vec<(String, RuntimeSpec)>, + pub old_chunks: Vec<(ChunkId, RuntimeSpec)>, pub all_old_runtime: RuntimeSpec, pub old_all_modules: IdentifierMap<(RspackHashDigest, ModuleId)>, pub old_runtime_modules: IdentifierMap, diff --git a/crates/rspack_core/src/compiler/module_executor/execute.rs b/crates/rspack_core/src/compiler/module_executor/execute.rs index 03b927bcac2..39a82e7d81a 100644 --- a/crates/rspack_core/src/compiler/module_executor/execute.rs +++ b/crates/rspack_core/src/compiler/module_executor/execute.rs @@ -100,7 +100,9 @@ impl Task for ExecuteTask { let mut chunk = Chunk::new(Some("build time chunk".into()), ChunkKind::Normal); - chunk.set_id(chunk.name().map(ToOwned::to_owned)); + if let Some(name) = chunk.name() { + chunk.set_id(&mut compilation.chunk_ids, name); + } let runtime: RuntimeSpec = once("build time".into()).collect(); chunk.set_runtime(runtime.clone()); diff --git a/crates/rspack_core/src/context_module.rs b/crates/rspack_core/src/context_module.rs index 8cdb3f60d0f..b5afc86c398 100644 --- a/crates/rspack_core/src/context_module.rs +++ b/crates/rspack_core/src/context_module.rs @@ -479,7 +479,7 @@ impl ContextModule { let chunk_id = compilation .chunk_by_ukey .expect_get(c) - .id() + .id(&compilation.chunk_ids) .expect("should have chunk id in code generation"); serde_json::json!(chunk_id) })) diff --git a/crates/rspack_core/src/dependency/runtime_template.rs b/crates/rspack_core/src/dependency/runtime_template.rs index fbc2d28e77e..9f9cb091f74 100644 --- a/crates/rspack_core/src/dependency/runtime_template.rs +++ b/crates/rspack_core/src/dependency/runtime_template.rs @@ -579,12 +579,18 @@ pub fn block_promise( .chunks .iter() .map(|c| compilation.chunk_by_ukey.expect_get(c)) - .filter(|c| !c.has_runtime(&compilation.chunk_group_by_ukey) && c.id().is_some()) + .filter(|c| { + !c.has_runtime(&compilation.chunk_group_by_ukey) && c.id(&compilation.chunk_ids).is_some() + }) .collect::>(); if chunks.len() == 1 { - let chunk_id = serde_json::to_string(chunks[0].id().expect("should have chunk.id")) - .expect("should able to json stringify"); + let chunk_id = serde_json::to_string( + chunks[0] + .id(&compilation.chunk_ids) + .expect("should have chunk.id"), + ) + .expect("should able to json stringify"); runtime_requirements.insert(RuntimeGlobals::ENSURE_CHUNK); let fetch_priority = chunk_group @@ -622,7 +628,7 @@ pub fn block_promise( .map(|c| format!( "{}({}{})", RuntimeGlobals::ENSURE_CHUNK, - serde_json::to_string(c.id().expect("should have chunk.id")) + serde_json::to_string(c.id(&compilation.chunk_ids).expect("should have chunk.id")) .expect("should able to json stringify"), fetch_priority .map(|x| format!(r#", "{x}""#)) diff --git a/crates/rspack_core/src/incremental/mutations.rs b/crates/rspack_core/src/incremental/mutations.rs index 04163236b8a..26bd599afb2 100644 --- a/crates/rspack_core/src/incremental/mutations.rs +++ b/crates/rspack_core/src/incremental/mutations.rs @@ -39,6 +39,7 @@ pub enum Mutation { ModuleRemove { module: ModuleIdentifier }, ModuleSetAsync { module: ModuleIdentifier }, ModuleSetId { module: ModuleIdentifier }, + ChunkSetId { chunk: ChunkUkey }, ChunkAdd { chunk: ChunkUkey }, ChunkSplit { from: ChunkUkey, to: ChunkUkey }, ChunksIntegrate { to: ChunkUkey }, @@ -52,6 +53,7 @@ impl fmt::Display for Mutation { Mutation::ModuleRemove { module } => write!(f, "remove module {}", module), Mutation::ModuleSetAsync { module } => write!(f, "set async module {}", module), Mutation::ModuleSetId { module } => write!(f, "set id module {}", module), + Mutation::ChunkSetId { chunk } => write!(f, "set id chunk {}", chunk.as_u32()), Mutation::ChunkAdd { chunk } => write!(f, "add chunk {}", chunk.as_u32()), Mutation::ChunkSplit { from, to } => { write!(f, "split chunk {} to {}", from.as_u32(), to.as_u32()) @@ -326,7 +328,7 @@ fn compute_affected_modules_with_chunk_graph( }; for chunk in &chunk_group.chunks { let chunk = compilation.chunk_by_ukey.expect_get(chunk); - chunk.id().hash(&mut hasher); + chunk.id(&compilation.chunk_ids).hash(&mut hasher); } } hasher.finish() diff --git a/crates/rspack_core/src/stats/mod.rs b/crates/rspack_core/src/stats/mod.rs index a0adc311b90..4441575c813 100644 --- a/crates/rspack_core/src/stats/mod.rs +++ b/crates/rspack_core/src/stats/mod.rs @@ -119,7 +119,11 @@ impl Stats<'_> { if let Some(chunks) = compilation_file_to_chunks.get(name) { asset.chunks = chunks .par_iter() - .map(|chunk| chunk.id().map(ToOwned::to_owned)) + .map(|chunk| { + chunk + .id(&self.compilation.chunk_ids) + .map(|id| id.to_string()) + }) .collect(); asset.chunks.sort_unstable(); asset.chunk_names = chunks @@ -137,7 +141,11 @@ impl Stats<'_> { if let Some(auxiliary_chunks) = compilation_file_to_auxiliary_chunks.get(name) { asset.auxiliary_chunks = auxiliary_chunks .par_iter() - .map(|chunk| chunk.id().map(ToOwned::to_owned)) + .map(|chunk| { + chunk + .id(&self.compilation.chunk_ids) + .map(|id| id.to_string()) + }) .collect(); asset.auxiliary_chunks.sort_unstable(); asset.auxiliary_chunk_names = auxiliary_chunks @@ -297,13 +305,7 @@ impl Stats<'_> { let (parents, children, siblings) = options .chunk_relations - .then(|| { - get_chunk_relations( - c, - &self.compilation.chunk_group_by_ukey, - &self.compilation.chunk_by_ukey, - ) - }) + .then(|| get_chunk_relations(c, self.compilation)) .map_or((None, None, None), |(parents, children, siblings)| { (Some(parents), Some(children), Some(siblings)) }); @@ -311,7 +313,13 @@ impl Stats<'_> { let mut children_by_order = HashMap::>::default(); for order in &orders { if let Some(order_chlidren) = c.get_child_ids_by_order(order, self.compilation) { - children_by_order.insert(order.clone(), order_chlidren); + children_by_order.insert( + order.clone(), + order_chlidren + .into_iter() + .map(|id| id.to_string()) + .collect(), + ); } } @@ -366,7 +374,7 @@ impl Stats<'_> { r#type: "chunk", files, auxiliary_files, - id: c.id().map(ToOwned::to_owned), + id: c.id(&self.compilation.chunk_ids).map(|id| id.to_string()), id_hints, names: c.name().map(|n| vec![n.to_owned()]).unwrap_or_default(), entry: c.has_entry_module(chunk_graph), @@ -421,8 +429,8 @@ impl Stats<'_> { .compilation .chunk_by_ukey .expect_get(c) - .id() - .map(ToOwned::to_owned) + .id(&self.compilation.chunk_ids) + .map(|id| id.to_string()) }) .collect(); @@ -586,7 +594,7 @@ impl Stats<'_> { chunk_name: chunk.and_then(|c| c.name().map(ToOwned::to_owned)), chunk_entry: chunk.map(|c| c.has_runtime(&self.compilation.chunk_group_by_ukey)), chunk_initial: chunk.map(|c| c.can_be_initial(&self.compilation.chunk_group_by_ukey)), - chunk_id: chunk.and_then(|c| c.id().map(ToOwned::to_owned)), + chunk_id: chunk.and_then(|c| c.id(&self.compilation.chunk_ids).map(|id| id.to_string())), details: d.details(), stack: d.stack(), module_trace, @@ -637,7 +645,7 @@ impl Stats<'_> { chunk_name: chunk.and_then(|c| c.name().map(ToOwned::to_owned)), chunk_entry: chunk.map(|c| c.has_runtime(&self.compilation.chunk_group_by_ukey)), chunk_initial: chunk.map(|c| c.can_be_initial(&self.compilation.chunk_group_by_ukey)), - chunk_id: chunk.and_then(|c| c.id().map(ToOwned::to_owned)), + chunk_id: chunk.and_then(|c| c.id(&self.compilation.chunk_ids).map(|id| id.to_string())), details: d.details(), stack: d.stack(), module_trace, @@ -861,8 +869,8 @@ impl Stats<'_> { .compilation .chunk_by_ukey .expect_get(k) - .id() - .map(ToOwned::to_owned) + .id(&self.compilation.chunk_ids) + .map(|id| id.to_string()) }) .collect() }; @@ -1134,8 +1142,8 @@ impl Stats<'_> { .compilation .chunk_by_ukey .expect_get(k) - .id() - .map(ToOwned::to_owned) + .id(&self.compilation.chunk_ids) + .map(|id| id.to_string()) }) .collect(); chunks.sort_unstable(); diff --git a/crates/rspack_core/src/stats/utils.rs b/crates/rspack_core/src/stats/utils.rs index 81ac61924f8..29e6d4a252c 100644 --- a/crates/rspack_core/src/stats/utils.rs +++ b/crates/rspack_core/src/stats/utils.rs @@ -94,20 +94,19 @@ pub fn get_chunk_group_oreded_child_assets( pub fn get_chunk_relations( chunk: &Chunk, - chunk_group_by_ukey: &ChunkGroupByUkey, - chunk_by_ukey: &ChunkByUkey, + compilation: &Compilation, ) -> (Vec, Vec, Vec) { let mut parents = HashSet::default(); let mut children = HashSet::default(); let mut siblings = HashSet::default(); for cg in chunk.groups() { - if let Some(cg) = chunk_group_by_ukey.get(cg) { + if let Some(cg) = compilation.chunk_group_by_ukey.get(cg) { for p in &cg.parents { - if let Some(pg) = chunk_group_by_ukey.get(p) { + if let Some(pg) = compilation.chunk_group_by_ukey.get(p) { for c in &pg.chunks { - if let Some(c) = chunk_by_ukey.get(c) - && let Some(id) = c.id() + if let Some(c) = compilation.chunk_by_ukey.get(c) + && let Some(id) = c.id(&compilation.chunk_ids) { parents.insert(id.to_string()); } @@ -116,10 +115,10 @@ pub fn get_chunk_relations( } for p in &cg.children { - if let Some(pg) = chunk_group_by_ukey.get(p) { + if let Some(pg) = compilation.chunk_group_by_ukey.get(p) { for c in &pg.chunks { - if let Some(c) = chunk_by_ukey.get(c) - && let Some(id) = c.id() + if let Some(c) = compilation.chunk_by_ukey.get(c) + && let Some(id) = c.id(&compilation.chunk_ids) { children.insert(id.to_string()); } @@ -128,9 +127,9 @@ pub fn get_chunk_relations( } for c in &cg.chunks { - if let Some(c) = chunk_by_ukey.get(c) - && c.id() != chunk.id() - && let Some(id) = c.id() + if let Some(c) = compilation.chunk_by_ukey.get(c) + && c.id(&compilation.chunk_ids) != chunk.id(&compilation.chunk_ids) + && let Some(id) = c.id(&compilation.chunk_ids) { siblings.insert(id.to_string()); } diff --git a/crates/rspack_core/src/utils/mod.rs b/crates/rspack_core/src/utils/mod.rs index 9c570be723e..f5643f9357d 100644 --- a/crates/rspack_core/src/utils/mod.rs +++ b/crates/rspack_core/src/utils/mod.rs @@ -1,10 +1,8 @@ -use std::{cmp::Ordering, fmt::Display}; +use std::cmp::Ordering; -use itertools::Itertools; use rspack_collections::Identifier; use rspack_util::comparators::compare_ids; use rspack_util::comparators::compare_numbers; -use rustc_hash::FxHashMap as HashMap; use crate::{ BoxModule, ChunkGraph, ChunkGroupByUkey, ChunkGroupUkey, ChunkUkey, Compilation, ModuleGraph, @@ -96,24 +94,6 @@ pub fn join_string_component(mut components: Vec) -> String { } } -pub fn stringify_map(map: &HashMap) -> String { - format!( - r#"{{{}}}"#, - map - .keys() - .sorted_unstable() - .fold(String::new(), |prev, cur| { - prev - + format!( - r#"{}: {},"#, - serde_json::to_string(cur).expect("json stringify failed"), - map.get(cur).expect("get key from map") - ) - .as_str() - }) - ) -} - pub fn sort_group_by_index( ukey_a: &ChunkGroupUkey, ukey_b: &ChunkGroupUkey, diff --git a/crates/rspack_ids/src/deterministic_chunk_ids_plugin.rs b/crates/rspack_ids/src/deterministic_chunk_ids_plugin.rs index c24882ede99..76a3fcb5f36 100644 --- a/crates/rspack_ids/src/deterministic_chunk_ids_plugin.rs +++ b/crates/rspack_ids/src/deterministic_chunk_ids_plugin.rs @@ -1,9 +1,8 @@ -use std::collections::HashMap; - use rspack_collections::DatabaseItem; use rspack_core::{ApplyContext, CompilationChunkIds, CompilerOptions, Plugin, PluginContext}; use rspack_error::Result; use rspack_hook::{plugin, plugin_hook}; +use rustc_hash::{FxBuildHasher, FxHashMap}; use crate::id_helpers::{ assign_deterministic_ids, compare_chunks_natural, get_full_chunk_name, get_used_chunk_ids, @@ -41,9 +40,10 @@ fn chunk_ids(&self, compilation: &mut rspack_core::Compilation) -> rspack_error: let chunks = compilation .chunk_by_ukey .values() - .filter(|chunk| chunk.id().is_none()) + .filter(|chunk| chunk.id(&compilation.chunk_ids).is_none()) .collect::>(); - let mut chunk_key_to_id = HashMap::with_capacity(chunks.len()); + let mut chunk_key_to_id = + FxHashMap::with_capacity_and_hasher(chunks.len(), FxBuildHasher::default()); assign_deterministic_ids( chunks, @@ -67,7 +67,7 @@ fn chunk_ids(&self, compilation: &mut rspack_core::Compilation) -> rspack_error: chunk_key_to_id.into_iter().for_each(|(chunk_ukey, id)| { let chunk = compilation.chunk_by_ukey.expect_get_mut(&chunk_ukey); - chunk.set_id(Some(id.to_string())); + chunk.set_id(&mut compilation.chunk_ids, id.to_string()); }); Ok(()) diff --git a/crates/rspack_ids/src/id_helpers.rs b/crates/rspack_ids/src/id_helpers.rs index 7e6b17f384f..b0daa2471a1 100644 --- a/crates/rspack_ids/src/id_helpers.rs +++ b/crates/rspack_ids/src/id_helpers.rs @@ -2,7 +2,6 @@ use std::sync::LazyLock; use std::{ borrow::Cow, cmp::Ordering, - collections::{hash_map::DefaultHasher, HashMap, HashSet}, hash::{Hash, Hasher}, }; @@ -10,7 +9,6 @@ use itertools::{ EitherOrBoth::{Both, Left, Right}, Itertools, }; -use rayon::prelude::*; use regex::Regex; use rspack_collections::{DatabaseItem, IdentifierMap}; use rspack_core::{ @@ -23,16 +21,17 @@ use rspack_util::{ identifier::make_paths_relative, number_hash::get_number_hash, }; +use rustc_hash::{FxHashSet, FxHasher}; #[allow(clippy::type_complexity)] #[allow(clippy::collapsible_else_if)] pub fn get_used_module_ids_and_modules( compilation: &Compilation, filter: Option bool>>, -) -> (HashSet, Vec) { +) -> (FxHashSet, Vec) { let chunk_graph = &compilation.chunk_graph; let mut modules = vec![]; - let mut used_ids = HashSet::new(); + let mut used_ids = FxHashSet::default(); // TODO: currently we don't have logic of compilation.usedModuleIds // if (compilation.usedModuleIds) { @@ -106,7 +105,7 @@ pub fn get_full_module_name(module: &BoxModule, context: &str) -> String { } pub fn get_hash(s: impl Hash, length: usize) -> String { - let mut hasher = DefaultHasher::default(); + let mut hasher = FxHasher::default(); s.hash(&mut hasher); let hash = hasher.finish(); let mut hash_str = format!("{hash:x}"); @@ -116,137 +115,6 @@ pub fn get_hash(s: impl Hash, length: usize) -> String { hash_str } -// pub fn assign_names( -// items: Vec, -// get_short_name: impl Fn(T) -> String, -// get_long_name: impl Fn(T, &str) -> String, -// comparator: impl Fn(&T, &T) -> Ordering, -// used_ids: &mut HashSet, -// mut assign_name: impl FnMut(T, String), -// ) -> Vec { -// let mut name_to_items: HashMap> = HashMap::default(); -// for item in items { -// let name = get_short_name(item); -// name_to_items.entry(name).or_default().push(item); -// } -// -// let mut name_to_items2: HashMap> = HashMap::default(); -// -// for (name, items) in name_to_items { -// if items.len() > 1 || name.is_empty() { -// for item in items { -// let long_name = get_long_name(item, &name); -// name_to_items2.entry(long_name).or_default().push(item); -// } -// } else { -// name_to_items2.entry(name).or_default().push(items[0]); -// } -// } -// -// let name_to_items2_keys = name_to_items2.keys().cloned().collect::>(); -// -// let mut unnamed_items = vec![]; -// for (name, mut items) in name_to_items2 { -// if name.is_empty() { -// for item in items { -// unnamed_items.push(item) -// } -// } else if items.len() == 1 && !used_ids.contains(&name) { -// assign_name(items[0], name.clone()); -// used_ids.insert(name.clone()); -// } else { -// items.sort_unstable_by(&comparator); -// let mut i = 0; -// for item in items { -// let formatted_name = format!("{name}{i}"); -// while name_to_items2_keys.contains(&formatted_name) && used_ids.contains(&formatted_name) { -// i += 1; -// } -// assign_name(item, formatted_name.clone()); -// used_ids.insert(formatted_name); -// i += 1; -// } -// } -// } -// unnamed_items.sort_unstable_by(comparator); -// unnamed_items -// } - -pub fn assign_names_par( - items: Vec, - get_short_name: impl Fn(T) -> String + std::marker::Sync, - get_long_name: impl Fn(T, &str) -> String + std::marker::Sync, - comparator: impl Fn(&T, &T) -> Ordering, - used_ids: &mut HashSet, - mut assign_name: impl FnMut(T, String), -) -> Vec { - let item_name_pair = items - .into_par_iter() - .map(|item| { - let name = get_short_name(item); - (item, name) - }) - .collect::>(); - let mut name_to_items: HashMap> = HashMap::default(); - let mut invalid_and_repeat_names: HashSet = HashSet::default(); - invalid_and_repeat_names.insert(String::from("")); - for (item, name) in item_name_pair { - let items = name_to_items.entry(name.clone()).or_default(); - items.push(item); - if items.len() > 1 { - invalid_and_repeat_names.insert(name); - } - } - - let item_name_pair = invalid_and_repeat_names - .iter() - .flat_map(|name| { - let mut res = vec![]; - for item in name_to_items.remove(name).unwrap_or_default() { - res.push((name.clone(), item)); - } - res - }) - .par_bridge() - .map(|(name, item)| { - let long_name = get_long_name(item, name.as_str()); - (item, long_name) - }) - .collect::>(); - for (item, name) in item_name_pair { - name_to_items.entry(name).or_default().push(item); - } - - let name_to_items_keys = name_to_items.keys().cloned().collect::>(); - - let mut unnamed_items = vec![]; - for (name, mut items) in name_to_items { - if name.is_empty() { - for item in items { - unnamed_items.push(item) - } - } else if items.len() == 1 && !used_ids.contains(&name) { - assign_name(items[0], name.clone()); - used_ids.insert(name.clone()); - } else { - items.sort_unstable_by(&comparator); - let mut i = 0; - for item in items { - let mut formatted_name = format!("{name}{}", itoa!(i)); - while name_to_items_keys.contains(&formatted_name) && used_ids.contains(&formatted_name) { - i += 1; - formatted_name = format!("{name}{}", itoa!(i)); - } - assign_name(item, formatted_name.clone()); - used_ids.insert(formatted_name); - i += 1; - } - } - } - unnamed_items.sort_unstable_by(comparator); - unnamed_items -} - #[allow(clippy::too_many_arguments)] pub fn assign_deterministic_ids( mut items: Vec, @@ -287,7 +155,7 @@ pub fn assign_deterministic_ids( } pub fn assign_ascending_module_ids( - used_ids: &HashSet, + used_ids: &FxHashSet, modules: Vec<&BoxModule>, module_ids: &mut IdentifierMap, ) { @@ -448,15 +316,11 @@ pub fn request_to_id(request: &str) -> String { .to_string() } -pub fn get_used_chunk_ids(compilation: &Compilation) -> HashSet { - let mut used_ids = compilation - .used_chunk_ids - .iter() - .cloned() - .collect::>(); +pub fn get_used_chunk_ids(compilation: &Compilation) -> FxHashSet { + let mut used_ids = FxHashSet::default(); for chunk in compilation.chunk_by_ukey.values() { - if let Some(id) = chunk.id() { - used_ids.insert(id.to_owned()); + if let Some(id) = chunk.id(&compilation.chunk_ids) { + used_ids.insert(id.to_string()); } } used_ids @@ -469,19 +333,19 @@ pub fn assign_ascending_chunk_ids(chunks: &[ChunkUkey], compilation: &mut Compil if !used_ids.is_empty() { for chunk in chunks { let chunk = compilation.chunk_by_ukey.expect_get_mut(chunk); - if chunk.id().is_none() { + if chunk.id(&compilation.chunk_ids).is_none() { while used_ids.contains(&next_id.to_string()) { next_id += 1; } - chunk.set_id(Some(next_id.to_string())); + chunk.set_id(&mut compilation.chunk_ids, next_id.to_string()); next_id += 1; } } } else { for chunk in chunks { let chunk = compilation.chunk_by_ukey.expect_get_mut(chunk); - if chunk.id().is_none() { - chunk.set_id(Some(next_id.to_string())); + if chunk.id(&compilation.chunk_ids).is_none() { + chunk.set_id(&mut compilation.chunk_ids, next_id.to_string()); next_id += 1; } } diff --git a/crates/rspack_ids/src/named_chunk_ids_plugin.rs b/crates/rspack_ids/src/named_chunk_ids_plugin.rs index d3ed4c9302b..ca69d7fa0ef 100644 --- a/crates/rspack_ids/src/named_chunk_ids_plugin.rs +++ b/crates/rspack_ids/src/named_chunk_ids_plugin.rs @@ -1,15 +1,135 @@ -use std::collections::HashMap; - -use rspack_collections::DatabaseItem; +use rayon::iter::{IntoParallelIterator, ParallelBridge, ParallelIterator}; +use rspack_collections::{DatabaseItem, UkeyIndexSet, UkeyMap, UkeySet}; use rspack_core::{ - ApplyContext, Chunk, CompilationChunkIds, CompilerOptions, Plugin, PluginContext, + chunk_graph_chunk::ChunkId, + incremental::{IncrementalPasses, Mutation, Mutations}, + ApplyContext, ChunkGraph, ChunkUkey, Compilation, CompilationChunkIds, CompilerOptions, Logger, + Plugin, PluginContext, }; use rspack_hook::{plugin, plugin_hook}; +use rspack_util::itoa; +use rustc_hash::{FxHashMap, FxHashSet}; -use crate::id_helpers::{ - assign_ascending_chunk_ids, assign_names_par, compare_chunks_natural, get_long_chunk_name, - get_short_chunk_name, get_used_chunk_ids, -}; +use crate::id_helpers::{compare_chunks_natural, get_long_chunk_name, get_short_chunk_name}; + +#[tracing::instrument(skip_all)] +fn assign_named_chunk_ids( + chunks: UkeySet, + compilation: &Compilation, + delimiter: &str, + used_ids: &mut FxHashMap, + chunk_ids: &mut UkeyMap, + mutations: &mut Option, +) -> Vec { + let context: &str = compilation.options.context.as_ref(); + let module_graph = compilation.get_module_graph(); + let chunk_graph = &compilation.chunk_graph; + + let item_name_pair: Vec<_> = chunks + .into_par_iter() + .map(|item| { + let chunk = compilation.chunk_by_ukey.expect_get(&item); + let name = get_short_chunk_name(chunk, chunk_graph, context, delimiter, &module_graph); + (item, name) + }) + .collect(); + let mut name_to_items: FxHashMap> = FxHashMap::default(); + let mut invalid_and_repeat_names: FxHashSet = std::iter::once(String::new()).collect(); + for (item, name) in item_name_pair { + let items = name_to_items.entry(name.clone()).or_default(); + items.insert(item); + // If the short chunk id is conflict, then we need to rename all the conflicting chunks to long module id + if items.len() > 1 { + invalid_and_repeat_names.insert(name); + } + // Also rename the conflicting chunks in used_ids + else if let Some(item) = used_ids.get(name.as_str()) + // Unless the chunk is explicitly using chunk name as id + && matches!(compilation.chunk_by_ukey.expect_get(item).name(), Some(chunk_name) if chunk_name != name) + { + items.insert(*item); + invalid_and_repeat_names.insert(name); + } + } + + let item_name_pair: Vec<_> = invalid_and_repeat_names + .iter() + .flat_map(|name| { + let mut res = vec![]; + for item in name_to_items.remove(name).unwrap_or_default() { + res.push((name.clone(), item)); + } + res + }) + .par_bridge() + .map(|(_, item)| { + let chunk = compilation.chunk_by_ukey.expect_get(&item); + let long_name = get_long_chunk_name(chunk, chunk_graph, context, delimiter, &module_graph); + (item, long_name) + }) + .collect(); + for (item, name) in item_name_pair { + let items = name_to_items.entry(name.clone()).or_default(); + items.insert(item); + // Also rename the conflicting chunks in used_ids + if let Some(item) = used_ids.get(name.as_str()) + // Unless the chunk is explicitly using chunk name as id + && matches!(compilation.chunk_by_ukey.expect_get(item).name(), Some(chunk_name) if chunk_name != name) + { + items.insert(*item); + } + } + + let name_to_items_keys = name_to_items.keys().cloned().collect::>(); + let mut unnamed_items = vec![]; + + for (name, mut items) in name_to_items { + if name.is_empty() { + for item in items { + unnamed_items.push(item) + } + } else if items.len() == 1 && !used_ids.contains_key(name.as_str()) { + let item = items[0]; + let name: ChunkId = name.into(); + if ChunkGraph::set_chunk_id(chunk_ids, item, name.clone()) + && let Some(mutations) = mutations + { + mutations.add(Mutation::ChunkSetId { chunk: item }); + } + used_ids.insert(name, item); + } else { + items.sort_unstable_by(|a, b| { + let a = compilation.chunk_by_ukey.expect_get(a); + let b = compilation.chunk_by_ukey.expect_get(b); + compare_chunks_natural(chunk_graph, &module_graph, &compilation.module_ids, a, b) + }); + let mut i = 0; + for item in items { + let mut formatted_name = format!("{name}{}", itoa!(i)); + while name_to_items_keys.contains(&formatted_name) + && used_ids.contains_key(formatted_name.as_str()) + { + i += 1; + formatted_name = format!("{name}{}", itoa!(i)); + } + let name: ChunkId = formatted_name.into(); + if ChunkGraph::set_chunk_id(chunk_ids, item, name.clone()) + && let Some(mutations) = mutations + { + mutations.add(Mutation::ChunkSetId { chunk: item }); + } + used_ids.insert(name, item); + i += 1; + } + } + } + unnamed_items.sort_unstable_by(|a, b| { + let a = compilation.chunk_by_ukey.expect_get(a); + let b = compilation.chunk_by_ukey.expect_get(b); + compare_chunks_natural(chunk_graph, &module_graph, &compilation.module_ids, a, b) + }); + unnamed_items +} #[plugin] #[derive(Debug)] @@ -26,52 +146,118 @@ impl NamedChunkIdsPlugin { #[plugin_hook(CompilationChunkIds for NamedChunkIdsPlugin)] fn chunk_ids(&self, compilation: &mut rspack_core::Compilation) -> rspack_error::Result<()> { - // set default value - for chunk in compilation.chunk_by_ukey.values_mut() { - if let Some(name) = chunk.name() { - chunk.set_id(Some(name.to_owned())); + let more_chunks = if let Some(mutations) = compilation + .incremental + .mutations_read(IncrementalPasses::CHUNK_IDS) + { + let mut affected_chunks: UkeySet = UkeySet::default(); + for mutation in mutations.iter() { + match mutation { + Mutation::ChunkRemove { chunk } => { + compilation.chunk_ids.remove(chunk); + } + Mutation::ModuleSetId { module } => { + affected_chunks.extend(compilation.chunk_graph.get_module_chunks(*module)); + } + _ => {} + } } - } + compilation + .chunk_ids + .retain(|chunk, _| compilation.chunk_by_ukey.contains(chunk)); + affected_chunks + } else { + UkeySet::default() + }; - let mut used_ids = get_used_chunk_ids(compilation); - let chunk_graph = &compilation.chunk_graph; - let module_graph = compilation.get_module_graph(); - let context = self - .context - .clone() - .unwrap_or_else(|| compilation.options.context.to_string()); - let chunks = compilation + let mut chunks: UkeySet = compilation .chunk_by_ukey .values() - .filter(|chunk| chunk.id().is_none()) - .map(|chunk| chunk as &Chunk) - .collect::>(); - let mut chunk_id_to_name = HashMap::with_capacity(chunks.len()); - let unnamed_chunks = assign_names_par( + .filter(|chunk| chunk.id(&compilation.chunk_ids).is_none()) + .map(|chunk| chunk.ukey()) + .collect(); + chunks.extend(more_chunks); + let chunks_len = chunks.len(); + + let mut mutations = compilation + .incremental + .can_write_mutations() + .then(Mutations::default); + + // Use chunk name as default chunk id + chunks.retain(|chunk_ukey| { + let chunk = compilation.chunk_by_ukey.expect_get(chunk_ukey); + if let Some(chunk_name) = chunk.name() { + if ChunkGraph::set_chunk_id(&mut compilation.chunk_ids, *chunk_ukey, chunk_name.into()) + && let Some(mutations) = &mut mutations + { + mutations.add(Mutation::ChunkSetId { chunk: *chunk_ukey }); + } + return false; + } + true + }); + let named_chunks_len = chunks_len - chunks.len(); + + let mut chunk_ids = std::mem::take(&mut compilation.chunk_ids); + let mut used_ids: FxHashMap = chunk_ids + .iter() + .map(|(&chunk, id)| (id.clone(), chunk)) + .collect(); + + let unnamed_chunks = assign_named_chunk_ids( chunks, - |chunk| get_short_chunk_name(chunk, chunk_graph, &context, &self.delimiter, &module_graph), - |chunk, _| get_long_chunk_name(chunk, chunk_graph, &context, &self.delimiter, &module_graph), - |a, b| compare_chunks_natural(chunk_graph, &module_graph, &compilation.module_ids, a, b), + compilation, + &self.delimiter, &mut used_ids, - |chunk, name| { - chunk_id_to_name.insert(chunk.ukey(), name); - }, + &mut chunk_ids, + &mut mutations, ); - let unnamed_chunks = unnamed_chunks - .iter() - .map(|chunk| chunk.ukey()) - .collect::>(); + if !unnamed_chunks.is_empty() { + let mut next_id = 0; + for chunk_ukey in &unnamed_chunks { + let chunk = compilation.chunk_by_ukey.expect_get_mut(chunk_ukey); + let mut id = next_id.to_string(); + while used_ids.contains_key(id.as_str()) { + next_id += 1; + id = next_id.to_string(); + } + if chunk.set_id(&mut chunk_ids, id) + && let Some(mutations) = &mut mutations + { + mutations.add(Mutation::ChunkSetId { chunk: *chunk_ukey }); + } + next_id += 1; + } + } - chunk_id_to_name.into_iter().for_each(|(chunk_ukey, name)| { - let chunk = compilation.chunk_by_ukey.expect_get_mut(&chunk_ukey); - chunk.set_id(Some(name.clone())); - }); + if compilation + .incremental + .can_read_mutations(IncrementalPasses::CHUNK_IDS) + && let Some(mutations) = &mutations + { + let logger = compilation.get_logger("rspack.incremental.chunkIds"); + logger.log(format!( + "{} chunks are affected, {} in total", + chunks_len, + compilation.chunk_by_ukey.len(), + )); + logger.log(format!( + "{} chunks are updated by set_chunk_id, with {} chunks using name as id, and {} unnamed chunks", + mutations.len(), + named_chunks_len, + unnamed_chunks.len(), + )); + } - if !unnamed_chunks.is_empty() { - assign_ascending_chunk_ids(&unnamed_chunks, compilation) + if let Some(compilation_mutations) = compilation.incremental.mutations_write() + && let Some(mutations) = mutations + { + compilation_mutations.extend(mutations); } + compilation.chunk_ids = chunk_ids; Ok(()) } diff --git a/crates/rspack_ids/src/named_module_ids_plugin.rs b/crates/rspack_ids/src/named_module_ids_plugin.rs index 1b7bccb35f9..8029c3626ee 100644 --- a/crates/rspack_ids/src/named_module_ids_plugin.rs +++ b/crates/rspack_ids/src/named_module_ids_plugin.rs @@ -1,5 +1,3 @@ -use std::collections::{HashMap, HashSet}; - use rayon::iter::{IntoParallelIterator, ParallelBridge, ParallelIterator}; use rspack_collections::{IdentifierIndexSet, IdentifierMap, IdentifierSet}; use rspack_core::{ @@ -33,14 +31,17 @@ fn assign_named_module_ids( (item, name) }) .collect(); - let mut name_to_items: HashMap = HashMap::default(); + let mut name_to_items: FxHashMap = FxHashMap::default(); let mut invalid_and_repeat_names: FxHashSet = std::iter::once(String::new()).collect(); for (item, name) in item_name_pair { let items = name_to_items.entry(name.clone()).or_default(); items.insert(item); + // If the short module id is conflict, then we need to rename all the conflicting modules to long module id if items.len() > 1 { invalid_and_repeat_names.insert(name); - } else if let Some(item) = used_ids.get(name.as_str()) { + } + // Also rename the conflicting modules in used_ids + else if let Some(item) = used_ids.get(name.as_str()) { items.insert(*item); invalid_and_repeat_names.insert(name); } @@ -67,12 +68,13 @@ fn assign_named_module_ids( for (item, name) in item_name_pair { let items = name_to_items.entry(name.clone()).or_default(); items.insert(item); + // Also rename the conflicting modules in used_ids if let Some(item) = used_ids.get(name.as_str()) { items.insert(*item); } } - let name_to_items_keys = name_to_items.keys().cloned().collect::>(); + let name_to_items_keys = name_to_items.keys().cloned().collect::>(); let mut unnamed_items = vec![]; for (name, mut items) in name_to_items { @@ -187,9 +189,10 @@ fn module_ids(&self, compilation: &mut rspack_core::Compilation) -> Result<()> { if !unnamed_modules.is_empty() { let mut next_id = 0; for module in unnamed_modules { - let id = next_id.to_string(); + let mut id = next_id.to_string(); while used_ids.contains_key(id.as_str()) { next_id += 1; + id = next_id.to_string(); } if ChunkGraph::set_module_id(&mut module_ids, module, id.into()) && let Some(mutations) = &mut mutations diff --git a/crates/rspack_plugin_banner/src/lib.rs b/crates/rspack_plugin_banner/src/lib.rs index 354b6cbb69c..a6ca94191a3 100644 --- a/crates/rspack_plugin_banner/src/lib.rs +++ b/crates/rspack_plugin_banner/src/lib.rs @@ -192,8 +192,8 @@ async fn process_assets(&self, compilation: &mut Compilation) -> Result<()> { &compilation.chunk_hashes_results, compilation.options.output.hash_digest_length, )) - .chunk_id_optional(chunk.id()) - .chunk_name_optional(chunk.name_for_filename_template()) + .chunk_id_optional(chunk.id(&compilation.chunk_ids).map(|id| id.as_str())) + .chunk_name_optional(chunk.name_for_filename_template(&compilation.chunk_ids)) .hash(&hash) .filename(file), ) diff --git a/crates/rspack_plugin_css/src/plugin/impl_plugin_for_css_plugin.rs b/crates/rspack_plugin_css/src/plugin/impl_plugin_for_css_plugin.rs index 78ad2079c7a..ce64443b374 100644 --- a/crates/rspack_plugin_css/src/plugin/impl_plugin_for_css_plugin.rs +++ b/crates/rspack_plugin_css/src/plugin/impl_plugin_for_css_plugin.rs @@ -101,9 +101,12 @@ impl CssPlugin { "Conflicting order".into(), format!( "chunk {}\nConflicting order between {} and {}", - chunk - .name() - .unwrap_or(chunk.id().expect("should have chunk id")), + chunk.name().unwrap_or( + chunk + .id(&compilation.chunk_ids) + .expect("should have chunk id") + .as_str() + ), failed_module.readable_identifier(&compilation.options.context), selected_module.readable_identifier(&compilation.options.context) ), @@ -333,12 +336,12 @@ async fn render_manifest( let output_path = compilation.get_path_with_info( filename_template, PathData::default() - .chunk_id_optional(chunk.id()) + .chunk_id_optional(chunk.id(&compilation.chunk_ids).map(|id| id.as_str())) .chunk_hash_optional(chunk.rendered_hash( &compilation.chunk_hashes_results, compilation.options.output.hash_digest_length, )) - .chunk_name_optional(chunk.name_for_filename_template()) + .chunk_name_optional(chunk.name_for_filename_template(&compilation.chunk_ids)) .content_hash_optional(chunk.rendered_content_hash_by_source_type( &compilation.chunk_hashes_results, &SourceType::Css, diff --git a/crates/rspack_plugin_css/src/runtime/mod.rs b/crates/rspack_plugin_css/src/runtime/mod.rs index cf5e3a75043..a4ad4442a64 100644 --- a/crates/rspack_plugin_css/src/runtime/mod.rs +++ b/crates/rspack_plugin_css/src/runtime/mod.rs @@ -54,8 +54,8 @@ impl RuntimeModule for CssLoadingRuntimeModule { let id = compilation .chunk_by_ukey .expect_get(chunk_ukey) - .expect_id() - .to_string(); + .expect_id(&compilation.chunk_ids) + .clone(); if chunk_has_css(chunk_ukey, compilation) { initial_chunk_ids.insert(id); } diff --git a/crates/rspack_plugin_devtool/src/source_map_dev_tool_plugin.rs b/crates/rspack_plugin_devtool/src/source_map_dev_tool_plugin.rs index 6f30034eaa5..0c481d82932 100644 --- a/crates/rspack_plugin_devtool/src/source_map_dev_tool_plugin.rs +++ b/crates/rspack_plugin_devtool/src/source_map_dev_tool_plugin.rs @@ -423,12 +423,12 @@ impl SourceMapDevToolPlugin { let data = PathData::default().filename(&filename); let data = match chunk { Some(chunk) => data - .chunk_id_optional(chunk.id()) + .chunk_id_optional(chunk.id(&compilation.chunk_ids).map(|id| id.as_str())) .chunk_hash_optional(chunk.rendered_hash( &compilation.chunk_hashes_results, compilation.options.output.hash_digest_length, )) - .chunk_name_optional(chunk.name_for_filename_template()) + .chunk_name_optional(chunk.name_for_filename_template(&compilation.chunk_ids)) .content_hash_optional(Some(digest.encoded())), None => data, }; diff --git a/crates/rspack_plugin_dll/src/lib_manifest_plugin.rs b/crates/rspack_plugin_dll/src/lib_manifest_plugin.rs index 0a59f922c8f..0ec34663160 100644 --- a/crates/rspack_plugin_dll/src/lib_manifest_plugin.rs +++ b/crates/rspack_plugin_dll/src/lib_manifest_plugin.rs @@ -72,12 +72,12 @@ async fn emit(&self, compilation: &mut Compilation) -> Result<()> { let target_path = compilation.get_path( &self.options.path, PathData::default() - .chunk_id_optional(chunk.id()) + .chunk_id_optional(chunk.id(&compilation.chunk_ids).map(|id| id.as_str())) .chunk_hash_optional(chunk.rendered_hash( &compilation.chunk_hashes_results, compilation.options.output.hash_digest_length, )) - .chunk_name_optional(chunk.name_for_filename_template()), + .chunk_name_optional(chunk.name_for_filename_template(&compilation.chunk_ids)), )?; if use_paths.contains(&target_path) { @@ -91,12 +91,12 @@ async fn emit(&self, compilation: &mut Compilation) -> Result<()> { .get_path( name, PathData::default() - .chunk_id_optional(chunk.id()) + .chunk_id_optional(chunk.id(&compilation.chunk_ids).map(|id| id.as_str())) .chunk_hash_optional(chunk.rendered_hash( &compilation.chunk_hashes_results, compilation.options.output.hash_digest_length, )) - .chunk_name_optional(chunk.name_for_filename_template()) + .chunk_name_optional(chunk.name_for_filename_template(&compilation.chunk_ids)) .content_hash_optional(chunk.rendered_content_hash_by_source_type( &compilation.chunk_hashes_results, &SourceType::JavaScript, diff --git a/crates/rspack_plugin_extract_css/src/plugin.rs b/crates/rspack_plugin_extract_css/src/plugin.rs index 0770ab305dd..e64f2b92baf 100644 --- a/crates/rspack_plugin_extract_css/src/plugin.rs +++ b/crates/rspack_plugin_extract_css/src/plugin.rs @@ -328,7 +328,10 @@ Conflicting order. Following module has been added: * {} despite it was not able to fulfill desired ordering with these modules: {}"#, - chunk.name().unwrap_or(chunk.id().unwrap_or_default()), + chunk + .name() + .or_else(|| chunk.id(&compilation.chunk_ids).map(|id| id.as_str())) + .unwrap_or_default(), fallback_module.readable_identifier(&compilation.options.context), conflict .reasons @@ -619,12 +622,12 @@ async fn render_manifest( let filename = compilation.get_path_with_info( filename_template, PathData::default() - .chunk_id_optional(chunk.id()) + .chunk_id_optional(chunk.id(&compilation.chunk_ids).map(|id| id.as_str())) .chunk_hash_optional(chunk.rendered_hash( &compilation.chunk_hashes_results, compilation.options.output.hash_digest_length, )) - .chunk_name_optional(chunk.name_for_filename_template()) + .chunk_name_optional(chunk.name_for_filename_template(&compilation.chunk_ids)) .content_hash_optional(chunk.rendered_content_hash_by_source_type( &compilation.chunk_hashes_results, &SOURCE_TYPE[0], diff --git a/crates/rspack_plugin_extract_css/src/runtime.rs b/crates/rspack_plugin_extract_css/src/runtime.rs index 8045f5309a1..ba777b5319b 100644 --- a/crates/rspack_plugin_extract_css/src/runtime.rs +++ b/crates/rspack_plugin_extract_css/src/runtime.rs @@ -153,7 +153,8 @@ impl RuntimeModule for CssLoadingRuntimeModule { "__INSTALLED_CHUNKS__", &format!( "{}: 0,\n", - serde_json::to_string(chunk.expect_id()).expect("json stringify failed") + serde_json::to_string(chunk.expect_id(&compilation.chunk_ids)) + .expect("json stringify failed") ), ); @@ -171,7 +172,7 @@ impl RuntimeModule for CssLoadingRuntimeModule { .filter_map(|id| { let chunk = compilation.chunk_by_ukey.expect_get(id); - chunk.id().map(|id| { + chunk.id(&compilation.chunk_ids).map(|id| { format!( "{}: 1,\n", serde_json::to_string(id).expect("json stringify failed") diff --git a/crates/rspack_plugin_hmr/src/lib.rs b/crates/rspack_plugin_hmr/src/lib.rs index bb813b9bbbd..b6568886808 100644 --- a/crates/rspack_plugin_hmr/src/lib.rs +++ b/crates/rspack_plugin_hmr/src/lib.rs @@ -6,6 +6,7 @@ use async_trait::async_trait; use hot_module_replacement::HotModuleReplacementRuntimeModule; use rspack_collections::{DatabaseItem, IdentifierSet, UkeyMap}; use rspack_core::{ + chunk_graph_chunk::ChunkId, collect_changed_modules, rspack_sources::{RawStringSource, SourceExt}, ApplyContext, AssetInfo, Chunk, ChunkKind, ChunkUkey, Compilation, @@ -135,18 +136,18 @@ async fn process_assets(&self, compilation: &mut Compilation) -> Result<()> { for (chunk_id, old_runtime) in &old_chunks { let mut new_modules = vec![]; let mut new_runtime_modules = vec![]; - let mut chunk_id = chunk_id.to_string(); + let mut chunk_id = chunk_id.clone(); let mut new_runtime = all_old_runtime.clone(); let mut removed_from_runtime = all_old_runtime.clone(); let current_chunk = compilation .chunk_by_ukey .iter() - .find(|(_, chunk)| chunk.expect_id().eq(&chunk_id)) + .find(|(_, chunk)| chunk.expect_id(&compilation.chunk_ids).eq(&chunk_id)) .map(|(_, chunk)| chunk); let current_chunk_ukey = current_chunk.map(|c| c.ukey()); if let Some(current_chunk) = current_chunk { - chunk_id = current_chunk.expect_id().to_string(); + chunk_id = current_chunk.expect_id(&compilation.chunk_ids).clone(); new_runtime = Default::default(); // intersectRuntime for old_runtime in all_old_runtime.iter() { @@ -182,7 +183,7 @@ async fn process_assets(&self, compilation: &mut Compilation) -> Result<()> { for removed in removed_from_runtime { if let Some(info) = hot_update_main_content_by_runtime.get_mut(removed.as_ref()) { - info.removed_chunk_ids.insert(chunk_id.to_string()); + info.removed_chunk_ids.insert(chunk_id.clone()); } // TODO: // for (const module of remainingModules) {} @@ -190,7 +191,7 @@ async fn process_assets(&self, compilation: &mut Compilation) -> Result<()> { if !new_modules.is_empty() || !new_runtime_modules.is_empty() { let mut hot_update_chunk = Chunk::new(None, ChunkKind::HotUpdate); - hot_update_chunk.set_id(Some(chunk_id.to_string())); + hot_update_chunk.set_id(&mut compilation.chunk_ids, chunk_id.clone()); hot_update_chunk.set_runtime(if let Some(current_chunk) = current_chunk { current_chunk.runtime().clone() } else { @@ -265,8 +266,14 @@ async fn process_assets(&self, compilation: &mut Compilation) -> Result<()> { .get_path( &compilation.options.output.hot_update_chunk_filename, PathData::default() - .chunk_id_optional(hot_update_chunk.id()) - .chunk_name_optional(hot_update_chunk.name_for_filename_template()) + .chunk_id_optional( + hot_update_chunk + .id(&compilation.chunk_ids) + .map(|id| id.as_str()), + ) + .chunk_name_optional( + hot_update_chunk.name_for_filename_template(&compilation.chunk_ids), + ) .hash_optional( old_hash .as_ref() @@ -294,7 +301,7 @@ async fn process_assets(&self, compilation: &mut Compilation) -> Result<()> { new_runtime.iter().for_each(|runtime| { if let Some(info) = hot_update_main_content_by_runtime.get_mut(runtime.as_ref()) { - info.updated_chunk_ids.insert(chunk_id.to_string()); + info.updated_chunk_ids.insert(chunk_id.clone()); } }); } @@ -312,8 +319,8 @@ async fn process_assets(&self, compilation: &mut Compilation) -> Result<()> { completely_removed_modules.into_iter().collect(); for (_, content) in hot_update_main_content_by_runtime { - let c: Vec = content.updated_chunk_ids.into_iter().collect(); - let r: Vec = content.removed_chunk_ids.into_iter().collect(); + let c: Vec = content.updated_chunk_ids.into_iter().collect(); + let r: Vec = content.removed_chunk_ids.into_iter().collect(); let m: Vec = completely_removed_modules_array .iter() .map(|x| x.to_owned()) @@ -445,8 +452,8 @@ impl Plugin for HotModuleReplacementPlugin { #[derive(Default)] struct HotUpdateContent { runtime: RuntimeSpec, - updated_chunk_ids: HashSet, - removed_chunk_ids: HashSet, + updated_chunk_ids: HashSet, + removed_chunk_ids: HashSet, _removed_modules: IdentifierSet, } diff --git a/crates/rspack_plugin_javascript/src/dependency/worker/mod.rs b/crates/rspack_plugin_javascript/src/dependency/worker/mod.rs index a2c81eb9663..cc2b19b2ff7 100644 --- a/crates/rspack_plugin_javascript/src/dependency/worker/mod.rs +++ b/crates/rspack_plugin_javascript/src/dependency/worker/mod.rs @@ -103,7 +103,7 @@ impl DependencyTemplate for WorkerDependency { }) .map(|entrypoint| entrypoint.get_entry_point_chunk()) .and_then(|ukey| compilation.chunk_by_ukey.get(&ukey)) - .and_then(|chunk| chunk.id()) + .and_then(|chunk| chunk.id(&compilation.chunk_ids)) .and_then(|chunk_id| serde_json::to_string(chunk_id).ok()) .expect("failed to get json stringified chunk id"); let worker_import_base_url = if !self.public_path.is_empty() { diff --git a/crates/rspack_plugin_javascript/src/plugin/impl_plugin_for_js_plugin.rs b/crates/rspack_plugin_javascript/src/plugin/impl_plugin_for_js_plugin.rs index 376869e7b83..fc95fe1f692 100644 --- a/crates/rspack_plugin_javascript/src/plugin/impl_plugin_for_js_plugin.rs +++ b/crates/rspack_plugin_javascript/src/plugin/impl_plugin_for_js_plugin.rs @@ -184,7 +184,7 @@ async fn content_hash( if chunk.has_runtime(&compilation.chunk_group_by_ukey) { self.update_hash_with_bootstrap(chunk_ukey, compilation, hasher)?; } else { - chunk.id().hash(&mut hasher); + chunk.id(&compilation.chunk_ids).hash(&mut hasher); } self.get_chunk_hash(chunk_ukey, compilation, hasher).await?; @@ -280,8 +280,8 @@ async fn render_manifest( &compilation.chunk_hashes_results, compilation.options.output.hash_digest_length, )) - .chunk_id_optional(chunk.id()) - .chunk_name_optional(chunk.name_for_filename_template()) + .chunk_id_optional(chunk.id(&compilation.chunk_ids).map(|id| id.as_str())) + .chunk_name_optional(chunk.name_for_filename_template(&compilation.chunk_ids)) .content_hash_optional(chunk.rendered_content_hash_by_source_type( &compilation.chunk_hashes_results, &SourceType::JavaScript, diff --git a/crates/rspack_plugin_javascript/src/plugin/mod.rs b/crates/rspack_plugin_javascript/src/plugin/mod.rs index 2a4e3551c3c..3b0c95c88eb 100644 --- a/crates/rspack_plugin_javascript/src/plugin/mod.rs +++ b/crates/rspack_plugin_javascript/src/plugin/mod.rs @@ -301,7 +301,7 @@ impl JsPlugin { compilation .chunk_by_ukey .expect_get(chunk_ukey) - .expect_id() + .expect_id(&compilation.chunk_ids) .to_string() }) .collect::>(); diff --git a/crates/rspack_plugin_javascript/src/runtime.rs b/crates/rspack_plugin_javascript/src/runtime.rs index 04cedd53fc8..40d2a04b2dc 100644 --- a/crates/rspack_plugin_javascript/src/runtime.rs +++ b/crates/rspack_plugin_javascript/src/runtime.rs @@ -1,4 +1,5 @@ use rayon::prelude::*; +use rspack_core::chunk_graph_chunk::ChunkId; use rspack_core::rspack_sources::{BoxSource, ConcatSource, RawStringSource, SourceExt}; use rspack_core::{ to_normal_comment, BoxModule, ChunkGraph, ChunkInitFragments, ChunkUkey, Compilation, @@ -253,7 +254,7 @@ pub fn render_runtime_modules( Ok(sources.boxed()) } -pub fn stringify_chunks_to_array(chunks: &HashSet) -> String { +pub fn stringify_chunks_to_array(chunks: &HashSet) -> String { let mut v = Vec::from_iter(chunks.iter()); v.sort_unstable(); diff --git a/crates/rspack_plugin_library/src/amd_library_plugin.rs b/crates/rspack_plugin_library/src/amd_library_plugin.rs index faea6c7d818..95c206b1a5c 100644 --- a/crates/rspack_plugin_library/src/amd_library_plugin.rs +++ b/crates/rspack_plugin_library/src/amd_library_plugin.rs @@ -133,12 +133,12 @@ fn render( .get_path( &FilenameTemplate::from(name.to_string()), PathData::default() - .chunk_id_optional(chunk.id()) + .chunk_id_optional(chunk.id(&compilation.chunk_ids).map(|id| id.as_str())) .chunk_hash_optional(chunk.rendered_hash( &compilation.chunk_hashes_results, compilation.options.output.hash_digest_length, )) - .chunk_name_optional(chunk.name_for_filename_template()) + .chunk_name_optional(chunk.name_for_filename_template(&compilation.chunk_ids)) .content_hash_optional(chunk.rendered_content_hash_by_source_type( &compilation.chunk_hashes_results, &SourceType::JavaScript, diff --git a/crates/rspack_plugin_library/src/assign_library_plugin.rs b/crates/rspack_plugin_library/src/assign_library_plugin.rs index 3041d001541..6c1af3e1987 100644 --- a/crates/rspack_plugin_library/src/assign_library_plugin.rs +++ b/crates/rspack_plugin_library/src/assign_library_plugin.rs @@ -158,12 +158,12 @@ impl AssignLibraryPlugin { .get_path( &FilenameTemplate::from(v.to_owned()), PathData::default() - .chunk_id_optional(chunk.id()) + .chunk_id_optional(chunk.id(&compilation.chunk_ids).map(|id| id.as_str())) .chunk_hash_optional(chunk.rendered_hash( &compilation.chunk_hashes_results, compilation.options.output.hash_digest_length, )) - .chunk_name_optional(chunk.name_for_filename_template()) + .chunk_name_optional(chunk.name_for_filename_template(&compilation.chunk_ids)) .content_hash_optional(chunk.rendered_content_hash_by_source_type( &compilation.chunk_hashes_results, &SourceType::JavaScript, diff --git a/crates/rspack_plugin_library/src/umd_library_plugin.rs b/crates/rspack_plugin_library/src/umd_library_plugin.rs index 2c3ca4e448f..2d3dd4b77a6 100644 --- a/crates/rspack_plugin_library/src/umd_library_plugin.rs +++ b/crates/rspack_plugin_library/src/umd_library_plugin.rs @@ -306,12 +306,12 @@ fn replace_keys(v: String, chunk: &Chunk, compilation: &Compilation) -> String { .get_path( &FilenameTemplate::from(v), PathData::default() - .chunk_id_optional(chunk.id()) + .chunk_id_optional(chunk.id(&compilation.chunk_ids).map(|id| id.as_str())) .chunk_hash_optional(chunk.rendered_hash( &compilation.chunk_hashes_results, compilation.options.output.hash_digest_length, )) - .chunk_name_optional(chunk.name_for_filename_template()) + .chunk_name_optional(chunk.name_for_filename_template(&compilation.chunk_ids)) .content_hash_optional(chunk.rendered_content_hash_by_source_type( &compilation.chunk_hashes_results, &SourceType::JavaScript, diff --git a/crates/rspack_plugin_mf/src/container/remote_runtime_module.rs b/crates/rspack_plugin_mf/src/container/remote_runtime_module.rs index 6f75d59fad5..e1098aeb223 100644 --- a/crates/rspack_plugin_mf/src/container/remote_runtime_module.rs +++ b/crates/rspack_plugin_mf/src/container/remote_runtime_module.rs @@ -83,7 +83,7 @@ impl RuntimeModule for RemoteRuntimeModule { let chunk = compilation.chunk_by_ukey.expect_get(&chunk); chunk_to_remotes_mapping.insert( chunk - .id() + .id(&compilation.chunk_ids) .expect("should have chunkId at ::generate"), remotes, ); diff --git a/crates/rspack_plugin_mf/src/sharing/consume_shared_runtime_module.rs b/crates/rspack_plugin_mf/src/sharing/consume_shared_runtime_module.rs index fea5282aac3..90f499bd224 100644 --- a/crates/rspack_plugin_mf/src/sharing/consume_shared_runtime_module.rs +++ b/crates/rspack_plugin_mf/src/sharing/consume_shared_runtime_module.rs @@ -86,7 +86,7 @@ impl RuntimeModule for ConsumeSharedRuntimeModule { } chunk_to_module_mapping.insert( chunk - .id() + .id(&compilation.chunk_ids) .map(ToOwned::to_owned) .expect("should have chunkId at ::generate"), ids, diff --git a/crates/rspack_plugin_runtime/src/array_push_callback_chunk_format.rs b/crates/rspack_plugin_runtime/src/array_push_callback_chunk_format.rs index 5ea7bd1a881..9f5b955e087 100644 --- a/crates/rspack_plugin_runtime/src/array_push_callback_chunk_format.rs +++ b/crates/rspack_plugin_runtime/src/array_push_callback_chunk_format.rs @@ -112,7 +112,7 @@ fn render_chunk( "{}[{}]('{}', ", global_object, serde_json::to_string(hot_update_global).map_err(|e| error!(e.to_string()))?, - chunk.expect_id() + chunk.expect_id(&compilation.chunk_ids) ))); source.add(render_source.source.clone()); if has_runtime_modules { @@ -129,7 +129,8 @@ fn render_chunk( chunk_loading_global, global_object, chunk_loading_global, - serde_json::to_string(chunk.expect_id()).expect("json stringify failed"), + serde_json::to_string(chunk.expect_id(&compilation.chunk_ids)) + .expect("json stringify failed"), ))); source.add(render_source.source.clone()); let has_entry = chunk.has_entry_module(&compilation.chunk_graph); diff --git a/crates/rspack_plugin_runtime/src/common_js_chunk_format.rs b/crates/rspack_plugin_runtime/src/common_js_chunk_format.rs index 9e96433ef8d..b83edc02798 100644 --- a/crates/rspack_plugin_runtime/src/common_js_chunk_format.rs +++ b/crates/rspack_plugin_runtime/src/common_js_chunk_format.rs @@ -102,7 +102,7 @@ fn render_chunk( let mut sources = ConcatSource::default(); sources.add(RawStringSource::from(format!( "exports.ids = ['{}'];\n", - &chunk.expect_id().to_string() + &chunk.expect_id(&compilation.chunk_ids) ))); sources.add(RawStringSource::from_static("exports.modules = ")); sources.add(render_source.source.clone()); diff --git a/crates/rspack_plugin_runtime/src/helpers.rs b/crates/rspack_plugin_runtime/src/helpers.rs index 63a2180605b..1e39030a408 100644 --- a/crates/rspack_plugin_runtime/src/helpers.rs +++ b/crates/rspack_plugin_runtime/src/helpers.rs @@ -41,7 +41,7 @@ pub fn update_hash_for_entry_startup( &compilation.chunk_group_by_ukey, ) { if let Some(chunk) = compilation.chunk_by_ukey.get(&chunk_ukey) { - chunk.id().hash(hasher); + chunk.id(&compilation.chunk_ids).hash(hasher); } } } @@ -174,7 +174,7 @@ pub fn generate_entry_startup( .iter() .map(|chunk_ukey| { let chunk = compilation.chunk_by_ukey.expect_get(chunk_ukey); - chunk.expect_id().to_string() + chunk.expect_id(&compilation.chunk_ids).clone() }) .collect::>(), ); @@ -258,12 +258,12 @@ pub fn get_chunk_output_name(chunk: &Chunk, compilation: &Compilation) -> Result compilation.get_path( &filename, PathData::default() - .chunk_id_optional(chunk.id()) + .chunk_id_optional(chunk.id(&compilation.chunk_ids).map(|id| id.as_str())) .chunk_hash_optional(chunk.rendered_hash( &compilation.chunk_hashes_results, compilation.options.output.hash_digest_length, )) - .chunk_name_optional(chunk.name_for_filename_template()) + .chunk_name_optional(chunk.name_for_filename_template(&compilation.chunk_ids)) .content_hash_optional(chunk.rendered_content_hash_by_source_type( &compilation.chunk_hashes_results, &SourceType::JavaScript, diff --git a/crates/rspack_plugin_runtime/src/module_chunk_format.rs b/crates/rspack_plugin_runtime/src/module_chunk_format.rs index 3268d4f1e77..7c19901177d 100644 --- a/crates/rspack_plugin_runtime/src/module_chunk_format.rs +++ b/crates/rspack_plugin_runtime/src/module_chunk_format.rs @@ -109,7 +109,7 @@ fn render_chunk( let mut sources = ConcatSource::default(); sources.add(RawStringSource::from(format!( "export const ids = ['{}'];\n", - &chunk.expect_id().to_string() + &chunk.expect_id(&compilation.chunk_ids) ))); sources.add(RawStringSource::from_static("export const modules = ")); sources.add(render_source.source.clone()); diff --git a/crates/rspack_plugin_runtime/src/runtime_module/auto_public_path.rs b/crates/rspack_plugin_runtime/src/runtime_module/auto_public_path.rs index cdb57bc046a..3eadf917650 100644 --- a/crates/rspack_plugin_runtime/src/runtime_module/auto_public_path.rs +++ b/crates/rspack_plugin_runtime/src/runtime_module/auto_public_path.rs @@ -45,12 +45,12 @@ impl RuntimeModule for AutoPublicPathRuntimeModule { let filename = compilation.get_path( &filename, PathData::default() - .chunk_id_optional(chunk.id()) + .chunk_id_optional(chunk.id(&compilation.chunk_ids).map(|id| id.as_str())) .chunk_hash_optional(chunk.rendered_hash( &compilation.chunk_hashes_results, compilation.options.output.hash_digest_length, )) - .chunk_name_optional(chunk.name_for_filename_template()) + .chunk_name_optional(chunk.name_for_filename_template(&compilation.chunk_ids)) .content_hash_optional(chunk.rendered_content_hash_by_source_type( &compilation.chunk_hashes_results, &SourceType::JavaScript, diff --git a/crates/rspack_plugin_runtime/src/runtime_module/chunk_prefetch_startup.rs b/crates/rspack_plugin_runtime/src/runtime_module/chunk_prefetch_startup.rs index a90df2a8d00..e14e69c022b 100644 --- a/crates/rspack_plugin_runtime/src/runtime_module/chunk_prefetch_startup.rs +++ b/crates/rspack_plugin_runtime/src/runtime_module/chunk_prefetch_startup.rs @@ -45,7 +45,10 @@ impl RuntimeModule for ChunkPrefetchStartupRuntimeModule { .iter() .filter_map(|c| { if c.to_owned().eq(&chunk_ukey) { - compilation.chunk_by_ukey.expect_get(c).id().to_owned() + compilation + .chunk_by_ukey + .expect_get(c) + .id(&compilation.chunk_ids) } else { None } @@ -54,7 +57,12 @@ impl RuntimeModule for ChunkPrefetchStartupRuntimeModule { let child_chunk_ids = child_chunks .iter() - .filter_map(|c| compilation.chunk_by_ukey.expect_get(c).id().to_owned()) + .filter_map(|c| { + compilation + .chunk_by_ukey + .expect_get(c) + .id(&compilation.chunk_ids) + }) .collect_vec(); let body = match child_chunks.len() { diff --git a/crates/rspack_plugin_runtime/src/runtime_module/chunk_prefetch_trigger.rs b/crates/rspack_plugin_runtime/src/runtime_module/chunk_prefetch_trigger.rs index 9743a087fab..f68c697740e 100644 --- a/crates/rspack_plugin_runtime/src/runtime_module/chunk_prefetch_trigger.rs +++ b/crates/rspack_plugin_runtime/src/runtime_module/chunk_prefetch_trigger.rs @@ -5,6 +5,7 @@ use indexmap::IndexMap; use rspack_cacheable::with::AsMap; use rspack_collections::Identifier; use rspack_core::{ + chunk_graph_chunk::ChunkId, impl_runtime_module, rspack_sources::{BoxSource, RawStringSource, SourceExt}, Compilation, RuntimeModule, RuntimeModuleStage, @@ -16,11 +17,11 @@ use rustc_hash::FxHasher; pub struct ChunkPrefetchTriggerRuntimeModule { id: Identifier, #[cacheable(with=AsMap)] - chunk_map: IndexMap, BuildHasherDefault>, + chunk_map: IndexMap, BuildHasherDefault>, } impl ChunkPrefetchTriggerRuntimeModule { - pub fn new(chunk_map: IndexMap, BuildHasherDefault>) -> Self { + pub fn new(chunk_map: IndexMap, BuildHasherDefault>) -> Self { Self::with_default( Identifier::from("webpack/runtime/chunk_prefetch_trigger"), chunk_map, diff --git a/crates/rspack_plugin_runtime/src/runtime_module/chunk_preload_trigger.rs b/crates/rspack_plugin_runtime/src/runtime_module/chunk_preload_trigger.rs index eea026a7059..51137b01df8 100644 --- a/crates/rspack_plugin_runtime/src/runtime_module/chunk_preload_trigger.rs +++ b/crates/rspack_plugin_runtime/src/runtime_module/chunk_preload_trigger.rs @@ -5,6 +5,7 @@ use indexmap::IndexMap; use rspack_cacheable::with::AsMap; use rspack_collections::Identifier; use rspack_core::{ + chunk_graph_chunk::ChunkId, impl_runtime_module, rspack_sources::{BoxSource, RawStringSource, SourceExt}, Compilation, RuntimeModule, RuntimeModuleStage, @@ -16,11 +17,11 @@ use rustc_hash::FxHasher; pub struct ChunkPreloadTriggerRuntimeModule { id: Identifier, #[cacheable(with=AsMap)] - chunk_map: IndexMap, BuildHasherDefault>, + chunk_map: IndexMap, BuildHasherDefault>, } impl ChunkPreloadTriggerRuntimeModule { - pub fn new(chunk_map: IndexMap, BuildHasherDefault>) -> Self { + pub fn new(chunk_map: IndexMap, BuildHasherDefault>) -> Self { Self::with_default( Identifier::from("webpack/runtime/chunk_preload_trigger"), chunk_map, diff --git a/crates/rspack_plugin_runtime/src/runtime_module/get_chunk_filename.rs b/crates/rspack_plugin_runtime/src/runtime_module/get_chunk_filename.rs index e97dff98a22..db090a175ab 100644 --- a/crates/rspack_plugin_runtime/src/runtime_module/get_chunk_filename.rs +++ b/crates/rspack_plugin_runtime/src/runtime_module/get_chunk_filename.rs @@ -179,12 +179,13 @@ impl RuntimeModule for GetChunkFilenameRuntimeModule { let chunk_id = "\" + chunkId + \""; let chunk_name = stringify_dynamic_chunk_map( - |c| match c.name() { - Some(name) => Some(name.to_string()), - None => c.id().map(|id| id.to_string()), + |c| { + c.name_for_filename_template(&compilation.chunk_ids) + .map(|s| s.to_string()) }, &chunks, &chunk_map, + compilation, ); let chunk_hash = stringify_dynamic_chunk_map( |c| { @@ -201,6 +202,7 @@ impl RuntimeModule for GetChunkFilenameRuntimeModule { }, &chunks, &chunk_map, + compilation, ); let content_hash = stringify_dynamic_chunk_map( |c| { @@ -216,6 +218,7 @@ impl RuntimeModule for GetChunkFilenameRuntimeModule { }, &chunks, &chunk_map, + compilation, ); let full_hash = match hash_len_map .get("[fullhash]") @@ -257,13 +260,16 @@ impl RuntimeModule for GetChunkFilenameRuntimeModule { let (fake_filename, hash_len_map) = get_filename_without_hash_length(filename_template); let chunk_id = chunk - .id() - .map(|chunk_id| unquoted_stringify(chunk, chunk_id)); + .id(&compilation.chunk_ids) + .map(|chunk_id| unquoted_stringify(Some(chunk_id), chunk_id.as_str())); let chunk_name = match chunk.name() { - Some(chunk_name) => Some(unquoted_stringify(chunk, chunk_name)), + Some(chunk_name) => Some(unquoted_stringify( + chunk.id(&compilation.chunk_ids), + chunk_name, + )), None => chunk - .id() - .map(|chunk_id| unquoted_stringify(chunk, chunk_id)), + .id(&compilation.chunk_ids) + .map(|chunk_id| unquoted_stringify(Some(chunk_id), chunk_id.as_str())), }; let chunk_hash = chunk .rendered_hash( @@ -271,7 +277,7 @@ impl RuntimeModule for GetChunkFilenameRuntimeModule { compilation.options.output.hash_digest_length, ) .map(|chunk_hash| { - let hash = unquoted_stringify(chunk, chunk_hash); + let hash = unquoted_stringify(chunk.id(&compilation.chunk_ids), chunk_hash); match hash_len_map.get("[chunkhash]") { Some(hash_len) => hash[..*hash_len].to_string(), None => hash, @@ -282,7 +288,7 @@ impl RuntimeModule for GetChunkFilenameRuntimeModule { .and_then(|content_hash| content_hash.get(&self.source_type)) .map(|i| { let hash = unquoted_stringify( - chunk, + chunk.id(&compilation.chunk_ids), i.rendered(compilation.options.output.hash_digest_length), ); match hash_len_map.get("[contenthash]") { @@ -310,7 +316,7 @@ impl RuntimeModule for GetChunkFilenameRuntimeModule { .render( PathData::default() .chunk_name_optional(chunk.name()) - .chunk_id_optional(chunk.id()), + .chunk_id_optional(chunk.id(&compilation.chunk_ids).map(|id| id.as_str())), None, )? .as_str(), @@ -326,11 +332,11 @@ impl RuntimeModule for GetChunkFilenameRuntimeModule { ) .always_ok(); - if let Some(chunk_id) = chunk.id() { + if let Some(chunk_id) = chunk.id(&compilation.chunk_ids) { static_urls .entry(filename) .or_insert(Vec::new()) - .push(chunk_id); + .push(chunk_id.as_str()); } } } diff --git a/crates/rspack_plugin_runtime/src/runtime_module/get_chunk_update_filename.rs b/crates/rspack_plugin_runtime/src/runtime_module/get_chunk_update_filename.rs index f2af566d3ed..3640d2f98d4 100644 --- a/crates/rspack_plugin_runtime/src/runtime_module/get_chunk_update_filename.rs +++ b/crates/rspack_plugin_runtime/src/runtime_module/get_chunk_update_filename.rs @@ -38,7 +38,7 @@ impl RuntimeModule for GetChunkUpdateFilenameRuntimeModule { &compilation.chunk_hashes_results, compilation.options.output.hash_digest_length, )) - .chunk_name_optional(chunk.name_for_filename_template()) + .chunk_name_optional(chunk.name_for_filename_template(&compilation.chunk_ids)) .content_hash_optional(chunk.rendered_content_hash_by_source_type( &compilation.chunk_hashes_results, &SourceType::JavaScript, diff --git a/crates/rspack_plugin_runtime/src/runtime_module/get_main_filename.rs b/crates/rspack_plugin_runtime/src/runtime_module/get_main_filename.rs index 1ac149b50e9..1e082d1b9a5 100644 --- a/crates/rspack_plugin_runtime/src/runtime_module/get_main_filename.rs +++ b/crates/rspack_plugin_runtime/src/runtime_module/get_main_filename.rs @@ -36,12 +36,12 @@ impl RuntimeModule for GetMainFilenameRuntimeModule { let filename = compilation.get_path( &self.filename, PathData::default() - .chunk_id_optional(chunk.id()) + .chunk_id_optional(chunk.id(&compilation.chunk_ids).map(|id| id.as_str())) .chunk_hash_optional(chunk.rendered_hash( &compilation.chunk_hashes_results, compilation.options.output.hash_digest_length, )) - .chunk_name_optional(chunk.name_for_filename_template()) + .chunk_name_optional(chunk.name_for_filename_template(&compilation.chunk_ids)) .content_hash_optional(chunk.rendered_content_hash_by_source_type( &compilation.chunk_hashes_results, &SourceType::JavaScript, diff --git a/crates/rspack_plugin_runtime/src/runtime_module/startup_chunk_dependencies.rs b/crates/rspack_plugin_runtime/src/runtime_module/startup_chunk_dependencies.rs index d33c15591e3..f453454435e 100644 --- a/crates/rspack_plugin_runtime/src/runtime_module/startup_chunk_dependencies.rs +++ b/crates/rspack_plugin_runtime/src/runtime_module/startup_chunk_dependencies.rs @@ -44,7 +44,7 @@ impl RuntimeModule for StartupChunkDependenciesRuntimeModule { compilation .chunk_by_ukey .expect_get(&chunk_ukey) - .expect_id() + .expect_id(&compilation.chunk_ids) .to_string() }) .collect::>(); diff --git a/crates/rspack_plugin_runtime/src/runtime_module/utils.rs b/crates/rspack_plugin_runtime/src/runtime_module/utils.rs index a386e1a77a6..c8853c1a247 100644 --- a/crates/rspack_plugin_runtime/src/runtime_module/utils.rs +++ b/crates/rspack_plugin_runtime/src/runtime_module/utils.rs @@ -2,8 +2,8 @@ use cow_utils::CowUtils; use itertools::Itertools; use rspack_collections::{UkeyIndexMap, UkeyIndexSet}; use rspack_core::{ - get_js_chunk_filename_template, stringify_map, Chunk, ChunkLoading, ChunkUkey, Compilation, - PathData, SourceType, + chunk_graph_chunk::ChunkId, get_js_chunk_filename_template, Chunk, ChunkLoading, ChunkUkey, + Compilation, PathData, SourceType, }; use rspack_util::test::{ HOT_TEST_ACCEPT, HOT_TEST_DISPOSE, HOT_TEST_OUTDATED, HOT_TEST_RUNTIME, HOT_TEST_UPDATED, @@ -14,7 +14,7 @@ pub fn get_initial_chunk_ids( chunk: Option, compilation: &Compilation, filter_fn: impl Fn(&ChunkUkey, &Compilation) -> bool, -) -> HashSet { +) -> HashSet { match chunk { Some(chunk_ukey) => match compilation.chunk_by_ukey.get(&chunk_ukey) { Some(chunk) => { @@ -24,10 +24,10 @@ pub fn get_initial_chunk_ids( .filter(|key| !(chunk_ukey.eq(key) || filter_fn(key, compilation))) .map(|chunk_ukey| { let chunk = compilation.chunk_by_ukey.expect_get(chunk_ukey); - chunk.expect_id().to_string() + chunk.expect_id(&compilation.chunk_ids).clone() }) .collect::>(); - js_chunks.insert(chunk.expect_id().to_string()); + js_chunks.insert(chunk.expect_id(&compilation.chunk_ids).clone()); js_chunks } None => HashSet::default(), @@ -36,7 +36,7 @@ pub fn get_initial_chunk_ids( } } -pub fn stringify_chunks(chunks: &HashSet, value: u8) -> String { +pub fn stringify_chunks(chunks: &HashSet, value: u8) -> String { let mut v = Vec::from_iter(chunks.iter()); v.sort_unstable(); @@ -130,12 +130,12 @@ pub fn get_output_dir( let output_dir = compilation.get_path( &filename, PathData::default() - .chunk_id_optional(chunk.id()) + .chunk_id_optional(chunk.id(&compilation.chunk_ids).map(|id| id.as_str())) .chunk_hash_optional(chunk.rendered_hash( &compilation.chunk_hashes_results, compilation.options.output.hash_digest_length, )) - .chunk_name_optional(chunk.name_for_filename_template()) + .chunk_name_optional(chunk.name_for_filename_template(&compilation.chunk_ids)) .content_hash_optional(chunk.rendered_content_hash_by_source_type( &compilation.chunk_hashes_results, &SourceType::JavaScript, @@ -163,9 +163,9 @@ pub fn is_enabled_for_chunk( chunk_loading == expected } -pub fn unquoted_stringify(chunk: &Chunk, str: &str) -> String { - if let Some(chunk_id) = chunk.id() { - if str.len() >= 5 && str == chunk_id { +pub fn unquoted_stringify(chunk_id: Option<&ChunkId>, str: &str) -> String { + if let Some(chunk_id) = chunk_id { + if str.len() >= 5 && str == chunk_id.as_str() { return "\" + chunkId + \"".to_string(); } } @@ -177,6 +177,7 @@ pub fn stringify_dynamic_chunk_map( f: F, chunks: &UkeyIndexSet, chunk_map: &UkeyIndexMap, + compilation: &Compilation, ) -> String where F: Fn(&Chunk) -> Option, @@ -188,16 +189,16 @@ where for chunk_ukey in chunks.iter() { if let Some(chunk) = chunk_map.get(chunk_ukey) { - if let Some(chunk_id) = chunk.id() { + if let Some(chunk_id) = chunk.id(&compilation.chunk_ids) { if let Some(value) = f(chunk) { - if value == *chunk_id { + if value.as_str() == chunk_id.as_str() { use_id = true; } else { result.insert( - chunk_id.to_owned(), + chunk_id.as_str(), serde_json::to_string(&value).expect("invalid json to_string"), ); - last_key = Some(chunk_id); + last_key = Some(chunk_id.as_str()); entries += 1; } } @@ -254,6 +255,24 @@ pub fn stringify_static_chunk_map(filename: &String, chunk_ids: &[&str]) -> Stri format!("if ({}) return {};", condition, filename) } +fn stringify_map(map: &HashMap<&str, T>) -> String { + format!( + r#"{{{}}}"#, + map + .keys() + .sorted_unstable() + .fold(String::new(), |prev, cur| { + prev + + format!( + r#"{}: {},"#, + serde_json::to_string(cur).expect("json stringify failed"), + map.get(cur).expect("get key from map") + ) + .as_str() + }) + ) +} + #[test] fn test_get_undo_path() { assert_eq!(get_undo_path("a", "/a/b/c".to_string(), true), "./"); diff --git a/packages/rspack-test-tools/tests/builtinCases/samples/cycle-dynamic-entry/__snapshots__/output.snap.txt b/packages/rspack-test-tools/tests/builtinCases/samples/cycle-dynamic-entry/__snapshots__/output.snap.txt index a5494169f83..f5161ae18be 100644 --- a/packages/rspack-test-tools/tests/builtinCases/samples/cycle-dynamic-entry/__snapshots__/output.snap.txt +++ b/packages/rspack-test-tools/tests/builtinCases/samples/cycle-dynamic-entry/__snapshots__/output.snap.txt @@ -1,12 +1,12 @@ -```js title=dynamic-1_js-_1d740.js +```js title=dynamic-1_js-_5ebd0.js "use strict"; -(self['webpackChunkwebpack'] = self['webpackChunkwebpack'] || []).push([["dynamic-1_js-_1d740"], { +(self['webpackChunkwebpack'] = self['webpackChunkwebpack'] || []).push([["dynamic-1_js-_5ebd0"], { "./dynamic-1.js": (function (__unused_webpack_module, __webpack_exports__, __webpack_require__) { __webpack_require__.r(__webpack_exports__); /* ESM import */var _shared__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./shared.js"); /* ESM import */var _shared__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_shared__WEBPACK_IMPORTED_MODULE_0__); -__webpack_require__.e(/* import() */ "dynamic-2_js-_15a90").then(__webpack_require__.bind(__webpack_require__, "./dynamic-2.js")); +__webpack_require__.e(/* import() */ "dynamic-2_js-_72240").then(__webpack_require__.bind(__webpack_require__, "./dynamic-2.js")); console.log("dynamic-1"); @@ -15,15 +15,15 @@ console.log("dynamic-1"); }]); ``` -```js title=dynamic-1_js-_1d741.js -(self['webpackChunkwebpack'] = self['webpackChunkwebpack'] || []).push([["dynamic-1_js-_1d741"], { +```js title=dynamic-1_js-_5ebd1.js +(self['webpackChunkwebpack'] = self['webpackChunkwebpack'] || []).push([["dynamic-1_js-_5ebd1"], { "./dynamic-1.js": (function (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* ESM import */var _shared__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./shared.js"); /* ESM import */var _shared__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_shared__WEBPACK_IMPORTED_MODULE_0__); -__webpack_require__.e(/* import() */ "dynamic-2_js-_15a90").then(__webpack_require__.bind(__webpack_require__, "./dynamic-2.js")); +__webpack_require__.e(/* import() */ "dynamic-2_js-_72240").then(__webpack_require__.bind(__webpack_require__, "./dynamic-2.js")); console.log("dynamic-1"); @@ -37,15 +37,15 @@ console.log("shared"); }]); ``` -```js title=dynamic-2_js-_15a90.js +```js title=dynamic-2_js-_72240.js "use strict"; -(self['webpackChunkwebpack'] = self['webpackChunkwebpack'] || []).push([["dynamic-2_js-_15a90"], { +(self['webpackChunkwebpack'] = self['webpackChunkwebpack'] || []).push([["dynamic-2_js-_72240"], { "./dynamic-2.js": (function (__unused_webpack_module, __webpack_exports__, __webpack_require__) { __webpack_require__.r(__webpack_exports__); /* ESM import */var _shared__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./shared.js"); /* ESM import */var _shared__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_shared__WEBPACK_IMPORTED_MODULE_0__); -__webpack_require__.e(/* import() */ "dynamic-1_js-_1d740").then(__webpack_require__.bind(__webpack_require__, "./dynamic-1.js")); +__webpack_require__.e(/* import() */ "dynamic-1_js-_5ebd0").then(__webpack_require__.bind(__webpack_require__, "./dynamic-1.js")); console.log("dynamic-2"); @@ -54,15 +54,15 @@ console.log("dynamic-2"); }]); ``` -```js title=dynamic-2_js-_15a91.js -(self['webpackChunkwebpack'] = self['webpackChunkwebpack'] || []).push([["dynamic-2_js-_15a91"], { +```js title=dynamic-2_js-_72241.js +(self['webpackChunkwebpack'] = self['webpackChunkwebpack'] || []).push([["dynamic-2_js-_72241"], { "./dynamic-2.js": (function (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* ESM import */var _shared__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./shared.js"); /* ESM import */var _shared__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_shared__WEBPACK_IMPORTED_MODULE_0__); -__webpack_require__.e(/* import() */ "dynamic-1_js-_1d740").then(__webpack_require__.bind(__webpack_require__, "./dynamic-1.js")); +__webpack_require__.e(/* import() */ "dynamic-1_js-_5ebd0").then(__webpack_require__.bind(__webpack_require__, "./dynamic-1.js")); console.log("dynamic-2"); @@ -79,8 +79,8 @@ console.log("shared"); ```js title=main.js (self['webpackChunkwebpack'] = self['webpackChunkwebpack'] || []).push([["main"], { "./index.js": (function (__unused_webpack_module, __unused_webpack_exports, __webpack_require__) { -__webpack_require__.e(/* import() */ "dynamic-1_js-_1d741").then(__webpack_require__.bind(__webpack_require__, "./dynamic-1.js")); -__webpack_require__.e(/* import() */ "dynamic-2_js-_15a91").then(__webpack_require__.bind(__webpack_require__, "./dynamic-2.js")); +__webpack_require__.e(/* import() */ "dynamic-1_js-_5ebd1").then(__webpack_require__.bind(__webpack_require__, "./dynamic-1.js")); +__webpack_require__.e(/* import() */ "dynamic-2_js-_72241").then(__webpack_require__.bind(__webpack_require__, "./dynamic-2.js")); console.log("index"); diff --git a/packages/rspack-test-tools/tests/builtinCases/samples/intersection/__snapshots__/output.snap.txt b/packages/rspack-test-tools/tests/builtinCases/samples/intersection/__snapshots__/output.snap.txt index d09ccc53de3..23e6b8feb15 100644 --- a/packages/rspack-test-tools/tests/builtinCases/samples/intersection/__snapshots__/output.snap.txt +++ b/packages/rspack-test-tools/tests/builtinCases/samples/intersection/__snapshots__/output.snap.txt @@ -1,5 +1,5 @@ -```js title=a_js-_9b1b0.js -(self['webpackChunkwebpack'] = self['webpackChunkwebpack'] || []).push([["a_js-_9b1b0"], { +```js title=a_js-_c18a0.js +(self['webpackChunkwebpack'] = self['webpackChunkwebpack'] || []).push([["a_js-_c18a0"], { "./a.js": (function (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); @@ -25,8 +25,8 @@ console.log("i-1"); }]); ``` -```js title=a_js-_9b1b1.js -(self['webpackChunkwebpack'] = self['webpackChunkwebpack'] || []).push([["a_js-_9b1b1"], { +```js title=a_js-_c18a1.js +(self['webpackChunkwebpack'] = self['webpackChunkwebpack'] || []).push([["a_js-_c18a1"], { "./a.js": (function (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); @@ -67,7 +67,7 @@ console.log("i-1"); /* ESM import */var _i_1__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_i_1__WEBPACK_IMPORTED_MODULE_1__); -__webpack_require__.e(/* import() */ "a_js-_9b1b1").then(__webpack_require__.bind(__webpack_require__, "./a.js")); +__webpack_require__.e(/* import() */ "a_js-_c18a1").then(__webpack_require__.bind(__webpack_require__, "./a.js")); console.log("index"); @@ -101,7 +101,7 @@ console.log("i-2"); /* ESM import */var _i_2__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_i_2__WEBPACK_IMPORTED_MODULE_1__); -__webpack_require__.e(/* import() */ "a_js-_9b1b0").then(__webpack_require__.bind(__webpack_require__, "./a.js")); +__webpack_require__.e(/* import() */ "a_js-_c18a0").then(__webpack_require__.bind(__webpack_require__, "./a.js")); console.log("index"); diff --git a/packages/rspack-test-tools/tests/builtinCases/samples/parent-have-partial-module/__snapshots__/output.snap.txt b/packages/rspack-test-tools/tests/builtinCases/samples/parent-have-partial-module/__snapshots__/output.snap.txt index b85b1a3f444..17d1b97bed8 100644 --- a/packages/rspack-test-tools/tests/builtinCases/samples/parent-have-partial-module/__snapshots__/output.snap.txt +++ b/packages/rspack-test-tools/tests/builtinCases/samples/parent-have-partial-module/__snapshots__/output.snap.txt @@ -28,7 +28,7 @@ __webpack_require__.r(__webpack_exports__); /* ESM import */var _exist__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./exist.js"); /* ESM import */var _exist__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_exist__WEBPACK_IMPORTED_MODULE_0__); -__webpack_require__.e(/* import() */ "shared_js-_ac581").then(__webpack_require__.bind(__webpack_require__, "./shared.js")); +__webpack_require__.e(/* import() */ "shared_js-_5ce21").then(__webpack_require__.bind(__webpack_require__, "./shared.js")); }), @@ -39,7 +39,7 @@ __webpack_require__.e(/* import() */ "shared_js-_ac581").then(__webpack_require_ ```js title=parent-2_js.js (self['webpackChunkwebpack'] = self['webpackChunkwebpack'] || []).push([["parent-2_js"], { "./parent-2.js": (function (__unused_webpack_module, __unused_webpack_exports, __webpack_require__) { -__webpack_require__.e(/* import() */ "shared_js-_ac580").then(__webpack_require__.bind(__webpack_require__, "./shared.js")); +__webpack_require__.e(/* import() */ "shared_js-_5ce20").then(__webpack_require__.bind(__webpack_require__, "./shared.js")); }), @@ -47,8 +47,8 @@ __webpack_require__.e(/* import() */ "shared_js-_ac580").then(__webpack_require_ }]); ``` -```js title=shared_js-_ac580.js -(self['webpackChunkwebpack'] = self['webpackChunkwebpack'] || []).push([["shared_js-_ac580"], { +```js title=shared_js-_5ce20.js +(self['webpackChunkwebpack'] = self['webpackChunkwebpack'] || []).push([["shared_js-_5ce20"], { "./exist.js": (function () { console.log("exist"); @@ -69,9 +69,9 @@ console.log("shared"); }]); ``` -```js title=shared_js-_ac581.js +```js title=shared_js-_5ce21.js "use strict"; -(self['webpackChunkwebpack'] = self['webpackChunkwebpack'] || []).push([["shared_js-_ac581"], { +(self['webpackChunkwebpack'] = self['webpackChunkwebpack'] || []).push([["shared_js-_5ce21"], { "./shared.js": (function (__unused_webpack_module, __webpack_exports__, __webpack_require__) { __webpack_require__.r(__webpack_exports__); /* ESM import */var _exist__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./exist.js"); diff --git a/packages/rspack-test-tools/tests/watchCases/chunk-ids/id-equals-name/0/id-equals-name.js b/packages/rspack-test-tools/tests/watchCases/chunk-ids/id-equals-name/0/id-equals-name.js new file mode 100644 index 00000000000..d4a6b3dbc31 --- /dev/null +++ b/packages/rspack-test-tools/tests/watchCases/chunk-ids/id-equals-name/0/id-equals-name.js @@ -0,0 +1 @@ +export default "id" + __resourceQuery; diff --git a/packages/rspack-test-tools/tests/watchCases/chunk-ids/id-equals-name/0/index.js b/packages/rspack-test-tools/tests/watchCases/chunk-ids/id-equals-name/0/index.js new file mode 100644 index 00000000000..51ab27bfb68 --- /dev/null +++ b/packages/rspack-test-tools/tests/watchCases/chunk-ids/id-equals-name/0/index.js @@ -0,0 +1,23 @@ +const promise = Promise.all([ + import("./id-equals-name"), + import(/* webpackChunkName: "id-equals-name_js" */ "./id-equals-name?1"), +]); + +it("should have correct chunk id", async () => { + const [a, b] = await promise; + expect(a.default).toBe("id"); + expect(b.default).toBe("id?1"); + expect(__STATS__.chunks.map(c => c.id)).toEqual(['id-equals-name_js', 'id-equals-name_js0', 'main']); +}) + +it("should have correct log when incremental enabled", async () => { + const fs = require("fs/promises"); + const path = require("path"); + const statsString = await fs.readFile(path.resolve(__dirname, `stats.${WATCH_STEP}.txt`), 'utf-8'); + const incrementalLog = /LOG from rspack\.incremental\.chunkIds[\s\S]*?LOG/.exec(statsString); + if (incrementalLog) { + const content = incrementalLog[0]; + expect(content.includes("3 chunks are affected, 3 in total")).toBe(true); + expect(content.includes("3 chunks are updated by set_chunk_id, with 2 chunks using name as id, and 0 unnamed chunks")).toBe(true); + } +}); diff --git a/packages/rspack-test-tools/tests/watchCases/chunk-ids/id-equals-name/1/index.js b/packages/rspack-test-tools/tests/watchCases/chunk-ids/id-equals-name/1/index.js new file mode 100644 index 00000000000..04a8ef43fa5 --- /dev/null +++ b/packages/rspack-test-tools/tests/watchCases/chunk-ids/id-equals-name/1/index.js @@ -0,0 +1,23 @@ +const promise = Promise.all([ + import(/* webpackChunkName: "id-equals-name_js" */ "./id-equals-name"), + import("./id-equals-name?1"), +]); + +it("should have correct chunk id", async () => { + const [a, b] = await promise; + expect(a.default).toBe("id"); + expect(b.default).toBe("id?1"); + expect(__STATS__.chunks.map(c => c.id)).toEqual(['id-equals-name_js', 'id-equals-name_js_1', 'main']); +}) + +it("should have correct log when incremental enabled", async () => { + const fs = require("fs/promises"); + const path = require("path"); + const statsString = await fs.readFile(path.resolve(__dirname, `stats.${WATCH_STEP}.txt`), 'utf-8'); + const incrementalLog = /LOG from rspack\.incremental\.chunkIds[\s\S]*?LOG/.exec(statsString); + if (incrementalLog) { + const content = incrementalLog[0]; + expect(content.includes("3 chunks are affected, 3 in total")).toBe(true); + expect(content.includes("3 chunks are updated by set_chunk_id, with 2 chunks using name as id, and 0 unnamed chunks")).toBe(true); + } +}); diff --git a/packages/rspack-test-tools/tests/watchCases/chunk-ids/update-module/0/a.js b/packages/rspack-test-tools/tests/watchCases/chunk-ids/update-module/0/a.js new file mode 100644 index 00000000000..0c3155a6108 --- /dev/null +++ b/packages/rspack-test-tools/tests/watchCases/chunk-ids/update-module/0/a.js @@ -0,0 +1 @@ +export default '0' + `id${__resourceQuery}`; diff --git a/packages/rspack-test-tools/tests/watchCases/chunk-ids/update-module/0/index.js b/packages/rspack-test-tools/tests/watchCases/chunk-ids/update-module/0/index.js new file mode 100644 index 00000000000..962b45504d4 --- /dev/null +++ b/packages/rspack-test-tools/tests/watchCases/chunk-ids/update-module/0/index.js @@ -0,0 +1,33 @@ +const promise = Promise.all([ + import("./a"), + import("./a?1"), + import("./a?2"), +]); + +it("should not change the chunk id for updating a module", async () => { + const [a, b, c] = await promise; + expect(a.default).toBe(WATCH_STEP + "id"); + expect(b.default).toBe(WATCH_STEP + "id?1"); + expect(c.default).toBe(WATCH_STEP + "id?2"); + expect(__STATS__.chunks.map(c => c.id)).toEqual(['a_js', 'a_js_1', 'a_js_2', 'main']); +}) + +it("should have correct log when incremental enabled", async () => { + const fs = require("fs/promises"); + const path = require("path"); + const statsString = await fs.readFile(path.resolve(__dirname, `stats.${WATCH_STEP}.txt`), 'utf-8'); + const incrementalLog = /LOG from rspack\.incremental\.chunkIds[\s\S]*?LOG/.exec(statsString); + if (incrementalLog) { + const content = incrementalLog[0]; + switch (WATCH_STEP) { + case "0": + expect(content.includes("4 chunks are affected, 4 in total")).toBe(true); + expect(content.includes("4 chunks are updated by set_chunk_id, with 1 chunks using name as id, and 0 unnamed chunks")).toBe(true); + break; + case "1": + expect(content.includes("0 chunks are affected, 4 in total")).toBe(true); + expect(content.includes("0 chunks are updated by set_chunk_id, with 0 chunks using name as id, and 0 unnamed chunks")).toBe(true); + break; + } + } +}); diff --git a/packages/rspack-test-tools/tests/watchCases/chunk-ids/update-module/1/a.js b/packages/rspack-test-tools/tests/watchCases/chunk-ids/update-module/1/a.js new file mode 100644 index 00000000000..736208741d2 --- /dev/null +++ b/packages/rspack-test-tools/tests/watchCases/chunk-ids/update-module/1/a.js @@ -0,0 +1 @@ +export default '1' + `id${__resourceQuery}`; diff --git a/packages/rspack-test-tools/tests/watchCases/module-ids/ignored-module/0/index.js b/packages/rspack-test-tools/tests/watchCases/module-ids/ignored-module/0/index.js index 9e6710d9ed0..a690595b628 100644 --- a/packages/rspack-test-tools/tests/watchCases/module-ids/ignored-module/0/index.js +++ b/packages/rspack-test-tools/tests/watchCases/module-ids/ignored-module/0/index.js @@ -1,11 +1,10 @@ -import fs from "fs/promises"; -import path from "path"; - it("should compile", () => { expect(true).toBe(true); }); it("should have correct log when incremental enabled", async () => { + const fs = require("fs/promises"); + const path = require("path"); const statsString = await fs.readFile(path.resolve(__dirname, `stats.${WATCH_STEP}.txt`), 'utf-8'); const incrementalLog = /LOG from rspack\.incremental\.moduleIds[\s\S]*?LOG/.exec(statsString); if (incrementalLog) { diff --git a/packages/rspack-test-tools/tests/watchCases/module-ids/ignored-module/1/index.js b/packages/rspack-test-tools/tests/watchCases/module-ids/ignored-module/1/index.js index bf66b1f5117..8786c64be60 100644 --- a/packages/rspack-test-tools/tests/watchCases/module-ids/ignored-module/1/index.js +++ b/packages/rspack-test-tools/tests/watchCases/module-ids/ignored-module/1/index.js @@ -1,12 +1,11 @@ -import fs from "fs/promises"; -import path from "path"; - it("should have correct ignored value", () => { const ignored = require("ignored"); expect(ignored).toEqual({}); }); it("should have correct log when incremental enabled", async () => { + const fs = require("fs/promises"); + const path = require("path"); const statsString = await fs.readFile(path.resolve(__dirname, `stats.${WATCH_STEP}.txt`), 'utf-8'); const incrementalLog = /LOG from rspack\.incremental\.moduleIds[\s\S]*?LOG/.exec(statsString); if (incrementalLog) { diff --git a/packages/rspack-test-tools/tests/watchCases/module-ids/update-module/0/index.js b/packages/rspack-test-tools/tests/watchCases/module-ids/update-module/0/index.js index a47e662d6e0..84a2341ac90 100644 --- a/packages/rspack-test-tools/tests/watchCases/module-ids/update-module/0/index.js +++ b/packages/rspack-test-tools/tests/watchCases/module-ids/update-module/0/index.js @@ -1,5 +1,4 @@ import fs from "fs/promises"; -import path from "path"; import { value } from "./a"; it("should not change the module id for the updated module", async () => { @@ -9,6 +8,8 @@ it("should not change the module id for the updated module", async () => { }) it("should have correct log when incremental enabled", async () => { + const fs = require("fs/promises"); + const path = require("path"); const statsString = await fs.readFile(path.resolve(__dirname, `stats.${WATCH_STEP}.txt`), 'utf-8'); const incrementalLog = /LOG from rspack\.incremental\.moduleIds[\s\S]*?LOG/.exec(statsString); if (incrementalLog) { diff --git a/packages/rspack/src/builtin-plugin/DeterministicChunkIdsPlugin.ts b/packages/rspack/src/builtin-plugin/DeterministicChunkIdsPlugin.ts index c10786716ac..94f5128e44a 100644 --- a/packages/rspack/src/builtin-plugin/DeterministicChunkIdsPlugin.ts +++ b/packages/rspack/src/builtin-plugin/DeterministicChunkIdsPlugin.ts @@ -1,9 +1,23 @@ -import { BuiltinPluginName } from "@rspack/binding"; +import { type BuiltinPlugin, BuiltinPluginName } from "@rspack/binding"; +import type { Compiler } from "../Compiler"; +import type { Incremental } from "../config"; +import { RspackBuiltinPlugin, createBuiltinPlugin } from "./base"; -import { create } from "./base"; +export class DeterministicChunkIdsPlugin extends RspackBuiltinPlugin { + name = BuiltinPluginName.DeterministicChunkIdsPlugin; + affectedHooks = "compilation" as const; -export const DeterministicChunkIdsPlugin = create( - BuiltinPluginName.DeterministicChunkIdsPlugin, - () => {}, - "compilation" -); + raw(compiler: Compiler): BuiltinPlugin { + const incremental = compiler.options.experiments.incremental as Incremental; + const logger = compiler.getInfrastructureLogger( + "rspack.DeterministicChunkIdsPlugin" + ); + if (incremental.chunkIds) { + incremental.chunkIds = false; + logger.warn( + "`optimization.chunkIds = 'deterministic'` can't be used with `incremental.chunkIds` as deterministic chunk ids is a global effect. `incremental.chunkIds` has been overridden to false." + ); + } + return createBuiltinPlugin(this.name, undefined); + } +} diff --git a/packages/rspack/src/builtin-plugin/NaturalChunkIdsPlugin.ts b/packages/rspack/src/builtin-plugin/NaturalChunkIdsPlugin.ts index d4b4d8dae98..b59b4e7c33a 100644 --- a/packages/rspack/src/builtin-plugin/NaturalChunkIdsPlugin.ts +++ b/packages/rspack/src/builtin-plugin/NaturalChunkIdsPlugin.ts @@ -1,9 +1,23 @@ -import { BuiltinPluginName } from "@rspack/binding"; +import { type BuiltinPlugin, BuiltinPluginName } from "@rspack/binding"; +import type { Compiler } from "../Compiler"; +import type { Incremental } from "../config"; +import { RspackBuiltinPlugin, createBuiltinPlugin } from "./base"; -import { create } from "./base"; +export class NaturalChunkIdsPlugin extends RspackBuiltinPlugin { + name = BuiltinPluginName.NaturalChunkIdsPlugin; + affectedHooks = "compilation" as const; -export const NaturalChunkIdsPlugin = create( - BuiltinPluginName.NaturalChunkIdsPlugin, - () => {}, - "compilation" -); + raw(compiler: Compiler): BuiltinPlugin { + const incremental = compiler.options.experiments.incremental as Incremental; + const logger = compiler.getInfrastructureLogger( + "rspack.NaturalChunkIdsPlugin" + ); + if (incremental.moduleIds) { + incremental.moduleIds = false; + logger.warn( + "`optimization.chunkIds = 'natural'` can't be used with `incremental.chunkIds` as natural chunk ids is a global effect. `incremental.chunkIds` has been overridden to false." + ); + } + return createBuiltinPlugin(this.name, undefined); + } +} diff --git a/packages/rspack/src/rspackOptionsApply.ts b/packages/rspack/src/rspackOptionsApply.ts index b8ea7a0d58f..4eb1887ba19 100644 --- a/packages/rspack/src/rspackOptionsApply.ts +++ b/packages/rspack/src/rspackOptionsApply.ts @@ -327,6 +327,7 @@ export class RspackOptionsApply { switch (chunkIds) { case "natural": { new NaturalChunkIdsPlugin().apply(compiler); + break; } case "named": { new NamedChunkIdsPlugin().apply(compiler); diff --git a/tests/webpack-test/__snapshots__/StatsTestCases.basictest.js.snap b/tests/webpack-test/__snapshots__/StatsTestCases.basictest.js.snap index 824aeda5ed0..6e7899bae56 100644 --- a/tests/webpack-test/__snapshots__/StatsTestCases.basictest.js.snap +++ b/tests/webpack-test/__snapshots__/StatsTestCases.basictest.js.snap @@ -1457,8 +1457,8 @@ exports[`StatsTestCases should print correct stats for runtime-specific-used-exp asset production-a.js 10.6 KiB [emitted] (name: a) asset production-b.js 10.6 KiB [emitted] (name: b) asset production-dx_js.js 952 bytes [emitted] - asset production-dw_js-_5cba0.js 928 bytes [emitted] - asset production-dw_js-_5cba1.js 928 bytes [emitted] + asset production-dw_js-_b3b00.js 928 bytes [emitted] + asset production-dw_js-_b3b01.js 928 bytes [emitted] asset production-dy_js.js 921 bytes [emitted] asset production-dz_js.js 921 bytes [emitted] asset production-c.js 45 bytes [emitted] (name: c) @@ -1487,11 +1487,11 @@ exports[`StatsTestCases should print correct stats for runtime-specific-used-exp chunk (runtime: c) production-c.js (c) 9 bytes [entry] [rendered] ./c.js 9 bytes [built] [code generated] [no exports used] - chunk (runtime: a) production-dw_js-_5cba0.js 168 bytes [rendered] + chunk (runtime: a) production-dw_js-_b3b00.js 168 bytes [rendered] ./dw.js 46 bytes [built] [code generated] ./module.js?chunk 122 bytes [dependent] [built] [code generated] [only some exports used: identity, w, x, y, z] - chunk (runtime: b) production-dw_js-_5cba1.js 168 bytes [rendered] + chunk (runtime: b) production-dw_js-_b3b01.js 168 bytes [rendered] ./dw.js 46 bytes [built] [code generated] ./module.js?chunk 122 bytes [dependent] [built] [code generated] [only some exports used: identity, w, x, y, z] @@ -1726,7 +1726,7 @@ Rspack x.x.x compiled successfully in X.23" exports[`StatsTestCases should print correct stats for side-effects-issue-7428 1`] = ` "asset main.js 9.98 KiB [emitted] (name: main) asset 0.js 578 bytes [emitted] -runtime modules 7.27 KiB 9 modules +runtime modules 7.26 KiB 9 modules cacheable modules 967 bytes modules by path ./components/src/ 501 bytes orphan modules 315 bytes [orphan] diff --git a/website/docs/en/config/experiments.mdx b/website/docs/en/config/experiments.mdx index 4254fcd19ff..37c4d6e99bc 100644 --- a/website/docs/en/config/experiments.mdx +++ b/website/docs/en/config/experiments.mdx @@ -245,6 +245,8 @@ type Incremental = { providedExports?: boolean; dependenciesDiagnostics?: boolean; buildChunkGraph?: boolean; + moduleIds?: boolean; + chunkIds?: boolean; modulesHashes?: boolean; modulesCodegen?: boolean; modulesRuntimeRequirements?: boolean; diff --git a/website/docs/zh/config/experiments.mdx b/website/docs/zh/config/experiments.mdx index 46e3f1ca560..b0a4796ac6a 100644 --- a/website/docs/zh/config/experiments.mdx +++ b/website/docs/zh/config/experiments.mdx @@ -243,6 +243,8 @@ type Incremental = { providedExports?: boolean; dependenciesDiagnostics?: boolean; buildChunkGraph?: boolean; + moduleIds?: boolean; + chunkIds?: boolean; modulesHashes?: boolean; modulesCodegen?: boolean; modulesRuntimeRequirements?: boolean;