From e65c5649f322f95784c88a68e38697efc410def6 Mon Sep 17 00:00:00 2001 From: Yunfei He Date: Fri, 1 Sep 2023 13:21:00 +0800 Subject: [PATCH] fix(runtime): should calculate installed css chunks correctly (#4072) * fix(runtime): should calculate installed css chunks correctly * fix: changed GetChunkFilenameRuntimeModule false allchunks for css * fix: replace chunkId match * fix: clippy * fix: e2e * fix: clippy --------- Co-authored-by: underfin --- .../src/chunk_graph/chunk_graph_chunk.rs | 25 +++--- .../src/runtime_module/css_loading.rs | 77 ++++++------------- .../src/runtime_module/get_chunk_filename.rs | 64 +++++++++------ .../import_scripts_chunk_loading.rs | 10 ++- .../src/runtime_module/jsonp_chunk_loading.rs | 20 +++-- .../runtime_module/load_chunk_with_module.rs | 8 +- .../runtime_module/readfile_chunk_loading.rs | 9 ++- .../require_js_chunk_loading.rs | 9 ++- .../src/runtime_module/utils.rs | 57 +++++++++----- .../__snapshots__/StatsTestCases.test.ts.snap | 28 +++---- .../dynamic.js | 0 .../index.js | 0 .../webpack.config.js | 0 .../{split-chunk => dynamic-chunk}/dynamic.js | 0 .../{split-chunk => dynamic-chunk}/index.js | 0 .../webpack.config.js | 0 .../dynamic.css | 0 .../dynamic.js | 0 .../index.js | 0 .../webpack.config.js | 0 .../common.js | 0 .../dynamic.css | 0 .../dynamic.js | 0 .../index.js | 1 + .../webpack.config.js | 0 .../runtime/dynamic-css-chunk/common.js | 1 + .../dynamic.css | 0 .../dynamic.js | 0 .../index.js | 1 + .../runtime/split-css-chunk/common.css | 3 + .../runtime/split-css-chunk/common.js | 2 +- .../runtime/split-css-chunk/index1.js | 9 +++ .../runtime/split-css-chunk/index2.js | 1 + .../runtime/split-css-chunk/webpack.config.js | 22 ++++++ 34 files changed, 203 insertions(+), 144 deletions(-) rename packages/rspack/tests/runtimeCases/runtime/{split-chunk-with-hash => dynamic-chunk-with-hash}/dynamic.js (100%) rename packages/rspack/tests/runtimeCases/runtime/{split-chunk-with-hash => dynamic-chunk-with-hash}/index.js (100%) rename packages/rspack/tests/runtimeCases/runtime/{split-chunk-with-hash => dynamic-chunk-with-hash}/webpack.config.js (100%) rename packages/rspack/tests/runtimeCases/runtime/{split-chunk => dynamic-chunk}/dynamic.js (100%) rename packages/rspack/tests/runtimeCases/runtime/{split-chunk => dynamic-chunk}/index.js (100%) rename packages/rspack/tests/runtimeCases/runtime/{split-chunk => dynamic-chunk}/webpack.config.js (100%) rename packages/rspack/tests/runtimeCases/runtime/{split-css-chunk-with-content-hash => dynamic-css-chunk-with-content-hash}/dynamic.css (100%) rename packages/rspack/tests/runtimeCases/runtime/{split-css-chunk-with-content-hash => dynamic-css-chunk-with-content-hash}/dynamic.js (100%) rename packages/rspack/tests/runtimeCases/runtime/{split-css-chunk-with-content-hash => dynamic-css-chunk-with-content-hash}/index.js (100%) rename packages/rspack/tests/runtimeCases/runtime/{split-css-chunk-with-content-hash => dynamic-css-chunk-with-content-hash}/webpack.config.js (100%) rename packages/rspack/tests/runtimeCases/runtime/{split-css-chunk-with-hash => dynamic-css-chunk-with-hash}/common.js (100%) rename packages/rspack/tests/runtimeCases/runtime/{split-css-chunk-with-hash => dynamic-css-chunk-with-hash}/dynamic.css (100%) rename packages/rspack/tests/runtimeCases/runtime/{split-css-chunk-with-hash => dynamic-css-chunk-with-hash}/dynamic.js (100%) rename packages/rspack/tests/runtimeCases/runtime/{split-css-chunk-with-hash => dynamic-css-chunk-with-hash}/index.js (97%) rename packages/rspack/tests/runtimeCases/runtime/{split-css-chunk-with-hash => dynamic-css-chunk-with-hash}/webpack.config.js (100%) create mode 100644 packages/rspack/tests/runtimeCases/runtime/dynamic-css-chunk/common.js rename packages/rspack/tests/runtimeCases/runtime/{split-css-chunk => dynamic-css-chunk}/dynamic.css (100%) rename packages/rspack/tests/runtimeCases/runtime/{split-css-chunk => dynamic-css-chunk}/dynamic.js (100%) rename packages/rspack/tests/runtimeCases/runtime/{split-css-chunk => dynamic-css-chunk}/index.js (97%) create mode 100644 packages/rspack/tests/runtimeCases/runtime/split-css-chunk/common.css create mode 100644 packages/rspack/tests/runtimeCases/runtime/split-css-chunk/index1.js create mode 100644 packages/rspack/tests/runtimeCases/runtime/split-css-chunk/index2.js create mode 100644 packages/rspack/tests/runtimeCases/runtime/split-css-chunk/webpack.config.js 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 f31feacdbbd..04ca683d74a 100644 --- a/crates/rspack_core/src/chunk_graph/chunk_graph_chunk.rs +++ b/crates/rspack_core/src/chunk_graph/chunk_graph_chunk.rs @@ -3,11 +3,11 @@ use rspack_identifier::{IdentifierLinkedMap, IdentifierSet}; use rustc_hash::{FxHashMap as HashMap, FxHashSet as HashSet}; -use crate::ChunkGraph; use crate::{ find_graph_roots, BoxModule, Chunk, ChunkByUkey, ChunkGroupByUkey, ChunkGroupUkey, ChunkUkey, Module, ModuleGraph, ModuleGraphModule, ModuleIdentifier, RuntimeGlobals, SourceType, }; +use crate::{ChunkGraph, Compilation}; #[derive(Debug, Clone, Default)] pub struct ChunkGraphChunk { @@ -252,20 +252,27 @@ impl ChunkGraph { cgc.runtime_modules.iter() } - pub fn get_chunk_condition_map bool>( + pub fn get_chunk_condition_map bool>( &self, chunk_ukey: &ChunkUkey, - chunk_by_ukey: &ChunkByUkey, - chunk_group_by_ukey: &ChunkGroupByUkey, - module_graph: &ModuleGraph, + compilation: &Compilation, filter: F, ) -> HashMap { let mut map = HashMap::default(); - let chunk = chunk_by_ukey.get(chunk_ukey).expect("Chunk should exist"); - for c in chunk.get_all_referenced_chunks(chunk_group_by_ukey).iter() { - let chunk = chunk_by_ukey.get(c).expect("Chunk should exist"); - map.insert(chunk.expect_id().to_string(), filter(c, self, module_graph)); + let chunk = compilation + .chunk_by_ukey + .get(chunk_ukey) + .expect("Chunk should exist"); + for c in chunk + .get_all_referenced_chunks(&compilation.chunk_group_by_ukey) + .iter() + { + let chunk = compilation + .chunk_by_ukey + .get(c) + .expect("Chunk should exist"); + map.insert(chunk.expect_id().to_string(), filter(c, compilation)); } map diff --git a/crates/rspack_plugin_runtime/src/runtime_module/css_loading.rs b/crates/rspack_plugin_runtime/src/runtime_module/css_loading.rs index be940ab910c..a1de731df01 100644 --- a/crates/rspack_plugin_runtime/src/runtime_module/css_loading.rs +++ b/crates/rspack_plugin_runtime/src/runtime_module/css_loading.rs @@ -1,14 +1,13 @@ use rspack_core::{ rspack_sources::{BoxSource, ConcatSource, RawSource, SourceExt}, - ChunkGraph, ChunkUkey, Compilation, ModuleGraph, RuntimeGlobals, RuntimeModule, SourceType, - RUNTIME_MODULE_STAGE_ATTACH, + ChunkUkey, Compilation, RuntimeGlobals, RuntimeModule, RUNTIME_MODULE_STAGE_ATTACH, }; use rspack_identifier::Identifier; -use rspack_plugin_javascript::runtime::stringify_chunks_to_array; use rustc_hash::FxHashSet as HashSet; +use super::utils::chunk_has_css; use crate::impl_runtime_module; -use crate::runtime_module::stringify_chunks; +use crate::runtime_module::{render_condition_map, stringify_chunks}; #[derive(Debug, Default, Eq)] pub struct CssLoadingRuntimeModule { id: Identifier, @@ -24,16 +23,6 @@ impl CssLoadingRuntimeModule { runtime_requirements, } } - - pub fn chunk_has_css( - chunk: &ChunkUkey, - chunk_graph: &ChunkGraph, - module_graph: &ModuleGraph, - ) -> bool { - !chunk_graph - .get_chunk_modules_by_source_type(chunk, SourceType::Css, module_graph) - .is_empty() - } } impl RuntimeModule for CssLoadingRuntimeModule { @@ -48,22 +37,6 @@ impl RuntimeModule for CssLoadingRuntimeModule { .get(&chunk_ukey) .expect("Chunk not found"); - let all_async_chunks = chunk.get_all_async_chunks(&compilation.chunk_group_by_ukey); - let mut async_chunk_ids_with_css = HashSet::default(); - for chunk_ukey in all_async_chunks.iter() { - if Self::chunk_has_css( - chunk_ukey, - &compilation.chunk_graph, - &compilation.module_graph, - ) { - let chunk = compilation - .chunk_by_ukey - .get(chunk_ukey) - .expect("Chunk not found"); - async_chunk_ids_with_css.insert(chunk.expect_id().to_string()); - } - } - let with_hmr = self .runtime_requirements .contains(RuntimeGlobals::HMR_DOWNLOAD_UPDATE_HANDLERS); @@ -72,34 +45,36 @@ impl RuntimeModule for CssLoadingRuntimeModule { .runtime_requirements .contains(RuntimeGlobals::ENSURE_CHUNK_HANDLERS); - if !with_hmr && !with_loading && async_chunk_ids_with_css.is_empty() { - return RawSource::from("").boxed(); - } - let mut initial_chunk_ids_with_css = HashSet::default(); + let mut initial_chunk_ids_without_css = HashSet::default(); let initial_chunks = chunk.get_all_initial_chunks(&compilation.chunk_group_by_ukey); for chunk_ukey in initial_chunks.iter() { - if Self::chunk_has_css( - chunk_ukey, - &compilation.chunk_graph, - &compilation.module_graph, - ) { - let chunk = compilation - .chunk_by_ukey - .get(chunk_ukey) - .expect("Chunk not found"); + let chunk = compilation + .chunk_by_ukey + .get(chunk_ukey) + .expect("Chunk not found"); + if chunk_has_css(chunk_ukey, compilation) { initial_chunk_ids_with_css.insert(chunk.expect_id().to_string()); + } else { + initial_chunk_ids_without_css.insert(chunk.expect_id().to_string()); } } + if !with_hmr && !with_loading && initial_chunk_ids_with_css.is_empty() { + return RawSource::from("").boxed(); + } + let mut source = ConcatSource::default(); // object to store loaded and loading chunks // undefined = chunk not loaded, null = chunk preloaded/prefetched // [resolve, reject, Promise] = chunk loading, 0 = chunk loaded + + // One entry initial chunk maybe is other entry dynamic chunk, so here + // only render chunk without css. See packages/rspack/tests/runtimeCases/runtime/split-css-chunk test. source.add(RawSource::from(format!( "var installedChunks = {};\n", - &stringify_chunks(&initial_chunk_ids_with_css, 0) + &stringify_chunks(&initial_chunk_ids_without_css, 0) ))); source.add(RawSource::from( @@ -110,15 +85,13 @@ impl RuntimeModule for CssLoadingRuntimeModule { )); if with_loading { + let condition_map = + compilation + .chunk_graph + .get_chunk_condition_map(&chunk_ukey, compilation, chunk_has_css); source.add(RawSource::from( - include_str!("runtime/css_loading_with_loading.js").replace( - "CSS_MATCHER", - format!( - "{}.indexOf(chunkId) > -1", - stringify_chunks_to_array(&async_chunk_ids_with_css) - ) - .as_str(), - ), + include_str!("runtime/css_loading_with_loading.js") + .replace("CSS_MATCHER", &render_condition_map(&condition_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 7fdbc489010..82705199de7 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 @@ -6,6 +6,7 @@ use rspack_core::{ use rspack_identifier::Identifier; use rustc_hash::FxHashMap as HashMap; +use super::utils::{chunk_has_css, chunk_has_js}; use crate::impl_runtime_module; #[derive(Debug, Eq)] @@ -17,7 +18,8 @@ pub struct GetChunkFilenameRuntimeModule { global: RuntimeGlobals, all_chunks: bool, } - +// It's render is different with webpack, rspack will only render chunk map +// and search it. impl GetChunkFilenameRuntimeModule { pub fn new( content_type: &'static str, @@ -77,31 +79,45 @@ impl RuntimeModule for GetChunkFilenameRuntimeModule { for chunk_ukey in chunks.iter() { if let Some(chunk) = compilation.chunk_by_ukey.get(chunk_ukey) { let filename_template = match self.source_type { - SourceType::JavaScript => get_js_chunk_filename_template( - chunk, - &compilation.options.output, - &compilation.chunk_group_by_ukey, - ), - SourceType::Css => get_css_chunk_filename_template( - chunk, - &compilation.options.output, - &compilation.chunk_group_by_ukey, - ), + SourceType::JavaScript => { + if chunk_has_js(chunk_ukey, compilation) { + Some(get_js_chunk_filename_template( + chunk, + &compilation.options.output, + &compilation.chunk_group_by_ukey, + )) + } else { + None + } + } + SourceType::Css => { + if chunk_has_css(chunk_ukey, compilation) { + Some(get_css_chunk_filename_template( + chunk, + &compilation.options.output, + &compilation.chunk_group_by_ukey, + )) + } else { + None + } + } _ => unreachable!(), }; - let filename = compilation.get_path( - filename_template, - PathData::default() - .chunk(chunk) - .content_hash_optional( - chunk - .content_hash - .get(&self.source_type) - .map(|i| i.rendered(compilation.options.output.hash_digest_length)), - ) - .hash_optional(compilation.get_hash()), - ); - chunks_map.insert(chunk.expect_id().to_string(), format!("\"{filename}\"")); + if let Some(filename_template) = filename_template { + let filename = compilation.get_path( + filename_template, + PathData::default() + .chunk(chunk) + .content_hash_optional( + chunk + .content_hash + .get(&self.source_type) + .map(|i| i.rendered(compilation.options.output.hash_digest_length)), + ) + .hash_optional(compilation.get_hash()), + ); + chunks_map.insert(chunk.expect_id().to_string(), format!("\"{filename}\"")); + } } } match chunks_map.is_empty() { diff --git a/crates/rspack_plugin_runtime/src/runtime_module/import_scripts_chunk_loading.rs b/crates/rspack_plugin_runtime/src/runtime_module/import_scripts_chunk_loading.rs index 936bd5b35d3..a0a4980c3f1 100644 --- a/crates/rspack_plugin_runtime/src/runtime_module/import_scripts_chunk_loading.rs +++ b/crates/rspack_plugin_runtime/src/runtime_module/import_scripts_chunk_loading.rs @@ -6,7 +6,7 @@ use rspack_identifier::Identifier; use super::utils::{chunk_has_js, get_output_dir}; use crate::impl_runtime_module; -use crate::runtime_module::utils::{get_initial_chunk_ids, stringify_chunks}; +use crate::runtime_module::utils::{get_initial_chunk_ids, render_condition_map, stringify_chunks}; #[derive(Debug, Default, Eq)] pub struct ImportScriptsChunkLoadingRuntimeModule { @@ -107,10 +107,14 @@ impl RuntimeModule for ImportScriptsChunkLoadingRuntimeModule { RuntimeGlobals::GET_CHUNK_SCRIPT_FILENAME ) }; + let condition_map = + compilation + .chunk_graph + .get_chunk_condition_map(&chunk.ukey, compilation, chunk_has_js); + // If chunkId not corresponding chunkName will skip load it. source.add(RawSource::from( include_str!("runtime/import_scripts_chunk_loading.js") - // TODO - .replace("JS_MATCHER", "chunkId") + .replace("JS_MATCHER", &render_condition_map(&condition_map)) .replace("$URL$", &url) .replace("$CHUNK_LOADING_GLOBAL_EXPR$", &chunk_loading_global_expr), )); diff --git a/crates/rspack_plugin_runtime/src/runtime_module/jsonp_chunk_loading.rs b/crates/rspack_plugin_runtime/src/runtime_module/jsonp_chunk_loading.rs index 63a47dd21e3..fdd1e3fbbf3 100644 --- a/crates/rspack_plugin_runtime/src/runtime_module/jsonp_chunk_loading.rs +++ b/crates/rspack_plugin_runtime/src/runtime_module/jsonp_chunk_loading.rs @@ -4,9 +4,10 @@ use rspack_core::{ }; use rspack_identifier::Identifier; -use super::utils::chunk_has_js; use crate::impl_runtime_module; -use crate::runtime_module::utils::{get_initial_chunk_ids, stringify_chunks}; +use crate::runtime_module::utils::{ + chunk_has_js, get_initial_chunk_ids, render_condition_map, stringify_chunks, +}; #[derive(Debug, Default, Eq)] pub struct JsonpChunkLoadingRuntimeModule { @@ -40,13 +41,6 @@ impl RuntimeModule for JsonpChunkLoadingRuntimeModule { } fn generate(&self, compilation: &Compilation) -> BoxSource { - // let condition_map = compilation.chunk_graph.get_chunk_condition_map( - // &chunk_ukey, - // &compilation.chunk_by_ukey, - // &compilation.chunk_group_by_ukey, - // &compilation.module_graph, - // chunk_hash_js, - // ); let initial_chunks = get_initial_chunk_ids(self.chunk, compilation, chunk_has_js); let chunk = compilation .chunk_by_ukey @@ -74,10 +68,14 @@ impl RuntimeModule for JsonpChunkLoadingRuntimeModule { .contains(RuntimeGlobals::ON_CHUNKS_LOADED); if with_loading { + let condition_map = + compilation + .chunk_graph + .get_chunk_condition_map(&chunk.ukey, compilation, chunk_has_js); + // If chunkId not corresponding chunkName will skip load it. source.add(RawSource::from( include_str!("runtime/jsonp_chunk_loading.js") - // TODO - .replace("JS_MATCHER", "chunkId"), + .replace("JS_MATCHER", &render_condition_map(&condition_map)), )); } diff --git a/crates/rspack_plugin_runtime/src/runtime_module/load_chunk_with_module.rs b/crates/rspack_plugin_runtime/src/runtime_module/load_chunk_with_module.rs index 8bd87090019..499f51aea0c 100644 --- a/crates/rspack_plugin_runtime/src/runtime_module/load_chunk_with_module.rs +++ b/crates/rspack_plugin_runtime/src/runtime_module/load_chunk_with_module.rs @@ -49,7 +49,7 @@ impl RuntimeModule for LoadChunkWithModuleRuntimeModule { .collect::>(); let map = async_modules .par_iter() - .map(|identifier| { + .filter_map(|identifier| { let mut chunk_ids = { let chunk_group = compilation .chunk_graph @@ -70,6 +70,9 @@ impl RuntimeModule for LoadChunkWithModuleRuntimeModule { }) .collect::>() }; + if chunk_ids.is_empty() { + return None; + } chunk_ids.sort_unstable(); let module = compilation .module_graph @@ -79,8 +82,7 @@ impl RuntimeModule for LoadChunkWithModuleRuntimeModule { let module_id = module.id(&compilation.chunk_graph); let module_id_expr = serde_json::to_string(module_id).expect("invalid module_id"); - // TODO if chunk_ids is empty, here should remove the filed - (module_id_expr, chunk_ids) + Some((module_id_expr, chunk_ids)) }) .collect::>>(); diff --git a/crates/rspack_plugin_runtime/src/runtime_module/readfile_chunk_loading.rs b/crates/rspack_plugin_runtime/src/runtime_module/readfile_chunk_loading.rs index beb41e870de..1fee3386855 100644 --- a/crates/rspack_plugin_runtime/src/runtime_module/readfile_chunk_loading.rs +++ b/crates/rspack_plugin_runtime/src/runtime_module/readfile_chunk_loading.rs @@ -6,7 +6,7 @@ use rspack_identifier::Identifier; use super::utils::{chunk_has_js, get_output_dir}; use crate::impl_runtime_module; -use crate::runtime_module::utils::{get_initial_chunk_ids, stringify_chunks}; +use crate::runtime_module::utils::{get_initial_chunk_ids, render_condition_map, stringify_chunks}; #[derive(Debug, Default, Eq)] pub struct ReadFileChunkLoadingRuntimeModule { @@ -110,10 +110,13 @@ impl RuntimeModule for ReadFileChunkLoadingRuntimeModule { } if with_loading { + let condition_map = + compilation + .chunk_graph + .get_chunk_condition_map(&chunk.ukey, compilation, chunk_has_js); source.add(RawSource::from( include_str!("runtime/readfile_chunk_loading_with_loading.js") - // TODO - .replace("JS_MATCHER", "chunkId") + .replace("JS_MATCHER", &render_condition_map(&condition_map)) .replace("$OUTPUT_DIR$", &root_output_dir), )); } diff --git a/crates/rspack_plugin_runtime/src/runtime_module/require_js_chunk_loading.rs b/crates/rspack_plugin_runtime/src/runtime_module/require_js_chunk_loading.rs index 502c40f6084..79c83debaa0 100644 --- a/crates/rspack_plugin_runtime/src/runtime_module/require_js_chunk_loading.rs +++ b/crates/rspack_plugin_runtime/src/runtime_module/require_js_chunk_loading.rs @@ -6,7 +6,7 @@ use rspack_identifier::Identifier; use super::utils::{chunk_has_js, get_output_dir}; use crate::impl_runtime_module; -use crate::runtime_module::utils::{get_initial_chunk_ids, stringify_chunks}; +use crate::runtime_module::utils::{get_initial_chunk_ids, render_condition_map, stringify_chunks}; #[derive(Debug, Default, Eq)] pub struct RequireChunkLoadingRuntimeModule { @@ -111,10 +111,13 @@ impl RuntimeModule for RequireChunkLoadingRuntimeModule { } if with_loading { + let condition_map = + compilation + .chunk_graph + .get_chunk_condition_map(&chunk.ukey, compilation, chunk_has_js); source.add(RawSource::from( include_str!("runtime/require_chunk_loading_with_loading.js") - // TODO - .replace("JS_MATCHER", "chunkId") + .replace("JS_MATCHER", &render_condition_map(&condition_map)) .replace("$OUTPUT_DIR$", &root_output_dir), )); } diff --git a/crates/rspack_plugin_runtime/src/runtime_module/utils.rs b/crates/rspack_plugin_runtime/src/runtime_module/utils.rs index 8ac290ceecd..2d638230447 100644 --- a/crates/rspack_plugin_runtime/src/runtime_module/utils.rs +++ b/crates/rspack_plugin_runtime/src/runtime_module/utils.rs @@ -1,28 +1,36 @@ use rspack_core::{ get_js_chunk_filename_template, Chunk, ChunkLoading, ChunkUkey, Compilation, PathData, SourceType, }; -use rustc_hash::FxHashSet as HashSet; +use rustc_hash::{FxHashMap as HashMap, FxHashSet as HashSet}; -// pub fn condition_map_to_string(map: &HashMap, _value: String) -> String { -// let positive_items = map -// .iter() -// .filter(|(_, v)| **v) -// .map(|(k, _)| k) -// .collect::>(); -// if positive_items.len() == 0 { -// return "false".to_string(); -// } -// let negative_items = map -// .iter() -// .filter(|(_, v)| !**v) -// .map(|(k, _)| k) -// .collect::>(); -// if negative_items.len() == 0 { -// return "true".to_string(); -// } -// // TODO -// return "true".to_string(); -// } +pub fn render_condition_map(map: &HashMap) -> String { + let mut positive_items = map + .iter() + .filter(|(_, v)| **v) + .map(|(k, _)| k) + .collect::>(); + if positive_items.is_empty() { + return false.to_string(); + } + let negative_items = map + .iter() + .filter(|(_, v)| !**v) + .map(|(k, _)| k) + .collect::>(); + if negative_items.is_empty() { + return true.to_string(); + } + + positive_items.sort_unstable(); + format!( + "[{}].indexOf(chunkId) > - 1", + positive_items + .iter() + .map(|s| format!("'{s}'")) + .collect::>() + .join(",") + ) +} pub fn get_initial_chunk_ids( chunk: Option, @@ -84,6 +92,13 @@ pub fn chunk_has_js(chunk_ukey: &ChunkUkey, compilation: &Compilation) -> bool { .is_empty() } +pub fn chunk_has_css(chunk: &ChunkUkey, compilation: &Compilation) -> bool { + !compilation + .chunk_graph + .get_chunk_modules_by_source_type(chunk, SourceType::Css, &compilation.module_graph) + .is_empty() +} + pub fn get_undo_path(filename: &str, p: String, enforce_relative: bool) -> String { let mut depth: i32 = -1; let mut append = String::new(); diff --git a/packages/rspack/tests/__snapshots__/StatsTestCases.test.ts.snap b/packages/rspack/tests/__snapshots__/StatsTestCases.test.ts.snap index 56226395fb7..a7b4eb932b5 100644 --- a/packages/rspack/tests/__snapshots__/StatsTestCases.test.ts.snap +++ b/packages/rspack/tests/__snapshots__/StatsTestCases.test.ts.snap @@ -352,7 +352,7 @@ exports[`StatsTestCases should print correct stats for filename 1`] = ` "hotModuleReplacement": false, }, "name": "main.xxxx.js", - "size": 1105, + "size": 1094, "type": "asset", }, ], @@ -461,10 +461,10 @@ exports[`StatsTestCases should print correct stats for filename 1`] = ` "assets": [ { "name": "main.xxxx.js", - "size": 1105, + "size": 1094, }, ], - "assetsSize": 1105, + "assetsSize": 1094, "chunks": [ "main", ], @@ -474,7 +474,7 @@ exports[`StatsTestCases should print correct stats for filename 1`] = ` "errors": [], "errorsCount": 0, "filteredModules": undefined, - "hash": "dab84cbef48dbc9f0e6b", + "hash": "7cdaa6ba61cec2cb7288", "logging": {}, "modules": [ { @@ -536,10 +536,10 @@ exports[`StatsTestCases should print correct stats for filename 1`] = ` "assets": [ { "name": "main.xxxx.js", - "size": 1105, + "size": 1094, }, ], - "assetsSize": 1105, + "assetsSize": 1094, "chunks": [ "main", ], @@ -556,8 +556,8 @@ exports[`StatsTestCases should print correct stats for filename 1`] = ` exports[`StatsTestCases should print correct stats for filename 2`] = ` "PublicPath: (none) asset dynamic_js.xxxx.js 138 bytes {dynamic_js} [emitted] -asset main.xxxx.js 1.08 KiB {main} [emitted] (name: main) -Entrypoint main 1.08 KiB = main.xxxx.js +asset main.xxxx.js 1.07 KiB {main} [emitted] (name: main) +Entrypoint main 1.07 KiB = main.xxxx.js chunk {dynamic_js} dynamic_js.xxxx.js <{main}> ./dynamic.js [426] {dynamic_js} dynamic import ./dynamic [10] @@ -568,7 +568,7 @@ chunk {main} main.xxxx.js (main) >{dynamic_js}< [entry] entry ./index ./dynamic.js [426] {dynamic_js} dynamic import ./dynamic [10] -rspack compiled successfully (dab84cbef48dbc9f0e6b)" +rspack compiled successfully (7cdaa6ba61cec2cb7288)" `; exports[`StatsTestCases should print correct stats for hot+production 1`] = ` @@ -1039,10 +1039,10 @@ exports[`StatsTestCases should print correct stats for named-chunk-group 1`] = ` "assets": [ { "name": "bundle.js", - "size": 1080, + "size": 1069, }, ], - "assetsSize": 1080, + "assetsSize": 1069, "chunks": [ "main", ], @@ -1067,10 +1067,10 @@ exports[`StatsTestCases should print correct stats for named-chunk-group 1`] = ` "assets": [ { "name": "bundle.js", - "size": 1080, + "size": 1069, }, ], - "assetsSize": 1080, + "assetsSize": 1069, "chunks": [ "main", ], @@ -1081,7 +1081,7 @@ exports[`StatsTestCases should print correct stats for named-chunk-group 1`] = ` `; exports[`StatsTestCases should print correct stats for named-chunk-group 2`] = ` -"Entrypoint main 1.05 KiB = bundle.js +"Entrypoint main 1.04 KiB = bundle.js Chunk Group cimanyd 135 bytes = cimanyd.bundle.js" `; diff --git a/packages/rspack/tests/runtimeCases/runtime/split-chunk-with-hash/dynamic.js b/packages/rspack/tests/runtimeCases/runtime/dynamic-chunk-with-hash/dynamic.js similarity index 100% rename from packages/rspack/tests/runtimeCases/runtime/split-chunk-with-hash/dynamic.js rename to packages/rspack/tests/runtimeCases/runtime/dynamic-chunk-with-hash/dynamic.js diff --git a/packages/rspack/tests/runtimeCases/runtime/split-chunk-with-hash/index.js b/packages/rspack/tests/runtimeCases/runtime/dynamic-chunk-with-hash/index.js similarity index 100% rename from packages/rspack/tests/runtimeCases/runtime/split-chunk-with-hash/index.js rename to packages/rspack/tests/runtimeCases/runtime/dynamic-chunk-with-hash/index.js diff --git a/packages/rspack/tests/runtimeCases/runtime/split-chunk-with-hash/webpack.config.js b/packages/rspack/tests/runtimeCases/runtime/dynamic-chunk-with-hash/webpack.config.js similarity index 100% rename from packages/rspack/tests/runtimeCases/runtime/split-chunk-with-hash/webpack.config.js rename to packages/rspack/tests/runtimeCases/runtime/dynamic-chunk-with-hash/webpack.config.js diff --git a/packages/rspack/tests/runtimeCases/runtime/split-chunk/dynamic.js b/packages/rspack/tests/runtimeCases/runtime/dynamic-chunk/dynamic.js similarity index 100% rename from packages/rspack/tests/runtimeCases/runtime/split-chunk/dynamic.js rename to packages/rspack/tests/runtimeCases/runtime/dynamic-chunk/dynamic.js diff --git a/packages/rspack/tests/runtimeCases/runtime/split-chunk/index.js b/packages/rspack/tests/runtimeCases/runtime/dynamic-chunk/index.js similarity index 100% rename from packages/rspack/tests/runtimeCases/runtime/split-chunk/index.js rename to packages/rspack/tests/runtimeCases/runtime/dynamic-chunk/index.js diff --git a/packages/rspack/tests/runtimeCases/runtime/split-chunk/webpack.config.js b/packages/rspack/tests/runtimeCases/runtime/dynamic-chunk/webpack.config.js similarity index 100% rename from packages/rspack/tests/runtimeCases/runtime/split-chunk/webpack.config.js rename to packages/rspack/tests/runtimeCases/runtime/dynamic-chunk/webpack.config.js diff --git a/packages/rspack/tests/runtimeCases/runtime/split-css-chunk-with-content-hash/dynamic.css b/packages/rspack/tests/runtimeCases/runtime/dynamic-css-chunk-with-content-hash/dynamic.css similarity index 100% rename from packages/rspack/tests/runtimeCases/runtime/split-css-chunk-with-content-hash/dynamic.css rename to packages/rspack/tests/runtimeCases/runtime/dynamic-css-chunk-with-content-hash/dynamic.css diff --git a/packages/rspack/tests/runtimeCases/runtime/split-css-chunk-with-content-hash/dynamic.js b/packages/rspack/tests/runtimeCases/runtime/dynamic-css-chunk-with-content-hash/dynamic.js similarity index 100% rename from packages/rspack/tests/runtimeCases/runtime/split-css-chunk-with-content-hash/dynamic.js rename to packages/rspack/tests/runtimeCases/runtime/dynamic-css-chunk-with-content-hash/dynamic.js diff --git a/packages/rspack/tests/runtimeCases/runtime/split-css-chunk-with-content-hash/index.js b/packages/rspack/tests/runtimeCases/runtime/dynamic-css-chunk-with-content-hash/index.js similarity index 100% rename from packages/rspack/tests/runtimeCases/runtime/split-css-chunk-with-content-hash/index.js rename to packages/rspack/tests/runtimeCases/runtime/dynamic-css-chunk-with-content-hash/index.js diff --git a/packages/rspack/tests/runtimeCases/runtime/split-css-chunk-with-content-hash/webpack.config.js b/packages/rspack/tests/runtimeCases/runtime/dynamic-css-chunk-with-content-hash/webpack.config.js similarity index 100% rename from packages/rspack/tests/runtimeCases/runtime/split-css-chunk-with-content-hash/webpack.config.js rename to packages/rspack/tests/runtimeCases/runtime/dynamic-css-chunk-with-content-hash/webpack.config.js diff --git a/packages/rspack/tests/runtimeCases/runtime/split-css-chunk-with-hash/common.js b/packages/rspack/tests/runtimeCases/runtime/dynamic-css-chunk-with-hash/common.js similarity index 100% rename from packages/rspack/tests/runtimeCases/runtime/split-css-chunk-with-hash/common.js rename to packages/rspack/tests/runtimeCases/runtime/dynamic-css-chunk-with-hash/common.js diff --git a/packages/rspack/tests/runtimeCases/runtime/split-css-chunk-with-hash/dynamic.css b/packages/rspack/tests/runtimeCases/runtime/dynamic-css-chunk-with-hash/dynamic.css similarity index 100% rename from packages/rspack/tests/runtimeCases/runtime/split-css-chunk-with-hash/dynamic.css rename to packages/rspack/tests/runtimeCases/runtime/dynamic-css-chunk-with-hash/dynamic.css diff --git a/packages/rspack/tests/runtimeCases/runtime/split-css-chunk-with-hash/dynamic.js b/packages/rspack/tests/runtimeCases/runtime/dynamic-css-chunk-with-hash/dynamic.js similarity index 100% rename from packages/rspack/tests/runtimeCases/runtime/split-css-chunk-with-hash/dynamic.js rename to packages/rspack/tests/runtimeCases/runtime/dynamic-css-chunk-with-hash/dynamic.js diff --git a/packages/rspack/tests/runtimeCases/runtime/split-css-chunk-with-hash/index.js b/packages/rspack/tests/runtimeCases/runtime/dynamic-css-chunk-with-hash/index.js similarity index 97% rename from packages/rspack/tests/runtimeCases/runtime/split-css-chunk-with-hash/index.js rename to packages/rspack/tests/runtimeCases/runtime/dynamic-css-chunk-with-hash/index.js index ad470a6368c..fd70b1a250b 100644 --- a/packages/rspack/tests/runtimeCases/runtime/split-css-chunk-with-hash/index.js +++ b/packages/rspack/tests/runtimeCases/runtime/dynamic-css-chunk-with-hash/index.js @@ -5,6 +5,7 @@ it("load dynamic css chunk with hash", function (done) { if (__webpack_require__.f.css) { expect(document.getElementsByTagName("link").length).toBe(1); } + debugger; import("./common").then(module => { expect(module.value).toBe("common"); // test is only for css loading diff --git a/packages/rspack/tests/runtimeCases/runtime/split-css-chunk-with-hash/webpack.config.js b/packages/rspack/tests/runtimeCases/runtime/dynamic-css-chunk-with-hash/webpack.config.js similarity index 100% rename from packages/rspack/tests/runtimeCases/runtime/split-css-chunk-with-hash/webpack.config.js rename to packages/rspack/tests/runtimeCases/runtime/dynamic-css-chunk-with-hash/webpack.config.js diff --git a/packages/rspack/tests/runtimeCases/runtime/dynamic-css-chunk/common.js b/packages/rspack/tests/runtimeCases/runtime/dynamic-css-chunk/common.js new file mode 100644 index 00000000000..a5eb765e0af --- /dev/null +++ b/packages/rspack/tests/runtimeCases/runtime/dynamic-css-chunk/common.js @@ -0,0 +1 @@ +export const value = "common"; diff --git a/packages/rspack/tests/runtimeCases/runtime/split-css-chunk/dynamic.css b/packages/rspack/tests/runtimeCases/runtime/dynamic-css-chunk/dynamic.css similarity index 100% rename from packages/rspack/tests/runtimeCases/runtime/split-css-chunk/dynamic.css rename to packages/rspack/tests/runtimeCases/runtime/dynamic-css-chunk/dynamic.css diff --git a/packages/rspack/tests/runtimeCases/runtime/split-css-chunk/dynamic.js b/packages/rspack/tests/runtimeCases/runtime/dynamic-css-chunk/dynamic.js similarity index 100% rename from packages/rspack/tests/runtimeCases/runtime/split-css-chunk/dynamic.js rename to packages/rspack/tests/runtimeCases/runtime/dynamic-css-chunk/dynamic.js diff --git a/packages/rspack/tests/runtimeCases/runtime/split-css-chunk/index.js b/packages/rspack/tests/runtimeCases/runtime/dynamic-css-chunk/index.js similarity index 97% rename from packages/rspack/tests/runtimeCases/runtime/split-css-chunk/index.js rename to packages/rspack/tests/runtimeCases/runtime/dynamic-css-chunk/index.js index 52b66df8a87..93ab07ebee2 100644 --- a/packages/rspack/tests/runtimeCases/runtime/split-css-chunk/index.js +++ b/packages/rspack/tests/runtimeCases/runtime/dynamic-css-chunk/index.js @@ -5,6 +5,7 @@ it("load dynamic css chunk", function (done) { if (__webpack_require__.f.css) { expect(document.getElementsByTagName("link").length).toBe(1); } + debugger; import("./common").then(module => { expect(module.value).toBe("common"); // test is only for css loading diff --git a/packages/rspack/tests/runtimeCases/runtime/split-css-chunk/common.css b/packages/rspack/tests/runtimeCases/runtime/split-css-chunk/common.css new file mode 100644 index 00000000000..c4845173e30 --- /dev/null +++ b/packages/rspack/tests/runtimeCases/runtime/split-css-chunk/common.css @@ -0,0 +1,3 @@ +#dynamic { + background: red; +} \ No newline at end of file diff --git a/packages/rspack/tests/runtimeCases/runtime/split-css-chunk/common.js b/packages/rspack/tests/runtimeCases/runtime/split-css-chunk/common.js index a5eb765e0af..3b529e8a100 100644 --- a/packages/rspack/tests/runtimeCases/runtime/split-css-chunk/common.js +++ b/packages/rspack/tests/runtimeCases/runtime/split-css-chunk/common.js @@ -1 +1 @@ -export const value = "common"; +import "./common.css"; diff --git a/packages/rspack/tests/runtimeCases/runtime/split-css-chunk/index1.js b/packages/rspack/tests/runtimeCases/runtime/split-css-chunk/index1.js new file mode 100644 index 00000000000..155b0cefb6f --- /dev/null +++ b/packages/rspack/tests/runtimeCases/runtime/split-css-chunk/index1.js @@ -0,0 +1,9 @@ +it("should load css chunk", function (done) { + import("./common").then(module => { + // test is only for css loading + if (__webpack_require__.f.css) { + expect(document.getElementsByTagName("link").length).toBe(1); + } + done(); + }); +}); diff --git a/packages/rspack/tests/runtimeCases/runtime/split-css-chunk/index2.js b/packages/rspack/tests/runtimeCases/runtime/split-css-chunk/index2.js new file mode 100644 index 00000000000..a8a18775ed3 --- /dev/null +++ b/packages/rspack/tests/runtimeCases/runtime/split-css-chunk/index2.js @@ -0,0 +1 @@ +import "./common"; diff --git a/packages/rspack/tests/runtimeCases/runtime/split-css-chunk/webpack.config.js b/packages/rspack/tests/runtimeCases/runtime/split-css-chunk/webpack.config.js new file mode 100644 index 00000000000..df936e86135 --- /dev/null +++ b/packages/rspack/tests/runtimeCases/runtime/split-css-chunk/webpack.config.js @@ -0,0 +1,22 @@ +module.exports = { + entry: { + main: "./index1.js", + main2: "./index2.js" + }, + output: { + chunkFilename: "[id].[contenthash].js" + }, + optimization: { + splitChunks: { + cacheGroups: { + common: { + chunks: "all", + test: /common/, + enforce: true, + name: "common" + } + } + }, + runtimeChunk: "single" + } +};