From 854a79e99cdde1ebd7c483ee8418421436b24d19 Mon Sep 17 00:00:00 2001 From: fi3ework Date: Wed, 22 May 2024 14:47:00 +0800 Subject: [PATCH] feat: root module is less prone to be wrapped in IIFE --- .../src/plugin/mod.rs | 295 +++++++++++++++++- .../rspack_plugin_javascript/src/runtime.rs | 2 +- packages/rspack-cli/package.json | 2 +- .../tests/build/basic/public/main.js | 13 +- .../tests/build/basic/public/main.js.map | 2 +- packages/rspack-dev-server/package.json | 2 +- .../rspack-plugin-react-refresh/package.json | 2 +- packages/rspack-test-tools/package.json | 8 +- .../tests/__snapshots__/StatsAPI.test.js.snap | 10 +- .../__snapshots__/StatsOutput.test.js.snap | 32 +- .../tests/statsAPICases/exports.js | 4 +- .../chunkFilename-fullhash/expected/main.js | 4 - .../expected/main.js | 4 - .../expected/main.mjs | 4 - .../es-named-export-as-is/expected/main.js | 4 - .../expected/main.mjs | 4 - .../cases/es-named-export/expected/main.js | 4 - .../expected/main.js | 4 - .../expected/main.js | 4 - .../cases/export-only-locals/expected/main.js | 4 - .../cases/issue-6649/expected/main.js | 4 +- .../multiple-compiler/expected/one-main.js | 4 - .../multiple-compiler/expected/two-main.js | 4 - .../cases/new-url/expected/main.js | 4 - .../cases/no-runtime/expected/main.js | 4 - .../StatsTestCases.basictest.js.snap | 16 +- .../output-module/inlined-module/index.js | 18 ++ .../output-module/inlined-module/module1.js | 3 + .../output-module/inlined-module/module2.js | 3 + .../output-module/inlined-module/module3.js | 3 + .../inlined-module/webpack.config.js | 13 + 31 files changed, 371 insertions(+), 113 deletions(-) create mode 100644 webpack-test/configCases/output-module/inlined-module/index.js create mode 100644 webpack-test/configCases/output-module/inlined-module/module1.js create mode 100644 webpack-test/configCases/output-module/inlined-module/module2.js create mode 100644 webpack-test/configCases/output-module/inlined-module/module3.js create mode 100644 webpack-test/configCases/output-module/inlined-module/webpack.config.js diff --git a/crates/rspack_plugin_javascript/src/plugin/mod.rs b/crates/rspack_plugin_javascript/src/plugin/mod.rs index 7da9517af1ed..1d41c7863783 100644 --- a/crates/rspack_plugin_javascript/src/plugin/mod.rs +++ b/crates/rspack_plugin_javascript/src/plugin/mod.rs @@ -1,3 +1,6 @@ +use std::collections::{HashMap, HashSet}; +use std::ops::Deref; +use std::sync::Arc; pub mod api_plugin; mod drive; mod flag_dependency_exports_plugin; @@ -8,8 +11,8 @@ pub mod inner_graph_plugin; mod mangle_exports_plugin; pub mod module_concatenation_plugin; mod side_effects_flag_plugin; - use std::borrow::Cow; +use std::collections::hash_map::Entry; use std::hash::Hash; pub use drive::*; @@ -19,17 +22,28 @@ use indoc::indoc; pub use mangle_exports_plugin::*; pub use module_concatenation_plugin::*; use once_cell::sync::Lazy; -use rspack_core::rspack_sources::{BoxSource, ConcatSource, RawSource, SourceExt}; +use rspack_ast::javascript::Ast; +use rspack_core::concatenated_module::REGEX; +use rspack_core::reserved_names::RESERVED_NAMES; +use rspack_core::rspack_sources::{ + BoxSource, ConcatSource, RawSource, ReplaceSource, Source, SourceExt, +}; use rspack_core::{ - basic_function, render_init_fragments, ChunkInitFragments, ChunkRenderContext, ChunkUkey, - CodeGenerationDataTopLevelDeclarations, Compilation, CompilationId, ExportsArgument, - RuntimeGlobals, SourceType, + basic_function, render_init_fragments, ChunkGroupUkey, ChunkInitFragments, ChunkRenderContext, + ChunkUkey, CodeGenerationDataTopLevelDeclarations, Compilation, CompilationId, + ConcatenatedModuleIdent, ExportsArgument, Module, RuntimeGlobals, SourceType, SpanExt, Template, + DEFAULT_EXPORT, NAMESPACE_OBJECT_EXPORT, }; +use rspack_core::{BoxModule, IdentCollector}; use rspack_error::Result; use rspack_hash::RspackHash; use rspack_hook::plugin; +use rspack_identifier::IdentifierLinkedMap; use rspack_util::fx_hash::{BuildFxHasher, FxDashMap}; pub use side_effects_flag_plugin::*; +use swc_core::atoms::Atom; +use swc_core::common::{FileName, Spanned, SyntaxContext}; +use swc_core::ecma::transforms::base::resolver; use crate::runtime::{ render_chunk_modules, render_module, render_runtime_modules, stringify_array, @@ -42,6 +56,12 @@ static COMPILATION_DRIVES_MAP: Lazy, + module_scope_idents: Vec>, + used_in_non_inlined: Vec>, +} + impl JsPlugin { pub fn get_compilation_drives( compilation: &Compilation, @@ -525,16 +545,19 @@ impl JsPlugin { sources.add(RawSource::from("\"use strict\";\n")); } } - let chunk_modules = if let Some(inlined_modules) = inlined_modules { + + let chunk_modules: Vec<&Box> = if let Some(inlined_modules) = inlined_modules { all_modules + .clone() .into_iter() .filter(|m| !inlined_modules.contains_key(&m.identifier())) - .collect() + .collect::>() } else { - all_modules + all_modules.clone() }; + let chunk_modules_result = - render_chunk_modules(compilation, chunk_ukey, chunk_modules, all_strict)?; + render_chunk_modules(compilation, chunk_ukey, &chunk_modules, all_strict)?; let has_chunk_modules_result = chunk_modules_result.is_some(); if has_chunk_modules_result || runtime_requirements.contains(RuntimeGlobals::MODULE_FACTORIES) @@ -583,15 +606,34 @@ impl JsPlugin { "var {} = {{}};\n", RuntimeGlobals::EXPORTS ))); + + let renamed_inline_modules = self.rename_inline_modules( + &all_modules, + inlined_modules, + compilation, + chunk_ukey, + all_strict, + )?; + for (m_identifier, _) in inlined_modules { let m = module_graph .module_by_identifier(m_identifier) .expect("should have module"); - let Some((rendered_module, fragments, additional_fragments)) = + let Some((mut rendered_module, fragments, additional_fragments)) = render_module(compilation, chunk_ukey, m, all_strict, false)? else { continue; }; + + if renamed_inline_modules + .get(&m_identifier.to_string()) + .is_some() + { + if let Some(source) = renamed_inline_modules.get(&m_identifier.to_string()) { + rendered_module = source.clone(); + }; + } + chunk_init_fragments.extend(fragments); chunk_init_fragments.extend(additional_fragments); let inner_strict = !all_strict && m.build_info().expect("should have build_info").strict; @@ -608,8 +650,6 @@ impl JsPlugin { Some("it need to be in strict mode.".into()) } else if inlined_modules.len() > 1 { Some("it need to be isolated against other entry modules.".into()) - } else if has_chunk_modules_result { - Some("it need to be isolated against other modules in the chunk.".into()) } else if exports && !webpack_exports { Some(format!("it uses a non-standard name for the exports ({exports_argument}).").into()) } else { @@ -706,6 +746,190 @@ impl JsPlugin { }) } + pub fn rename_inline_modules( + &self, + all_modules: &[&BoxModule], + inlined_modules: &IdentifierLinkedMap, + compilation: &Compilation, + chunk_ukey: &ChunkUkey, + all_strict: bool, + ) -> Result>> { + let mut inlined_modules_to_info: HashMap = HashMap::new(); + let mut non_inlined_module_through_idents: Vec = Vec::new(); + let mut renamed_inline_modules: HashMap> = HashMap::new(); + let mut all_used_names: HashSet = + HashSet::from_iter(RESERVED_NAMES.iter().map(|item| item.to_string())); + + for m in all_modules.iter() { + let is_inlined_module = inlined_modules.contains_key(&m.identifier()); + + let Some((rendered_module, ..)) = + render_module(compilation, chunk_ukey, m, all_strict, false)? + else { + continue; + }; + + let code = rendered_module; + let cm: Arc = Default::default(); + let fm = cm.new_source_file( + FileName::Custom(m.identifier().to_string()), + code.source().to_string(), + ); + let comments = swc_node_comments::SwcComments::default(); + let mut errors = vec![]; + + let Ok(program) = swc_core::ecma::parser::parse_file_as_program( + &fm, + swc_core::ecma::parser::Syntax::default(), + swc_core::ecma::ast::EsVersion::EsNext, + Some(&comments), + &mut errors, + ) else { + continue; + }; + + let mut ast: Ast = Ast::new(program, cm, Some(comments)); + + let mut global_ctxt = SyntaxContext::empty(); + let mut module_ctxt = SyntaxContext::empty(); + + ast.transform(|program, context| { + global_ctxt = global_ctxt.apply_mark(context.unresolved_mark); + module_ctxt = module_ctxt.apply_mark(context.top_level_mark); + program.visit_mut_with(&mut resolver( + context.unresolved_mark, + context.top_level_mark, + false, + )); + }); + + let mut collector = IdentCollector::default(); + ast.visit(|program, _ctxt| { + program.visit_with(&mut collector); + }); + + if is_inlined_module { + let mut module_scope_idents = Vec::new(); + + for ident in collector.ids { + if ident.id.span.ctxt == global_ctxt + || ident.id.span.ctxt != module_ctxt + || ident.is_class_expr_with_ident + { + all_used_names.insert(ident.id.sym.to_string()); + } + + if ident.id.span.ctxt == module_ctxt { + all_used_names.insert(ident.id.sym.to_string()); + module_scope_idents.push(Arc::new(ident)); + } + } + + let ident: String = m.identifier().to_string(); + inlined_modules_to_info.insert( + ident, + InlinedModuleInfo { + source: code, + module_scope_idents, + used_in_non_inlined: Vec::new(), + }, + ); + } else { + for ident in collector.ids { + if ident.id.span.ctxt == global_ctxt { + all_used_names.insert(ident.id.sym.to_string()); + non_inlined_module_through_idents.push(ident); + } + } + } + } + + for (_ident, info) in inlined_modules_to_info.iter_mut() { + for module_scope_ident in info.module_scope_idents.iter() { + for non_inlined_module_through_ident in non_inlined_module_through_idents.iter() { + if module_scope_ident.id.sym == non_inlined_module_through_ident.id.sym { + info + .used_in_non_inlined + .push(Arc::clone(module_scope_ident)); + } + } + } + } + + for (module_id, inlined_module_info) in inlined_modules_to_info.iter() { + let InlinedModuleInfo { + source: _source, + module_scope_idents, + used_in_non_inlined, + } = inlined_module_info; + + let module = all_modules + .iter() + .find(|m| m.identifier().to_string() == *module_id) + .expect("should find the inlined module in all_modules"); + + let mut source: Arc = Arc::clone(_source); + + if used_in_non_inlined.is_empty() { + renamed_inline_modules.insert(module_id.to_string(), source); + continue; + } + + let mut binding_to_ref: HashMap<(Atom, SyntaxContext), Vec> = + HashMap::default(); + + for module_scope_ident in module_scope_idents.iter() { + match binding_to_ref.entry(( + module_scope_ident.id.sym.clone(), + module_scope_ident.id.span.ctxt, + )) { + Entry::Occupied(mut occ) => { + occ.get_mut().push(module_scope_ident.deref().clone()); + } + Entry::Vacant(vac) => { + vac.insert(vec![module_scope_ident.deref().clone()]); + } + }; + } + + for (id, refs) in binding_to_ref.iter() { + let name = &id.0; + let ident_used = !used_in_non_inlined + .iter() + .filter(|v| v.id.sym == *name) + .collect::>() + .is_empty(); + + if ident_used { + let context = compilation.options.context.clone(); + let readable_identifier = module.readable_identifier(&context).to_string(); + let new_name = Self::find_new_name(name, &all_used_names, None, &readable_identifier); + + let mut replace_source = ReplaceSource::new(Arc::clone(&source)); + for identifier in refs.iter() { + let span = identifier.id.span(); + let low = span.real_lo(); + let high = span.real_hi(); + + if identifier.shorthand { + replace_source.insert(high, &format!(": {}", new_name), None); + continue; + } + + replace_source.replace(low, high, &new_name, None); + } + + source = Arc::new(replace_source); + all_used_names.insert(new_name); + } + } + + renamed_inline_modules.insert(module_id.to_string(), Arc::clone(&source)); + } + + Ok(renamed_inline_modules) + } + pub async fn render_chunk( &self, compilation: &Compilation, @@ -739,7 +963,7 @@ impl JsPlugin { } } let (chunk_modules_source, chunk_init_fragments) = - render_chunk_modules(compilation, chunk_ukey, chunk_modules, all_strict)? + render_chunk_modules(compilation, chunk_ukey, &chunk_modules, all_strict)? .unwrap_or_else(|| (RawSource::from("{}").boxed(), Vec::new())); let chunk_modules_source = drive .render_chunk(RenderJsChunkArgs { @@ -802,6 +1026,51 @@ impl JsPlugin { startup.hash(hasher); allow_inline_startup.hash(hasher); } + + pub fn find_new_name( + old_name: &str, + used_names1: &HashSet, + used_names2: Option<&HashSet>, + extra_info: &str, + ) -> String { + let mut name = old_name.to_string(); + + if name == DEFAULT_EXPORT { + name = String::new(); + } + if name == NAMESPACE_OBJECT_EXPORT { + name = "namespaceObject".to_string(); + } + // Remove uncool stuff + let extra_info = REGEX.replace_all(extra_info, "").to_string(); + + let mut splitted_info: Vec<&str> = extra_info.split('/').collect(); + while let Some(info_part) = splitted_info.pop() { + name = format!("{}_{}", info_part, name); + let name_ident = Template::to_identifier(&name); + if !used_names1.contains(&name_ident) + && (used_names2.is_none() + || !used_names2 + .expect("should not be none") + .contains(&name_ident)) + { + return name_ident; + } + } + + let mut i = 0; + let mut name_with_number = Template::to_identifier(&format!("{}_{}", name, i)); + while used_names1.contains(&name_with_number) + || used_names2 + .map(|map| map.contains(&name_with_number)) + .unwrap_or_default() + { + i += 1; + name_with_number = Template::to_identifier(&format!("{}_{}", name, i)); + } + + name_with_number + } } #[derive(Debug, Clone)] diff --git a/crates/rspack_plugin_javascript/src/runtime.rs b/crates/rspack_plugin_javascript/src/runtime.rs index ec8da44b71fa..8e7bc5a38dc8 100644 --- a/crates/rspack_plugin_javascript/src/runtime.rs +++ b/crates/rspack_plugin_javascript/src/runtime.rs @@ -13,7 +13,7 @@ use crate::{JsPlugin, RenderJsModuleContentArgs}; pub fn render_chunk_modules( compilation: &Compilation, chunk_ukey: &ChunkUkey, - ordered_modules: Vec<&BoxModule>, + ordered_modules: &Vec<&BoxModule>, all_strict: bool, ) -> Result> { let mut module_code_array = ordered_modules diff --git a/packages/rspack-cli/package.json b/packages/rspack-cli/package.json index 1fb4bf90298b..05ff2ccea07b 100644 --- a/packages/rspack-cli/package.json +++ b/packages/rspack-cli/package.json @@ -11,7 +11,7 @@ "scripts": { "build": "tsc -b ./tsconfig.build.json", "dev": "tsc -b -w", - "test": "cross-env jest --runInBand" + "test": "cross-env jest --runInBand --colors" }, "files": [ "bin", diff --git a/packages/rspack-cli/tests/build/basic/public/main.js b/packages/rspack-cli/tests/build/basic/public/main.js index 14108a36bcb7..ab111f86de68 100644 --- a/packages/rspack-cli/tests/build/basic/public/main.js +++ b/packages/rspack-cli/tests/build/basic/public/main.js @@ -1,6 +1,7 @@ -(() => { - // webpackBootstrap - var __webpack_exports__ = {}; - console.log("CONFIG"); -})(); -//# sourceMappingURL=main.js.map +(() => { // webpackBootstrap +var __webpack_exports__ = {}; +console.log("CONFIG"); + +})() +; +//# sourceMappingURL=main.js.map \ No newline at end of file diff --git a/packages/rspack-cli/tests/build/basic/public/main.js.map b/packages/rspack-cli/tests/build/basic/public/main.js.map index acb555904f49..c3c7043c3cd6 100644 --- a/packages/rspack-cli/tests/build/basic/public/main.js.map +++ b/packages/rspack-cli/tests/build/basic/public/main.js.map @@ -1 +1 @@ -{"version":3,"file":"main.js","sources":["webpack:///./src/entry.js"],"sourcesContent":["console.log(\"CONFIG\");\n"],"names":[],"mappings":";;AAAA,QAAQ,GAAG,CAAC"} \ No newline at end of file +{"version":3,"file":"main.js","sources":["webpack:///./src/entry.js"],"sourcesContent":["console.log(\"CONFIG\");\n"],"names":[],"mappings":";;AAAA"} \ No newline at end of file diff --git a/packages/rspack-dev-server/package.json b/packages/rspack-dev-server/package.json index 8fea8fa18fcd..3e612e4a5777 100644 --- a/packages/rspack-dev-server/package.json +++ b/packages/rspack-dev-server/package.json @@ -16,7 +16,7 @@ "scripts": { "build": "tsc -b ./tsconfig.build.json", "dev": "tsc -w -b ./tsconfig.build.json", - "test": "rimraf .test-temp && jest --runInBand", + "test": "rimraf .test-temp && jest --runInBand --colors", "api-extractor": "api-extractor run --verbose", "api-extractor:ci": "api-extractor run --verbose || diff temp/api.md etc/api.md" }, diff --git a/packages/rspack-plugin-react-refresh/package.json b/packages/rspack-plugin-react-refresh/package.json index 6dee888a8ef4..d8bbc3592ca7 100644 --- a/packages/rspack-plugin-react-refresh/package.json +++ b/packages/rspack-plugin-react-refresh/package.json @@ -16,7 +16,7 @@ "scripts": { "build": "tsc -b ./tsconfig.build.json", "dev": "tsc -b -w", - "test": "jest --runInBand", + "test": "jest --runInBand --colors", "api-extractor": "api-extractor run --verbose", "api-extractor:ci": "api-extractor run --verbose || diff temp/api.md etc/api.md" }, diff --git a/packages/rspack-test-tools/package.json b/packages/rspack-test-tools/package.json index 253b7dbc71ef..4e46eafcac45 100644 --- a/packages/rspack-test-tools/package.json +++ b/packages/rspack-test-tools/package.json @@ -17,10 +17,10 @@ "dev:viewer": "rspack serve", "dev": "tsc -b -w", "test": "sh -c 'run-s \"test:* -- $*\"' sh", - "testu": "sh -c 'run-s \"test:* -- $*\"' sh -u", - "test:base": "cross-env NO_COLOR=1 node --expose-gc --max-old-space-size=8192 --experimental-vm-modules ../../node_modules/jest-cli/bin/jest --logHeapUsage --config ./jest.config.js --passWithNoTests", - "test:hot": "cross-env RSPACK_HOT_TEST=true NO_COLOR=1 node --expose-gc --max-old-space-size=8192 --experimental-vm-modules ../../node_modules/jest-cli/bin/jest --logHeapUsage --config ./jest.config.hot.js --passWithNoTests", - "test:diff": "cross-env RSPACK_DIFF=true NO_COLOR=1 node --expose-gc --max-old-space-size=8192 --experimental-vm-modules ../../node_modules/jest-cli/bin/jest --logHeapUsage --config ./jest.config.diff.js --passWithNoTests", + "testu": "sh -c 'run-s \"test:* -u -- $*\"' sh", + "test:base": "cross-env NO_COLOR=1 node --expose-gc --max-old-space-size=8192 --experimental-vm-modules ../../node_modules/jest-cli/bin/jest --logHeapUsage --colors --config ./jest.config.js --passWithNoTests", + "test:hot": "cross-env RSPACK_HOT_TEST=true NO_COLOR=1 node --expose-gc --max-old-space-size=8192 --experimental-vm-modules ../../node_modules/jest-cli/bin/jest --logHeapUsage --colors --config ./jest.config.hot.js --passWithNoTests", + "test:diff": "cross-env RSPACK_DIFF=true NO_COLOR=1 node --expose-gc --max-old-space-size=8192 --experimental-vm-modules ../../node_modules/jest-cli/bin/jest --logHeapUsage --colors --config ./jest.config.diff.js --passWithNoTests", "api-extractor": "api-extractor run --verbose", "api-extractor:ci": "api-extractor run --verbose || diff temp/api.md etc/api.md" }, diff --git a/packages/rspack-test-tools/tests/__snapshots__/StatsAPI.test.js.snap b/packages/rspack-test-tools/tests/__snapshots__/StatsAPI.test.js.snap index 26efb58bedca..4a237f281556 100644 --- a/packages/rspack-test-tools/tests/__snapshots__/StatsAPI.test.js.snap +++ b/packages/rspack-test-tools/tests/__snapshots__/StatsAPI.test.js.snap @@ -192,7 +192,7 @@ Object { "hotModuleReplacement": false, }, "name": "main.js", - "size": 714, + "size": 704, "type": "asset", }, ], @@ -401,10 +401,10 @@ Object { "assets": Array [ Object { "name": "main.js", - "size": 714, + "size": 704, }, ], - "assetsSize": 714, + "assetsSize": 704, "chunks": Array [ "909", ], @@ -661,10 +661,10 @@ Object { "assets": Array [ Object { "name": "main.js", - "size": 714, + "size": 704, }, ], - "assetsSize": 714, + "assetsSize": 704, "chunks": Array [ "909", ], diff --git a/packages/rspack-test-tools/tests/__snapshots__/StatsOutput.test.js.snap b/packages/rspack-test-tools/tests/__snapshots__/StatsOutput.test.js.snap index ad4f3dde925b..f6b68547724c 100644 --- a/packages/rspack-test-tools/tests/__snapshots__/StatsOutput.test.js.snap +++ b/packages/rspack-test-tools/tests/__snapshots__/StatsOutput.test.js.snap @@ -3,8 +3,8 @@ exports[`statsOutput statsOutput/auxiliary-files-test should print correct stats for 1`] = ` "PublicPath: auto asset a09d8e0f399c215faa79.png 7 bytes {909} [emitted] [from: raw.png] (name: main) -asset bundle.js 2.58 KiB {909} [emitted] (name: main) -Entrypoint main 2.58 KiB = bundle.js +asset bundle.js 2.46 KiB {909} [emitted] (name: main) +Entrypoint main 2.46 KiB = bundle.js chunk {909} bundle.js (main) [entry] ./raw.png [193] {909} [no exports] @@ -125,8 +125,8 @@ Rspack compiled with 2 errors" exports[`statsOutput statsOutput/limit-chunk-count-plugin should print correct stats for 1`] = ` "1 chunks: PublicPath: auto - asset bundle1.js 3.69 KiB [emitted] (name: main) - Entrypoint main 3.69 KiB = bundle1.js + asset bundle1.js 3.57 KiB [emitted] (name: main) + Entrypoint main 3.57 KiB = bundle1.js chunk bundle1.js (main) <{909}> >{909}< [entry] ./b.js ./c.js @@ -138,8 +138,8 @@ exports[`statsOutput statsOutput/limit-chunk-count-plugin should print correct s 2 chunks: PublicPath: auto asset 76.bundle2.js 497 bytes [emitted] (name: c) - asset bundle2.js 10.3 KiB [emitted] (name: main) - Entrypoint main 10.3 KiB = bundle2.js + asset bundle2.js 10.2 KiB [emitted] (name: main) + Entrypoint main 10.2 KiB = bundle2.js chunk 76.bundle2.js (c) <{76}> <{909}> >{76}< ./c.js ./d.js @@ -153,8 +153,8 @@ exports[`statsOutput statsOutput/limit-chunk-count-plugin should print correct s PublicPath: auto asset 345.bundle3.js 186 bytes [emitted] asset 76.bundle3.js 387 bytes [emitted] (name: c) - asset bundle3.js 10.3 KiB [emitted] (name: main) - Entrypoint main 10.3 KiB = bundle3.js + asset bundle3.js 10.2 KiB [emitted] (name: main) + Entrypoint main 10.2 KiB = bundle3.js chunk 345.bundle3.js <{76}> ./d.js ./e.js @@ -170,8 +170,8 @@ exports[`statsOutput statsOutput/limit-chunk-count-plugin should print correct s asset 697.bundle4.js 130 bytes [emitted] asset 753.bundle4.js 130 bytes [emitted] asset 76.bundle4.js 387 bytes [emitted] (name: c) - asset bundle4.js 10.3 KiB [emitted] (name: main) - Entrypoint main 10.3 KiB = bundle4.js + asset bundle4.js 10.2 KiB [emitted] (name: main) + Entrypoint main 10.2 KiB = bundle4.js chunk 697.bundle4.js <{76}> ./e.js chunk 753.bundle4.js <{76}> @@ -316,11 +316,11 @@ runtime modules 12 modules ./index.js ERROR in × asset size limit: The following asset(s) exceed the recommended size limit (244.141 KiB). This can impact web performance.Assets: - │ main.js (303.479 KiB) + │ main.js (303.354 KiB) ERROR in × entrypoint size limit: The following entrypoint(s) combined asset size exceeds the recommended limit (244.141 KiB). This can impact web performance.Entrypoints: - │ main (303.479 KiB) + │ main (303.354 KiB) │ main.js @@ -405,8 +405,8 @@ webpack/runtime/define_property_getters" exports[`statsOutput statsOutput/runtime-specific-exports should print correct stats for 1`] = ` "PublicPath: auto -asset main.js 1.8 KiB [emitted] (name: main) -Entrypoint main 1.8 KiB = main.js +asset main.js 1.67 KiB [emitted] (name: main) +Entrypoint main 1.67 KiB = main.js ./math.js [exports: add, multiply] [only some exports used: add] @@ -421,8 +421,8 @@ Rspack x.x.x compiled successfully in X s (df258688ac5f176fb388)" exports[`statsOutput statsOutput/side-effects-bailouts should print correct stats for 1`] = ` "PublicPath: auto -asset main.js 1.86 KiB {909} [emitted] (name: main) -Entrypoint main 1.86 KiB = main.js +asset main.js 1.73 KiB {909} [emitted] (name: main) +Entrypoint main 1.73 KiB = main.js chunk {909} main.js (main) [entry] ./lib.js [467] {909} [exports: test] diff --git a/packages/rspack-test-tools/tests/statsAPICases/exports.js b/packages/rspack-test-tools/tests/statsAPICases/exports.js index ad090767f19c..f2a1c212a9e0 100644 --- a/packages/rspack-test-tools/tests/statsAPICases/exports.js +++ b/packages/rspack-test-tools/tests/statsAPICases/exports.js @@ -25,8 +25,8 @@ module.exports = { expect(stats?.toJson(statsOptions)).toMatchSnapshot(); expect(stats?.toString(statsOptions)).toMatchInlineSnapshot(` "PublicPath: auto - asset main.js 714 bytes [emitted] (name: main) - Entrypoint main 714 bytes = main.js + asset main.js 704 bytes [emitted] (name: main) + Entrypoint main 704 bytes = main.js runtime modules 3 modules ./fixtures/esm/a.js [exports: a, default] diff --git a/plugin-test/css-extract/cases/chunkFilename-fullhash/expected/main.js b/plugin-test/css-extract/cases/chunkFilename-fullhash/expected/main.js index 50f01188688e..ef8929c4bfe0 100644 --- a/plugin-test/css-extract/cases/chunkFilename-fullhash/expected/main.js +++ b/plugin-test/css-extract/cases/chunkFilename-fullhash/expected/main.js @@ -390,8 +390,6 @@ chunkLoadingGlobal.push = webpackJsonpCallback.bind( })(); /************************************************************************/ var __webpack_exports__ = {}; -// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. -(() => { __webpack_require__.r(__webpack_exports__); /* harmony import */var _style_css__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./style.css?b16f"); @@ -399,7 +397,5 @@ __webpack_require__.r(__webpack_exports__); /* eslint-disable-next-line no-unused-expressions */ __webpack_require__.e(/* import() | async */ "async").then(__webpack_require__.bind(__webpack_require__, "./async.css?833a")); -})(); - })() ; \ No newline at end of file diff --git a/plugin-test/css-extract/cases/custom-loader-with-functional-exports/expected/main.js b/plugin-test/css-extract/cases/custom-loader-with-functional-exports/expected/main.js index 08b151dc2ab9..deb97bbd7e31 100644 --- a/plugin-test/css-extract/cases/custom-loader-with-functional-exports/expected/main.js +++ b/plugin-test/css-extract/cases/custom-loader-with-functional-exports/expected/main.js @@ -71,8 +71,6 @@ __webpack_require__.r = function(exports) { })(); /************************************************************************/ var __webpack_exports__ = {}; -// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. -(() => { __webpack_require__.r(__webpack_exports__); /* harmony import */var _style_css__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./style.css?3e20"); @@ -80,7 +78,5 @@ __webpack_require__.r(__webpack_exports__); // eslint-disable-next-line no-console console.log((0,_style_css__WEBPACK_IMPORTED_MODULE_0__.cnA)(), (0,_style_css__WEBPACK_IMPORTED_MODULE_0__.cnB)()); -})(); - })() ; \ No newline at end of file diff --git a/plugin-test/css-extract/cases/es-named-export-as-is-output-module/expected/main.mjs b/plugin-test/css-extract/cases/es-named-export-as-is-output-module/expected/main.mjs index 78565c6d6c8c..ed75d321a418 100644 --- a/plugin-test/css-extract/cases/es-named-export-as-is-output-module/expected/main.mjs +++ b/plugin-test/css-extract/cases/es-named-export-as-is-output-module/expected/main.mjs @@ -71,8 +71,6 @@ __webpack_require__.r = function(exports) { })(); /************************************************************************/ var __webpack_exports__ = {}; -// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. -(() => { __webpack_require__.r(__webpack_exports__); /* harmony import */var _style_css__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./style.css?eccb"); @@ -80,5 +78,3 @@ __webpack_require__.r(__webpack_exports__); // eslint-disable-next-line no-console console.log({ css: _style_css__WEBPACK_IMPORTED_MODULE_0__["default"], aClass: _style_css__WEBPACK_IMPORTED_MODULE_0__["a-class"], bClass: _style_css__WEBPACK_IMPORTED_MODULE_0__.b__class, cClass: _style_css__WEBPACK_IMPORTED_MODULE_0__.cClass }); -})(); - diff --git a/plugin-test/css-extract/cases/es-named-export-as-is/expected/main.js b/plugin-test/css-extract/cases/es-named-export-as-is/expected/main.js index 907643fee584..178b8299a9b1 100644 --- a/plugin-test/css-extract/cases/es-named-export-as-is/expected/main.js +++ b/plugin-test/css-extract/cases/es-named-export-as-is/expected/main.js @@ -73,8 +73,6 @@ __webpack_require__.r = function(exports) { })(); /************************************************************************/ var __webpack_exports__ = {}; -// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. -(() => { __webpack_require__.r(__webpack_exports__); /* harmony import */var _style_css__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./style.css?eccb"); @@ -82,7 +80,5 @@ __webpack_require__.r(__webpack_exports__); // eslint-disable-next-line no-console console.log({ css: _style_css__WEBPACK_IMPORTED_MODULE_0__["default"], aClass: _style_css__WEBPACK_IMPORTED_MODULE_0__["a-class"], bClass: _style_css__WEBPACK_IMPORTED_MODULE_0__.b__class, cClass: _style_css__WEBPACK_IMPORTED_MODULE_0__.cClass }); -})(); - })() ; \ No newline at end of file diff --git a/plugin-test/css-extract/cases/es-named-export-output-module/expected/main.mjs b/plugin-test/css-extract/cases/es-named-export-output-module/expected/main.mjs index 94a21b897cfe..edd49bde1fc3 100644 --- a/plugin-test/css-extract/cases/es-named-export-output-module/expected/main.mjs +++ b/plugin-test/css-extract/cases/es-named-export-output-module/expected/main.mjs @@ -71,8 +71,6 @@ __webpack_require__.r = function(exports) { })(); /************************************************************************/ var __webpack_exports__ = {}; -// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. -(() => { __webpack_require__.r(__webpack_exports__); /* harmony import */var _style_css__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./style.css?eccb"); @@ -80,5 +78,3 @@ __webpack_require__.r(__webpack_exports__); // eslint-disable-next-line no-console console.log({ css: _style_css__WEBPACK_IMPORTED_MODULE_0__["default"], aClass: _style_css__WEBPACK_IMPORTED_MODULE_0__.aClass, bClass: _style_css__WEBPACK_IMPORTED_MODULE_0__.bClass, cClass: _style_css__WEBPACK_IMPORTED_MODULE_0__.cClass }); -})(); - diff --git a/plugin-test/css-extract/cases/es-named-export/expected/main.js b/plugin-test/css-extract/cases/es-named-export/expected/main.js index f2d0cbf03d12..f65903de27d3 100644 --- a/plugin-test/css-extract/cases/es-named-export/expected/main.js +++ b/plugin-test/css-extract/cases/es-named-export/expected/main.js @@ -73,8 +73,6 @@ __webpack_require__.r = function(exports) { })(); /************************************************************************/ var __webpack_exports__ = {}; -// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. -(() => { __webpack_require__.r(__webpack_exports__); /* harmony import */var _style_css__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./style.css?eccb"); @@ -82,7 +80,5 @@ __webpack_require__.r(__webpack_exports__); // eslint-disable-next-line no-console console.log({ css: _style_css__WEBPACK_IMPORTED_MODULE_0__["default"], aClass: _style_css__WEBPACK_IMPORTED_MODULE_0__.aClass, bClass: _style_css__WEBPACK_IMPORTED_MODULE_0__.bClass, cClass: _style_css__WEBPACK_IMPORTED_MODULE_0__.cClass }); -})(); - })() ; \ No newline at end of file diff --git a/plugin-test/css-extract/cases/export-only-locals-and-es-named-export/expected/main.js b/plugin-test/css-extract/cases/export-only-locals-and-es-named-export/expected/main.js index 15981c5a215e..257ac6741daa 100644 --- a/plugin-test/css-extract/cases/export-only-locals-and-es-named-export/expected/main.js +++ b/plugin-test/css-extract/cases/export-only-locals-and-es-named-export/expected/main.js @@ -73,8 +73,6 @@ __webpack_require__.r = function(exports) { })(); /************************************************************************/ var __webpack_exports__ = {}; -// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. -(() => { __webpack_require__.r(__webpack_exports__); /* harmony import */var _style_css__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./style.css"); @@ -82,7 +80,5 @@ __webpack_require__.r(__webpack_exports__); // eslint-disable-next-line no-console console.log({ aClass: _style_css__WEBPACK_IMPORTED_MODULE_0__.aClass, bClass: _style_css__WEBPACK_IMPORTED_MODULE_0__.bClass, cClass: _style_css__WEBPACK_IMPORTED_MODULE_0__.cClass }); -})(); - })() ; \ No newline at end of file diff --git a/plugin-test/css-extract/cases/export-only-locals-commonjs/expected/main.js b/plugin-test/css-extract/cases/export-only-locals-commonjs/expected/main.js index dade46e86f27..eeb0efda071a 100644 --- a/plugin-test/css-extract/cases/export-only-locals-commonjs/expected/main.js +++ b/plugin-test/css-extract/cases/export-only-locals-commonjs/expected/main.js @@ -47,8 +47,6 @@ __webpack_require__.r = function(exports) { })(); /************************************************************************/ var __webpack_exports__ = {}; -// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. -(() => { __webpack_require__.r(__webpack_exports__); /* harmony import */var _style_css__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./style.css"); @@ -56,7 +54,5 @@ __webpack_require__.r(__webpack_exports__); // eslint-disable-next-line no-console console.log({ aClass: _style_css__WEBPACK_IMPORTED_MODULE_0__.aClass, bClass: _style_css__WEBPACK_IMPORTED_MODULE_0__.bClass, cClass: _style_css__WEBPACK_IMPORTED_MODULE_0__.cClass }); -})(); - })() ; \ No newline at end of file diff --git a/plugin-test/css-extract/cases/export-only-locals/expected/main.js b/plugin-test/css-extract/cases/export-only-locals/expected/main.js index dade46e86f27..eeb0efda071a 100644 --- a/plugin-test/css-extract/cases/export-only-locals/expected/main.js +++ b/plugin-test/css-extract/cases/export-only-locals/expected/main.js @@ -47,8 +47,6 @@ __webpack_require__.r = function(exports) { })(); /************************************************************************/ var __webpack_exports__ = {}; -// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. -(() => { __webpack_require__.r(__webpack_exports__); /* harmony import */var _style_css__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./style.css"); @@ -56,7 +54,5 @@ __webpack_require__.r(__webpack_exports__); // eslint-disable-next-line no-console console.log({ aClass: _style_css__WEBPACK_IMPORTED_MODULE_0__.aClass, bClass: _style_css__WEBPACK_IMPORTED_MODULE_0__.bClass, cClass: _style_css__WEBPACK_IMPORTED_MODULE_0__.cClass }); -})(); - })() ; \ No newline at end of file diff --git a/plugin-test/css-extract/cases/issue-6649/expected/main.js b/plugin-test/css-extract/cases/issue-6649/expected/main.js index 12d2ad2f6718..5052ce3d6dc7 100644 --- a/plugin-test/css-extract/cases/issue-6649/expected/main.js +++ b/plugin-test/css-extract/cases/issue-6649/expected/main.js @@ -89,7 +89,7 @@ __webpack_require__.e = function (chunkId) { // return url for filenames not based on template // return url for filenames based on template - return "" + chunkId + ".$" + {"\\css\\chunk": "b88d395b0e288c1b8cfe","\\js\\chunk": "5dc72ab590cca7957d71",}[chunkId] + "$.js"; + return "" + chunkId + ".$" + {"\\css\\chunk": "a6681fb0036ba5fc970a","\\js\\chunk": "fed3c082f6312f1983aa",}[chunkId] + "$.js"; }; })(); @@ -107,7 +107,7 @@ __webpack_require__.e = function (chunkId) { // webpack/runtime/get_full_hash (() => { __webpack_require__.h = function () { - return "a0870bd6e64301212efb"; + return "fefca101f5f5eed780fa"; }; })(); diff --git a/plugin-test/css-extract/cases/multiple-compiler/expected/one-main.js b/plugin-test/css-extract/cases/multiple-compiler/expected/one-main.js index 68cf256195fe..913796aba0c1 100644 --- a/plugin-test/css-extract/cases/multiple-compiler/expected/one-main.js +++ b/plugin-test/css-extract/cases/multiple-compiler/expected/one-main.js @@ -47,13 +47,9 @@ __webpack_require__.r = function(exports) { })(); /************************************************************************/ var __webpack_exports__ = {}; -// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. -(() => { __webpack_require__.r(__webpack_exports__); /* harmony import */var _style_css__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./style.css?b16f"); -})(); - })() ; \ No newline at end of file diff --git a/plugin-test/css-extract/cases/multiple-compiler/expected/two-main.js b/plugin-test/css-extract/cases/multiple-compiler/expected/two-main.js index 68cf256195fe..913796aba0c1 100644 --- a/plugin-test/css-extract/cases/multiple-compiler/expected/two-main.js +++ b/plugin-test/css-extract/cases/multiple-compiler/expected/two-main.js @@ -47,13 +47,9 @@ __webpack_require__.r = function(exports) { })(); /************************************************************************/ var __webpack_exports__ = {}; -// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. -(() => { __webpack_require__.r(__webpack_exports__); /* harmony import */var _style_css__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./style.css?b16f"); -})(); - })() ; \ No newline at end of file diff --git a/plugin-test/css-extract/cases/new-url/expected/main.js b/plugin-test/css-extract/cases/new-url/expected/main.js index 3a5dfc46f470..aaba9f232e2a 100644 --- a/plugin-test/css-extract/cases/new-url/expected/main.js +++ b/plugin-test/css-extract/cases/new-url/expected/main.js @@ -67,13 +67,9 @@ __webpack_require__.b = document.baseURI || self.location.href; })(); /************************************************************************/ var __webpack_exports__ = {}; -// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. -(() => { const myURL = new URL(/* asset import */__webpack_require__("./style.css?b16f"), __webpack_require__.b); console.log(myURL); -})(); - })() ; \ No newline at end of file diff --git a/plugin-test/css-extract/cases/no-runtime/expected/main.js b/plugin-test/css-extract/cases/no-runtime/expected/main.js index e00a2dffe342..8b1ba1e412b9 100644 --- a/plugin-test/css-extract/cases/no-runtime/expected/main.js +++ b/plugin-test/css-extract/cases/no-runtime/expected/main.js @@ -281,15 +281,11 @@ chunkLoadingGlobal.push = webpackJsonpCallback.bind( })(); /************************************************************************/ var __webpack_exports__ = {}; -// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. -(() => { __webpack_require__.r(__webpack_exports__); /* harmony import */var _style_css__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./style.css?b16f"); __webpack_require__.e(/* import() | async */ "async").then(__webpack_require__.bind(__webpack_require__, "./async.css?833a")); -})(); - })() ; \ No newline at end of file diff --git a/webpack-test/__snapshots__/StatsTestCases.basictest.js.snap b/webpack-test/__snapshots__/StatsTestCases.basictest.js.snap index 4f1e90b76863..e5ffb538cf6b 100644 --- a/webpack-test/__snapshots__/StatsTestCases.basictest.js.snap +++ b/webpack-test/__snapshots__/StatsTestCases.basictest.js.snap @@ -80,9 +80,9 @@ Rspack x.x.x compiled with 3 warnings in X s (4a7903c5017e2488a0e8)" exports[`StatsTestCases should print correct stats for performance-no-async-chunks-shown 1`] = ` "PublicPath: auto asset main.js 294 KiB [emitted] (name: main) -asset sec.js 1.16 KiB [emitted] (name: sec) +asset sec.js 1.04 KiB [emitted] (name: sec) Entrypoint main 294 KiB = main.js -Entrypoint sec 1.16 KiB = sec.js +Entrypoint sec 1.04 KiB = sec.js ./a.js ./b.js ./c.js @@ -92,12 +92,12 @@ Entrypoint sec 1.16 KiB = sec.js WARNING in asset size limit: The following asset(s) exceed the recommended size limit (244.141 KiB). This can impact web performance. Assets: - main.js (294.045 KiB) + main.js (293.921 KiB) WARNING in entrypoint size limit: The following entrypoint(s) combined asset size exceeds the recommended limit (244.141 KiB). This can impact web performance. Entrypoints: - main (294.045 KiB) + main (293.921 KiB) main.js @@ -121,15 +121,15 @@ Entrypoint sec 294 KiB = sec.js ERROR in × asset size limit: The following asset(s) exceed the recommended size limit (244.141 KiB). This can impact web performance. Assets: - main.js (293.965 KiB) - sec.js (293.965 KiB) + main.js (293.841 KiB) + sec.js (293.841 KiB) ERROR in × entrypoint size limit: The following entrypoint(s) combined asset size exceeds the recommended limit (244.141 KiB). This can impact web performance. Entrypoints: - main (293.965 KiB) + main (293.841 KiB) main.js - sec (293.965 KiB) + sec (293.841 KiB) sec.js diff --git a/webpack-test/configCases/output-module/inlined-module/index.js b/webpack-test/configCases/output-module/inlined-module/index.js new file mode 100644 index 000000000000..d528599c4d36 --- /dev/null +++ b/webpack-test/configCases/output-module/inlined-module/index.js @@ -0,0 +1,18 @@ +import { value as v1 } from "./module1"; +const v2 = require("./module2") +const module3Inc = require("./module3") + +var value = 42; + +function inc() { + value++; +} + +it("single inlined module should not be wrapped in IIFE", () => { + expect(value).toBe(42); + expect(v1).toBe(undefined); + expect(v2).toBe(undefined); + expect(module3Inc).toBe(undefined); + inc(); + expect(value).toBe(43); +}); diff --git a/webpack-test/configCases/output-module/inlined-module/module1.js b/webpack-test/configCases/output-module/inlined-module/module1.js new file mode 100644 index 000000000000..67ebbe022de7 --- /dev/null +++ b/webpack-test/configCases/output-module/inlined-module/module1.js @@ -0,0 +1,3 @@ +let value; + +export { value }; diff --git a/webpack-test/configCases/output-module/inlined-module/module2.js b/webpack-test/configCases/output-module/inlined-module/module2.js new file mode 100644 index 000000000000..3e533c777ea8 --- /dev/null +++ b/webpack-test/configCases/output-module/inlined-module/module2.js @@ -0,0 +1,3 @@ +let value + +module.exports = value diff --git a/webpack-test/configCases/output-module/inlined-module/module3.js b/webpack-test/configCases/output-module/inlined-module/module3.js new file mode 100644 index 000000000000..5b457b1be859 --- /dev/null +++ b/webpack-test/configCases/output-module/inlined-module/module3.js @@ -0,0 +1,3 @@ +let inc + +module.exports = inc diff --git a/webpack-test/configCases/output-module/inlined-module/webpack.config.js b/webpack-test/configCases/output-module/inlined-module/webpack.config.js new file mode 100644 index 000000000000..61f4abca9763 --- /dev/null +++ b/webpack-test/configCases/output-module/inlined-module/webpack.config.js @@ -0,0 +1,13 @@ +/** @type {import("../../../../").Configuration} */ +module.exports = { + output: { + module: true + }, + optimization: { + concatenateModules: true + }, + experiments: { + outputModule: true + }, + target: "es2020" +};