diff --git a/Cargo.lock b/Cargo.lock index 30adfa684067..da35801b90c6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4839,7 +4839,6 @@ dependencies = [ "rspack_hook", "rspack_paths", "rspack_plugin_html", - "rspack_plugin_mf", "rspack_plugin_real_content_hash", "rspack_plugin_runtime", "rspack_util", diff --git a/crates/rspack_plugin_sri/Cargo.toml b/crates/rspack_plugin_sri/Cargo.toml index 5670cab79731..b0ba4a467540 100644 --- a/crates/rspack_plugin_sri/Cargo.toml +++ b/crates/rspack_plugin_sri/Cargo.toml @@ -25,7 +25,6 @@ rspack_hash = { workspace = true } rspack_hook = { workspace = true } rspack_paths = { workspace = true } rspack_plugin_html = { workspace = true } -rspack_plugin_mf = { workspace = true } rspack_plugin_real_content_hash = { workspace = true } rspack_plugin_runtime = { workspace = true } rspack_util = { workspace = true } diff --git a/crates/rspack_plugin_sri/src/asset.rs b/crates/rspack_plugin_sri/src/asset.rs index 01a15d148032..23844edd53c4 100644 --- a/crates/rspack_plugin_sri/src/asset.rs +++ b/crates/rspack_plugin_sri/src/asset.rs @@ -192,14 +192,15 @@ fn process_chunk_source( } } -fn digest_chunks(compilation: &Compilation) -> Vec> { +fn digest_chunks(compilation: &Compilation) -> Vec> { let mut batches = vec![]; let mut visited_chunk_groups = HashSet::default(); let mut visited_chunks = HashSet::default(); let mut batch_chunk_groups = compilation.entrypoints().values().collect::>(); while !batch_chunk_groups.is_empty() { - let mut chunk_batch = HashSet::default(); + let mut chunk_batch = vec![]; + let mut chunk_runtime_batch = vec![]; for chunk_group in std::mem::take(&mut batch_chunk_groups) { if visited_chunk_groups.contains(chunk_group) { continue; @@ -208,15 +209,23 @@ fn digest_chunks(compilation: &Compilation) -> Vec> { if let Some(chunk_group) = compilation.chunk_group_by_ukey.get(chunk_group) { batch_chunk_groups.extend(chunk_group.children.iter()); batch_chunk_groups.extend(chunk_group.async_entrypoints_iterable()); - for chunk in chunk_group.chunks.iter() { - if visited_chunks.contains(chunk) { + for chunk_ukey in chunk_group.chunks.iter() { + if visited_chunks.contains(chunk_ukey) { continue; } - visited_chunks.insert(*chunk); - chunk_batch.insert(*chunk); + let Some(chunk) = compilation.chunk_by_ukey.get(chunk_ukey) else { + continue; + }; + visited_chunks.insert(*chunk_ukey); + if chunk.has_runtime(&compilation.chunk_group_by_ukey) { + chunk_runtime_batch.push(*chunk_ukey); + } else { + chunk_batch.push(*chunk_ukey); + } } } } + batches.push(chunk_runtime_batch); batches.push(chunk_batch); } batches.reverse(); diff --git a/crates/rspack_plugin_sri/src/runtime.rs b/crates/rspack_plugin_sri/src/runtime.rs index 444f82ab161e..da6fc8ffe5da 100644 --- a/crates/rspack_plugin_sri/src/runtime.rs +++ b/crates/rspack_plugin_sri/src/runtime.rs @@ -5,7 +5,6 @@ use rspack_core::{ }; use rspack_error::{Result, error}; use rspack_hook::plugin_hook; -use rspack_plugin_mf::{ConsumeSharedModule, ProvideSharedModule}; use rspack_plugin_runtime::{ CreateScriptData, LinkPreloadData, RuntimePluginCreateScript, RuntimePluginLinkPreload, }; @@ -83,10 +82,7 @@ impl RuntimeModule for SRIHashVariableRuntimeModule { .chunk_graph .get_chunk_modules(&c, &module_graph) .iter() - .any(|m| { - m.downcast_ref::().is_none() - && m.downcast_ref::().is_none() - }); + .any(|m| m.source().is_some()); if has_modules && include_chunks.contains_key(id) { Some(id) diff --git a/tests/rspack-test/configCases/sri/mf-splitting/async-chunk.js b/tests/rspack-test/configCases/sri/mf-splitting/async-chunk.js new file mode 100644 index 000000000000..51310aef6f5a --- /dev/null +++ b/tests/rspack-test/configCases/sri/mf-splitting/async-chunk.js @@ -0,0 +1,6 @@ +import load from 'mock'; + + +load( + () => import('./inside-async-chunk'), +); \ No newline at end of file diff --git a/tests/rspack-test/configCases/sri/mf-splitting/inside-async-chunk.js b/tests/rspack-test/configCases/sri/mf-splitting/inside-async-chunk.js new file mode 100644 index 000000000000..3f0477c59204 --- /dev/null +++ b/tests/rspack-test/configCases/sri/mf-splitting/inside-async-chunk.js @@ -0,0 +1,2 @@ +import Provider from 'mock-redux'; +Provider() \ No newline at end of file diff --git a/tests/rspack-test/configCases/sri/mf-splitting/main-entry.js b/tests/rspack-test/configCases/sri/mf-splitting/main-entry.js new file mode 100644 index 000000000000..38379d0252ba --- /dev/null +++ b/tests/rspack-test/configCases/sri/mf-splitting/main-entry.js @@ -0,0 +1,8 @@ +import load from 'mock'; + +load( + () => + import( + './async-chunk' + ) +); \ No newline at end of file diff --git a/tests/rspack-test/configCases/sri/mf-splitting/mfe-entry.js b/tests/rspack-test/configCases/sri/mf-splitting/mfe-entry.js new file mode 100644 index 000000000000..e4b66bb37e18 --- /dev/null +++ b/tests/rspack-test/configCases/sri/mf-splitting/mfe-entry.js @@ -0,0 +1 @@ +__webpack_public_path__ = `${document.currentScript.src}/../`; \ No newline at end of file diff --git a/tests/rspack-test/configCases/sri/mf-splitting/node_modules/mock-redux/index.js b/tests/rspack-test/configCases/sri/mf-splitting/node_modules/mock-redux/index.js new file mode 100644 index 000000000000..9bf823a9d254 --- /dev/null +++ b/tests/rspack-test/configCases/sri/mf-splitting/node_modules/mock-redux/index.js @@ -0,0 +1,3 @@ +module.exports = () => { + console.log('mock'); +}; \ No newline at end of file diff --git a/tests/rspack-test/configCases/sri/mf-splitting/node_modules/mock-redux/package.json b/tests/rspack-test/configCases/sri/mf-splitting/node_modules/mock-redux/package.json new file mode 100644 index 000000000000..f99dc50090d9 --- /dev/null +++ b/tests/rspack-test/configCases/sri/mf-splitting/node_modules/mock-redux/package.json @@ -0,0 +1,5 @@ +{ + "name": "mock-redux", + "version": "1.0.0", + "main": "index.js" +} \ No newline at end of file diff --git a/tests/rspack-test/configCases/sri/mf-splitting/node_modules/mock/index.js b/tests/rspack-test/configCases/sri/mf-splitting/node_modules/mock/index.js new file mode 100644 index 000000000000..9bf823a9d254 --- /dev/null +++ b/tests/rspack-test/configCases/sri/mf-splitting/node_modules/mock/index.js @@ -0,0 +1,3 @@ +module.exports = () => { + console.log('mock'); +}; \ No newline at end of file diff --git a/tests/rspack-test/configCases/sri/mf-splitting/node_modules/mock/package.json b/tests/rspack-test/configCases/sri/mf-splitting/node_modules/mock/package.json new file mode 100644 index 000000000000..e1bc9f9f0593 --- /dev/null +++ b/tests/rspack-test/configCases/sri/mf-splitting/node_modules/mock/package.json @@ -0,0 +1,5 @@ +{ + "name": "mock", + "version": "1.0.0", + "main": "index.js" +} \ No newline at end of file diff --git a/tests/rspack-test/configCases/sri/mf-splitting/rspack.config.js b/tests/rspack-test/configCases/sri/mf-splitting/rspack.config.js new file mode 100644 index 000000000000..8d3df08c68f5 --- /dev/null +++ b/tests/rspack-test/configCases/sri/mf-splitting/rspack.config.js @@ -0,0 +1,63 @@ +const rspack = require("@rspack/core"); +const { experiments } = rspack; +const { SubresourceIntegrityPlugin } = experiments; + +const createConfig = (runtimeChunk, mfPlugin) => ({ + mode: "production", + devtool: false, + target: "web", + entry: { + main: "./main-entry", + mfeEntry: "./mfe-entry", + }, + plugins: [ + new SubresourceIntegrityPlugin(), + mfPlugin && new rspack.container.ModuleFederationPlugin({ + name: "mfeEntry", + filename: 'mfe-chunk.js', + exposes: { + './mock': 'mock', + './mock-redux': 'mock-redux', + } + }), + ].filter(Boolean), + output: { + filename: `${runtimeChunk}-${mfPlugin ? "mf" : "no-mf"}-[name].js`, + crossOriginLoading: "anonymous", + }, + optimization: { + runtimeChunk: runtimeChunk, + splitChunks: { + cacheGroups: { + framework: { + test(m) { + const resource = m.nameForCondition?.(); + if (!resource) return false; + + const frameworkDeps = [ + "mock", + "mock-redux", + ]; + + const isFramework = frameworkDeps + .map((pkg) => `node_modules/${pkg}/`) + .some((dep) => resource.includes(dep)); + + return isFramework; + }, + name: "framework", + chunks: "all", + enforce: true, + }, + }, + }, + }, +}); + + +module.exports = [ + createConfig("single", true), + createConfig("single", false), + createConfig("multiple", true), + createConfig("multiple", false), +]; \ No newline at end of file diff --git a/tests/rspack-test/configCases/sri/mf-splitting/test.config.js b/tests/rspack-test/configCases/sri/mf-splitting/test.config.js new file mode 100644 index 000000000000..a63378f4bb06 --- /dev/null +++ b/tests/rspack-test/configCases/sri/mf-splitting/test.config.js @@ -0,0 +1,5 @@ +module.exports = { + findBundle: function () { + return []; + }, +}; \ No newline at end of file