Skip to content

Commit

Permalink
fix(runtime): should calculate installed css chunks correctly (#4072)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>
  • Loading branch information
hyf0 and underfin authored Sep 1, 2023
1 parent c7bf5bf commit e65c564
Show file tree
Hide file tree
Showing 34 changed files with 203 additions and 144 deletions.
25 changes: 16 additions & 9 deletions crates/rspack_core/src/chunk_graph/chunk_graph_chunk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -252,20 +252,27 @@ impl ChunkGraph {
cgc.runtime_modules.iter()
}

pub fn get_chunk_condition_map<F: Fn(&ChunkUkey, &ChunkGraph, &ModuleGraph) -> bool>(
pub fn get_chunk_condition_map<F: Fn(&ChunkUkey, &Compilation) -> bool>(
&self,
chunk_ukey: &ChunkUkey,
chunk_by_ukey: &ChunkByUkey,
chunk_group_by_ukey: &ChunkGroupByUkey,
module_graph: &ModuleGraph,
compilation: &Compilation,
filter: F,
) -> HashMap<String, bool> {
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
Expand Down
77 changes: 25 additions & 52 deletions crates/rspack_plugin_runtime/src/runtime_module/css_loading.rs
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -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 {
Expand All @@ -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);
Expand All @@ -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(
Expand All @@ -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)),
));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand All @@ -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<chunkId, chunkName>
// and search it.
impl GetChunkFilenameRuntimeModule {
pub fn new(
content_type: &'static str,
Expand Down Expand Up @@ -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() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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),
));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)),
));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ impl RuntimeModule for LoadChunkWithModuleRuntimeModule {
.collect::<HashSet<_>>();
let map = async_modules
.par_iter()
.map(|identifier| {
.filter_map(|identifier| {
let mut chunk_ids = {
let chunk_group = compilation
.chunk_graph
Expand All @@ -70,6 +70,9 @@ impl RuntimeModule for LoadChunkWithModuleRuntimeModule {
})
.collect::<Vec<_>>()
};
if chunk_ids.is_empty() {
return None;
}
chunk_ids.sort_unstable();
let module = compilation
.module_graph
Expand All @@ -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::<HashMap<String, Vec<String>>>();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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),
));
}
Expand Down
Loading

0 comments on commit e65c564

Please sign in to comment.