From 3c0a94e46d50aac6efc2088f678af679a02aa448 Mon Sep 17 00:00:00 2001 From: "zhanghang.heal" Date: Fri, 24 Oct 2025 11:10:19 +0800 Subject: [PATCH 01/87] feat: treeshake share --- Cargo.lock | 1 + crates/node_binding/napi-binding.d.ts | 31 + .../src/plugins/interceptor.rs | 3 +- .../src/raw_options/raw_builtins/mod.rs | 34 +- .../src/raw_options/raw_builtins/raw_mf.rs | 105 +++- crates/rspack_core/src/compilation/mod.rs | 8 + .../src/dependency/dependency_type.rs | 6 + crates/rspack_core/src/dependency/mod.rs | 10 +- crates/rspack_core/src/lib.rs | 6 + crates/rspack_plugin_javascript/Cargo.toml | 1 + .../esm/esm_import_specifier_dependency.rs | 79 ++- .../plugin/flag_dependency_usage_plugin.rs | 67 ++- crates/rspack_plugin_mf/src/lib.rs | 6 + crates/rspack_plugin_mf/src/manifest/data.rs | 22 +- crates/rspack_plugin_mf/src/manifest/mod.rs | 7 +- crates/rspack_plugin_mf/src/manifest/utils.rs | 1 + .../sharing/collect_shared_entry_plugin.rs | 232 ++++++++ .../src/sharing/consume_shared_module.rs | 1 + .../src/sharing/consume_shared_plugin.rs | 33 +- .../sharing/consume_shared_runtime_module.rs | 4 +- crates/rspack_plugin_mf/src/sharing/mod.rs | 9 + .../src/sharing/provide_shared_dependency.rs | 3 + .../src/sharing/provide_shared_module.rs | 8 + .../sharing/provide_shared_module_factory.rs | 1 + .../src/sharing/provide_shared_plugin.rs | 9 + .../src/sharing/share_runtime_module.rs | 4 +- .../sharing/shared_container_dependency.rs | 71 +++ .../shared_container_entry_dependency.rs | 78 +++ .../sharing/shared_container_entry_module.rs | 268 +++++++++ .../shared_container_entry_module_factory.rs | 26 + .../src/sharing/shared_container_plugin.rs | 107 ++++ .../shared_container_runtime_module.rs | 40 ++ .../shared_used_exports_optimizer_plugin.rs | 546 ++++++++++++++++++ ...d_used_exports_optimizer_runtime_module.rs | 78 +++ packages/rspack/etc/core.api.md | 81 ++- packages/rspack/package.json | 2 +- .../rspack/src/container/ContainerPlugin.ts | 2 +- .../ModuleFederationManifestPlugin.ts | 157 ++++- .../src/container/ModuleFederationPlugin.ts | 209 +++---- packages/rspack/src/exports.ts | 3 + .../runtime/moduleFederationDefaultRuntime.js | 51 +- .../src/sharing/CollectSharedEntryPlugin.ts | 89 +++ .../rspack/src/sharing/ConsumeSharedPlugin.ts | 104 ++-- .../src/sharing/IndependentSharedPlugin.ts | 445 ++++++++++++++ .../rspack/src/sharing/ProvideSharedPlugin.ts | 73 ++- packages/rspack/src/sharing/SharePlugin.ts | 116 ++-- .../src/sharing/SharedContainerPlugin.ts | 116 ++++ .../SharedUsedExportsOptimizerPlugin.ts | 65 +++ .../src/sharing/TreeShakeSharedPlugin.ts | 69 +++ packages/rspack/src/sharing/utils.ts | 13 + packages/rspack/src/taps/types.ts | 1 + pnpm-lock.yaml | 47 +- .../treeshake-shared-infer-strategy/App.js | 23 + .../treeshake-shared-infer-strategy/index.js | 124 ++++ .../ui-lib-dynamic-default-export/index.js | 9 + .../package.json | 6 + .../ui-lib-dynamic-specific-export/index.js | 3 + .../package.json | 6 + .../node_modules/ui-lib-es/index.js | 3 + .../node_modules/ui-lib-es/package.json | 6 + .../node_modules/ui-lib-side-effect/index.js | 12 + .../ui-lib-side-effect/package.json | 6 + .../node_modules/ui-lib/index.js | 9 + .../node_modules/ui-lib/package.json | 6 + .../rspack.config.js | 68 +++ .../runtime-plugin.js | 18 + .../test.config.js | 5 + .../treeshake-shared-server-strategy/App.js | 23 + .../treeshake-shared-server-strategy/index.js | 125 ++++ .../node_modules/.federation/shared-entry.js | 5 + .../ui-lib-dynamic-default-export/index.js | 9 + .../package.json | 6 + .../ui-lib-dynamic-specific-export/index.js | 3 + .../package.json | 6 + .../node_modules/ui-lib-es/index.js | 3 + .../node_modules/ui-lib-es/package.json | 6 + .../node_modules/ui-lib-side-effect/index.js | 12 + .../ui-lib-side-effect/package.json | 6 + .../node_modules/ui-lib/index.js | 9 + .../node_modules/ui-lib/package.json | 6 + .../rspack.config.js | 68 +++ .../runtime-plugin.js | 18 + .../test.config.js | 5 + .../collect-share-entry-plugin/index.js | 14 + .../collect-share-entry-plugin/module.js | 3 + .../node_modules/xreact/index.js | 4 + .../node_modules/xreact/package.json | 5 + .../collect-share-entry-plugin/package.json | 5 + .../rspack.config.js | 39 ++ .../sharing/reshake-share/index.js | 61 ++ .../node_modules/ui-lib-dep/index.js | 9 + .../node_modules/ui-lib-dep/package.json | 6 + .../node_modules/ui-lib/index.js | 16 + .../node_modules/ui-lib/package.json | 6 + .../sharing/reshake-share/rspack.config.js | 55 ++ .../sharing/treeshake-share/index.js | 74 +++ .../node_modules/ui-lib-side-effect/index.js | 12 + .../ui-lib-side-effect/package.json | 6 + .../node_modules/ui-lib/index.js | 9 + .../node_modules/ui-lib/package.json | 6 + .../node_modules/ui-lib2/index.js | 9 + .../node_modules/ui-lib2/package.json | 6 + .../sharing/treeshake-share/rspack.config.js | 36 ++ .../webpack/tree-shake-shared-plugin.mdx | 45 ++ .../webpack/tree-shake-shared-plugin.mdx | 45 ++ 105 files changed, 4258 insertions(+), 375 deletions(-) create mode 100644 crates/rspack_plugin_mf/src/sharing/collect_shared_entry_plugin.rs create mode 100644 crates/rspack_plugin_mf/src/sharing/shared_container_dependency.rs create mode 100644 crates/rspack_plugin_mf/src/sharing/shared_container_entry_dependency.rs create mode 100644 crates/rspack_plugin_mf/src/sharing/shared_container_entry_module.rs create mode 100644 crates/rspack_plugin_mf/src/sharing/shared_container_entry_module_factory.rs create mode 100644 crates/rspack_plugin_mf/src/sharing/shared_container_plugin.rs create mode 100644 crates/rspack_plugin_mf/src/sharing/shared_container_runtime_module.rs create mode 100644 crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_plugin.rs create mode 100644 crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_runtime_module.rs create mode 100644 packages/rspack/src/sharing/CollectSharedEntryPlugin.ts create mode 100644 packages/rspack/src/sharing/IndependentSharedPlugin.ts create mode 100644 packages/rspack/src/sharing/SharedContainerPlugin.ts create mode 100644 packages/rspack/src/sharing/SharedUsedExportsOptimizerPlugin.ts create mode 100644 packages/rspack/src/sharing/TreeShakeSharedPlugin.ts create mode 100644 tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/App.js create mode 100644 tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/index.js create mode 100644 tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib-dynamic-default-export/index.js create mode 100644 tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib-dynamic-default-export/package.json create mode 100644 tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib-dynamic-specific-export/index.js create mode 100644 tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib-dynamic-specific-export/package.json create mode 100644 tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib-es/index.js create mode 100644 tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib-es/package.json create mode 100644 tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib-side-effect/index.js create mode 100644 tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib-side-effect/package.json create mode 100644 tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib/index.js create mode 100644 tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib/package.json create mode 100644 tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/rspack.config.js create mode 100644 tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/runtime-plugin.js create mode 100644 tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/test.config.js create mode 100644 tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/App.js create mode 100644 tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/index.js create mode 100644 tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/.federation/shared-entry.js create mode 100644 tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib-dynamic-default-export/index.js create mode 100644 tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib-dynamic-default-export/package.json create mode 100644 tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib-dynamic-specific-export/index.js create mode 100644 tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib-dynamic-specific-export/package.json create mode 100644 tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib-es/index.js create mode 100644 tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib-es/package.json create mode 100644 tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib-side-effect/index.js create mode 100644 tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib-side-effect/package.json create mode 100644 tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib/index.js create mode 100644 tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib/package.json create mode 100644 tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/rspack.config.js create mode 100644 tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/runtime-plugin.js create mode 100644 tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/test.config.js create mode 100644 tests/rspack-test/configCases/sharing/collect-share-entry-plugin/index.js create mode 100644 tests/rspack-test/configCases/sharing/collect-share-entry-plugin/module.js create mode 100644 tests/rspack-test/configCases/sharing/collect-share-entry-plugin/node_modules/xreact/index.js create mode 100644 tests/rspack-test/configCases/sharing/collect-share-entry-plugin/node_modules/xreact/package.json create mode 100644 tests/rspack-test/configCases/sharing/collect-share-entry-plugin/package.json create mode 100644 tests/rspack-test/configCases/sharing/collect-share-entry-plugin/rspack.config.js create mode 100644 tests/rspack-test/configCases/sharing/reshake-share/index.js create mode 100644 tests/rspack-test/configCases/sharing/reshake-share/node_modules/ui-lib-dep/index.js create mode 100644 tests/rspack-test/configCases/sharing/reshake-share/node_modules/ui-lib-dep/package.json create mode 100644 tests/rspack-test/configCases/sharing/reshake-share/node_modules/ui-lib/index.js create mode 100644 tests/rspack-test/configCases/sharing/reshake-share/node_modules/ui-lib/package.json create mode 100644 tests/rspack-test/configCases/sharing/reshake-share/rspack.config.js create mode 100644 tests/rspack-test/configCases/sharing/treeshake-share/index.js create mode 100644 tests/rspack-test/configCases/sharing/treeshake-share/node_modules/ui-lib-side-effect/index.js create mode 100644 tests/rspack-test/configCases/sharing/treeshake-share/node_modules/ui-lib-side-effect/package.json create mode 100644 tests/rspack-test/configCases/sharing/treeshake-share/node_modules/ui-lib/index.js create mode 100644 tests/rspack-test/configCases/sharing/treeshake-share/node_modules/ui-lib/package.json create mode 100644 tests/rspack-test/configCases/sharing/treeshake-share/node_modules/ui-lib2/index.js create mode 100644 tests/rspack-test/configCases/sharing/treeshake-share/node_modules/ui-lib2/package.json create mode 100644 tests/rspack-test/configCases/sharing/treeshake-share/rspack.config.js create mode 100644 website/docs/en/plugins/webpack/tree-shake-shared-plugin.mdx create mode 100644 website/docs/zh/plugins/webpack/tree-shake-shared-plugin.mdx diff --git a/Cargo.lock b/Cargo.lock index 57f12bad6a58..46167c7ea8ea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4473,6 +4473,7 @@ dependencies = [ "cow-utils", "either", "fast-glob", + "futures", "indexmap", "itertools 0.14.0", "linked_hash_set", diff --git a/crates/node_binding/napi-binding.d.ts b/crates/node_binding/napi-binding.d.ts index e218980d337a..db7de9e2961c 100644 --- a/crates/node_binding/napi-binding.d.ts +++ b/crates/node_binding/napi-binding.d.ts @@ -540,10 +540,13 @@ export declare enum BuiltinPluginName { SplitChunksPlugin = 'SplitChunksPlugin', RemoveDuplicateModulesPlugin = 'RemoveDuplicateModulesPlugin', ShareRuntimePlugin = 'ShareRuntimePlugin', + SharedUsedExportsOptimizerPlugin = 'SharedUsedExportsOptimizerPlugin', ContainerPlugin = 'ContainerPlugin', ContainerReferencePlugin = 'ContainerReferencePlugin', ProvideSharedPlugin = 'ProvideSharedPlugin', ConsumeSharedPlugin = 'ConsumeSharedPlugin', + CollectSharedEntryPlugin = 'CollectSharedEntryPlugin', + SharedContainerPlugin = 'SharedContainerPlugin', ModuleFederationRuntimePlugin = 'ModuleFederationRuntimePlugin', ModuleFederationManifestPlugin = 'ModuleFederationManifestPlugin', NamedModuleIdsPlugin = 'NamedModuleIdsPlugin', @@ -1837,6 +1840,11 @@ export interface RawCircularDependencyRspackPluginOptions { onEnd?: () => void } +export interface RawCollectShareEntryPluginOptions { + consumes: Array + filename?: string +} + export interface RawConsumeOptions { key: string import?: string @@ -1848,6 +1856,7 @@ export interface RawConsumeOptions { strictVersion: boolean singleton: boolean eager: boolean + treeshakeStrategy?: string } export interface RawConsumeSharedPluginOptions { @@ -2586,6 +2595,12 @@ export interface RawOptimizationOptions { avoidEntryIife: boolean } +export interface RawOptimizeSharedConfig { + shareKey: string + treeshake: boolean + usedExports?: Array +} + export interface RawOptions { name?: string mode?: undefined | 'production' | 'development' | 'none' @@ -2686,6 +2701,7 @@ export interface RawProvideOptions { singleton?: boolean requiredVersion?: string | false | undefined strictVersion?: boolean + treeshakeStrategy?: string } export interface RawRelated { @@ -2822,6 +2838,21 @@ export interface RawRuntimeChunkOptions { name: string | ((entrypoint: { name: string }) => string) } +export interface RawSharedContainerPluginOptions { + name: string + request: string + version: string + fileName?: string + library: JsLibraryOptions +} + +export interface RawSharedUsedExportsOptimizerPluginOptions { + shared: Array + injectUsedExports?: boolean + manifestFileName?: string + statsFileName?: string +} + export interface RawSizeLimitsPluginOptions { assetFilter?: (assetFilename: string) => boolean hints?: "error" | "warning" diff --git a/crates/rspack_binding_api/src/plugins/interceptor.rs b/crates/rspack_binding_api/src/plugins/interceptor.rs index 4df54156cb4d..dd9d12cb1218 100644 --- a/crates/rspack_binding_api/src/plugins/interceptor.rs +++ b/crates/rspack_binding_api/src/plugins/interceptor.rs @@ -79,6 +79,7 @@ use crate::{ JsContextModuleFactoryAfterResolveDataWrapper, JsContextModuleFactoryAfterResolveResult, JsContextModuleFactoryBeforeResolveDataWrapper, JsContextModuleFactoryBeforeResolveResult, }, + dependency::DependencyWrapper, html::{ JsAfterEmitData, JsAfterTemplateExecutionData, JsAlterAssetTagGroupsData, JsAlterAssetTagsData, JsBeforeAssetTagGenerationData, JsBeforeEmitData, @@ -95,7 +96,7 @@ use crate::{ runtime::{ JsAdditionalTreeRuntimeRequirementsArg, JsAdditionalTreeRuntimeRequirementsResult, JsCreateLinkData, JsCreateScriptData, JsLinkPrefetchData, JsLinkPreloadData, JsRuntimeGlobals, - JsRuntimeRequirementInTreeArg, JsRuntimeRequirementInTreeResult, + JsRuntimeRequirementInTreeArg, JsRuntimeRequirementInTreeResult, JsRuntimeSpec, }, source::JsSourceToJs, }; diff --git a/crates/rspack_binding_api/src/raw_options/raw_builtins/mod.rs b/crates/rspack_binding_api/src/raw_options/raw_builtins/mod.rs index 8733f3a79aa0..d74fe7d9acdf 100644 --- a/crates/rspack_binding_api/src/raw_options/raw_builtins/mod.rs +++ b/crates/rspack_binding_api/src/raw_options/raw_builtins/mod.rs @@ -32,7 +32,11 @@ use napi_derive::napi; use raw_dll::{RawDllReferenceAgencyPluginOptions, RawFlagAllModulesAsUsedPluginOptions}; use raw_ids::RawOccurrenceChunkIdsPluginOptions; use raw_lightning_css_minimizer::RawLightningCssMinimizerRspackPluginOptions; -use raw_mf::{RawModuleFederationManifestPluginOptions, RawModuleFederationRuntimePluginOptions}; +use raw_mf::{ + RawCollectShareEntryPluginOptions, RawModuleFederationManifestPluginOptions, + RawModuleFederationRuntimePluginOptions, RawProvideOptions, + RawSharedUsedExportsOptimizerPluginOptions, +}; use raw_sri::RawSubresourceIntegrityPluginOptions; use rspack_core::{BoxPlugin, Plugin, PluginExt}; use rspack_error::{Result, ToStringResultToRspackResultExt}; @@ -75,8 +79,9 @@ use rspack_plugin_lightning_css_minimizer::LightningCssMinimizerRspackPlugin; use rspack_plugin_limit_chunk_count::LimitChunkCountPlugin; use rspack_plugin_merge_duplicate_chunks::MergeDuplicateChunksPlugin; use rspack_plugin_mf::{ - ConsumeSharedPlugin, ContainerPlugin, ContainerReferencePlugin, ModuleFederationManifestPlugin, - ModuleFederationRuntimePlugin, ProvideSharedPlugin, ShareRuntimePlugin, + CollectSharedEntryPlugin, ConsumeSharedPlugin, ContainerPlugin, ContainerReferencePlugin, + ModuleFederationManifestPlugin, ModuleFederationRuntimePlugin, ProvideSharedPlugin, + ShareRuntimePlugin, SharedContainerPlugin, SharedUsedExportsOptimizerPlugin, }; use rspack_plugin_module_info_header::ModuleInfoHeaderPlugin; use rspack_plugin_module_replacement::{ContextReplacementPlugin, NormalModuleReplacementPlugin}; @@ -117,7 +122,7 @@ use self::{ raw_limit_chunk_count::RawLimitChunkCountPluginOptions, raw_mf::{ RawConsumeSharedPluginOptions, RawContainerPluginOptions, RawContainerReferencePluginOptions, - RawProvideOptions, + RawSharedContainerPluginOptions, }, raw_normal_replacement::RawNormalModuleReplacementPluginOptions, raw_runtime_chunk::RawRuntimeChunkOptions, @@ -167,10 +172,13 @@ pub enum BuiltinPluginName { SplitChunksPlugin, RemoveDuplicateModulesPlugin, ShareRuntimePlugin, + SharedUsedExportsOptimizerPlugin, ContainerPlugin, ContainerReferencePlugin, ProvideSharedPlugin, ConsumeSharedPlugin, + CollectSharedEntryPlugin, + SharedContainerPlugin, ModuleFederationRuntimePlugin, ModuleFederationManifestPlugin, NamedModuleIdsPlugin, @@ -463,6 +471,12 @@ impl<'a> BuiltinPlugin<'a> { ) .boxed(), ), + BuiltinPluginName::SharedUsedExportsOptimizerPlugin => { + let options = downcast_into::(self.options) + .map_err(|report| napi::Error::from_reason(report.to_string()))? + .into(); + plugins.push(SharedUsedExportsOptimizerPlugin::new(options).boxed()); + } BuiltinPluginName::ContainerPlugin => { plugins.push( ContainerPlugin::new( @@ -492,6 +506,18 @@ impl<'a> BuiltinPlugin<'a> { provides.sort_unstable_by_key(|(k, _)| k.to_string()); plugins.push(ProvideSharedPlugin::new(provides).boxed()) } + BuiltinPluginName::CollectSharedEntryPlugin => { + let options = downcast_into::(self.options) + .map_err(|report| napi::Error::from_reason(report.to_string()))? + .into(); + plugins.push(CollectSharedEntryPlugin::new(options).boxed()) + } + BuiltinPluginName::SharedContainerPlugin => { + let options = downcast_into::(self.options) + .map_err(|report| napi::Error::from_reason(report.to_string()))? + .into(); + plugins.push(SharedContainerPlugin::new(options).boxed()) + } BuiltinPluginName::ConsumeSharedPlugin => plugins.push( ConsumeSharedPlugin::new( downcast_into::(self.options) diff --git a/crates/rspack_binding_api/src/raw_options/raw_builtins/raw_mf.rs b/crates/rspack_binding_api/src/raw_options/raw_builtins/raw_mf.rs index 03adc9c05724..708ea7f8b95e 100644 --- a/crates/rspack_binding_api/src/raw_options/raw_builtins/raw_mf.rs +++ b/crates/rspack_binding_api/src/raw_options/raw_builtins/raw_mf.rs @@ -3,10 +3,12 @@ use std::{collections::HashMap, sync::Arc}; use napi::Either; use napi_derive::napi; use rspack_plugin_mf::{ - ConsumeOptions, ConsumeSharedPluginOptions, ConsumeVersion, ContainerPluginOptions, - ContainerReferencePluginOptions, ExposeOptions, ManifestExposeOption, ManifestSharedOption, - ModuleFederationManifestPluginOptions, ModuleFederationRuntimePluginOptions, ProvideOptions, - ProvideVersion, RemoteAliasTarget, RemoteOptions, StatsBuildInfo, + CollectSharedEntryPluginOptions, ConsumeOptions, ConsumeSharedPluginOptions, ConsumeVersion, + ContainerPluginOptions, ContainerReferencePluginOptions, ExposeOptions, ManifestExposeOption, + ManifestSharedOption, ModuleFederationManifestPluginOptions, + ModuleFederationRuntimePluginOptions, OptimizeSharedConfig, ProvideOptions, ProvideVersion, + RemoteAliasTarget, RemoteOptions, ShareContainerEntryOptions, SharedContainerPluginOptions, + SharedUsedExportsOptimizerPluginOptions, StatsBuildInfo, }; use crate::options::{ @@ -114,6 +116,7 @@ pub struct RawProvideOptions { #[napi(ts_type = "string | false | undefined")] pub required_version: Option, pub strict_version: Option, + pub treeshake_strategy: Option, } impl From for (String, ProvideOptions) { @@ -128,11 +131,57 @@ impl From for (String, ProvideOptions) { singleton: value.singleton, required_version: value.required_version.map(|v| RawVersionWrapper(v).into()), strict_version: value.strict_version, + treeshake_strategy: value.treeshake_strategy, }, ) } } +#[derive(Debug)] +#[napi(object)] +pub struct RawCollectShareEntryPluginOptions { + pub consumes: Vec, + pub filename: Option, +} + +impl From for CollectSharedEntryPluginOptions { + fn from(value: RawCollectShareEntryPluginOptions) -> Self { + Self { + consumes: value + .consumes + .into_iter() + .map(|provide| { + let (key, consume_options): (String, ConsumeOptions) = provide.into(); + (key, std::sync::Arc::new(consume_options)) + }) + .collect(), + filename: value.filename, + } + } +} + +#[derive(Debug)] +#[napi(object)] +pub struct RawSharedContainerPluginOptions { + pub name: String, + pub request: String, + pub version: String, + pub file_name: Option, + pub library: JsLibraryOptions, +} + +impl From for SharedContainerPluginOptions { + fn from(value: RawSharedContainerPluginOptions) -> Self { + SharedContainerPluginOptions { + name: value.name, + request: value.request, + version: value.version, + library: value.library.into(), + file_name: value.file_name.clone().map(Into::into), + } + } +} + #[derive(Debug)] #[napi(object)] pub struct RawConsumeSharedPluginOptions { @@ -154,6 +203,52 @@ impl From for ConsumeSharedPluginOptions { } } +#[derive(Debug)] +#[napi(object)] +pub struct RawOptimizeSharedConfig { + pub share_key: String, + pub treeshake: bool, + pub used_exports: Option>, +} + +impl From for OptimizeSharedConfig { + fn from(value: RawOptimizeSharedConfig) -> Self { + Self { + share_key: value.share_key, + treeshake: value.treeshake, + used_exports: value.used_exports.unwrap_or_default(), + } + } +} + +#[derive(Debug)] +#[napi(object)] +pub struct RawSharedUsedExportsOptimizerPluginOptions { + pub shared: Vec, + pub inject_used_exports: Option, + pub manifest_file_name: Option, + pub stats_file_name: Option, +} + +impl From for SharedUsedExportsOptimizerPluginOptions { + fn from(value: RawSharedUsedExportsOptimizerPluginOptions) -> Self { + Self { + shared: value + .shared + .into_iter() + .map(|config| config.into()) + .collect(), + inject_used_exports: value.inject_used_exports.unwrap_or(true), + manifest_file_name: value + .manifest_file_name + .and_then(|s| if s.trim().is_empty() { None } else { Some(s) }), + stats_file_name: value + .stats_file_name + .and_then(|s| if s.trim().is_empty() { None } else { Some(s) }), + } + } +} + #[derive(Debug)] #[napi(object)] pub struct RawConsumeOptions { @@ -168,6 +263,7 @@ pub struct RawConsumeOptions { pub strict_version: bool, pub singleton: bool, pub eager: bool, + pub treeshake_strategy: Option, } impl From for (String, ConsumeOptions) { @@ -184,6 +280,7 @@ impl From for (String, ConsumeOptions) { strict_version: value.strict_version, singleton: value.singleton, eager: value.eager, + treeshake_strategy: value.treeshake_strategy, }, ) } diff --git a/crates/rspack_core/src/compilation/mod.rs b/crates/rspack_core/src/compilation/mod.rs index 621e5f0c0c2a..14bc364f3bbd 100644 --- a/crates/rspack_core/src/compilation/mod.rs +++ b/crates/rspack_core/src/compilation/mod.rs @@ -55,6 +55,7 @@ use crate::{ ModuleIdsArtifact, ModuleStaticCacheArtifact, PathData, ResolverFactory, RuntimeGlobals, RuntimeKeyMap, RuntimeMode, RuntimeModule, RuntimeSpec, RuntimeSpecMap, RuntimeTemplate, SharedPluginDriver, SideEffectsOptimizeArtifact, SourceType, Stats, ValueCacheVersions, + DependencyId, ExtendedReferencedExport, build_chunk_graph::artifact::BuildChunkGraphArtifact, compilation::build_module_graph::{ BuildModuleGraphArtifact, ModuleExecutor, UpdateParam, build_module_graph, @@ -77,6 +78,12 @@ define_hook!(CompilationExecuteModule: Series(module: &ModuleIdentifier, runtime_modules: &IdentifierSet, code_generation_results: &BindingCell, execute_module_id: &ExecuteModuleId)); define_hook!(CompilationFinishModules: Series(compilation: &mut Compilation, async_modules_artifact: &mut AsyncModulesArtifact)); define_hook!(CompilationSeal: Series(compilation: &mut Compilation)); +define_hook!(CompilationDependencyReferencedExports: Series( + compilation: &Compilation, + dependency: &DependencyId, + referenced_exports: &Option> , + runtime: Option<&RuntimeSpec> +)); define_hook!(CompilationConcatenationScope: SeriesBail(compilation: &Compilation, curr_module: ModuleIdentifier) -> ConcatenationScope); define_hook!(CompilationOptimizeDependencies: SeriesBail(compilation: &mut Compilation, side_effects_optimize_artifact: &mut SideEffectsOptimizeArtifact, diagnostics: &mut Vec) -> bool); define_hook!(CompilationOptimizeModules: SeriesBail(compilation: &mut Compilation) -> bool); @@ -114,6 +121,7 @@ pub struct CompilationHooks { pub succeed_module: CompilationSucceedModuleHook, pub execute_module: CompilationExecuteModuleHook, pub finish_modules: CompilationFinishModulesHook, + pub dependency_referenced_exports: CompilationDependencyReferencedExportsHook, pub seal: CompilationSealHook, pub optimize_dependencies: CompilationOptimizeDependenciesHook, pub optimize_modules: CompilationOptimizeModulesHook, diff --git a/crates/rspack_core/src/dependency/dependency_type.rs b/crates/rspack_core/src/dependency/dependency_type.rs index e0994a0ccdf6..fd62282c1795 100644 --- a/crates/rspack_core/src/dependency/dependency_type.rs +++ b/crates/rspack_core/src/dependency/dependency_type.rs @@ -99,6 +99,10 @@ pub enum DependencyType { ContainerExposed, /// container entry, ContainerEntry, + /// share container entry + ShareContainerEntry, + /// share container fallback + ShareContainerFallback, /// remote to external, RemoteToExternal, /// fallback @@ -185,6 +189,8 @@ impl DependencyType { DependencyType::ImportMetaResolve => "import.meta.resolve", DependencyType::ContainerExposed => "container exposed", DependencyType::ContainerEntry => "container entry", + DependencyType::ShareContainerEntry => "share container entry", + DependencyType::ShareContainerFallback => "share container fallback", DependencyType::DllEntry => "dll entry", DependencyType::RemoteToExternal => "remote to external", DependencyType::RemoteToFallback => "fallback", diff --git a/crates/rspack_core/src/dependency/mod.rs b/crates/rspack_core/src/dependency/mod.rs index 0b4f649d05eb..d06ae800db13 100644 --- a/crates/rspack_core/src/dependency/mod.rs +++ b/crates/rspack_core/src/dependency/mod.rs @@ -40,10 +40,16 @@ pub use static_exports_dependency::{StaticExportsDependency, StaticExportsSpec}; use swc_core::ecma::atoms::Atom; use crate::{ - ConnectionState, EvaluatedInlinableValue, ModuleGraph, ModuleGraphCacheArtifact, - ModuleGraphConnection, ModuleIdentifier, RuntimeSpec, + ConnectionState, EvaluatedInlinableValue, ExtendedReferencedExport, ModuleGraph, + ModuleGraphCacheArtifact, ModuleGraphConnection, ModuleIdentifier, RuntimeSpec, }; +#[derive(Debug, Clone)] +pub enum ProcessModuleReferencedExports { + Map(FxHashMap), + ExtendRef(Vec), +} + #[derive(Debug, Default)] pub struct ExportSpec { pub name: Atom, diff --git a/crates/rspack_core/src/lib.rs b/crates/rspack_core/src/lib.rs index 4b020bd22cad..5d5c4c03baf2 100644 --- a/crates/rspack_core/src/lib.rs +++ b/crates/rspack_core/src/lib.rs @@ -123,6 +123,7 @@ pub enum SourceType { Remote, ShareInit, ConsumeShared, + ShareContainerShared, Custom(#[cacheable(with=AsPreset)] Ustr), #[default] Unknown, @@ -142,6 +143,7 @@ impl std::fmt::Display for SourceType { SourceType::Remote => write!(f, "remote"), SourceType::ShareInit => write!(f, "share-init"), SourceType::ConsumeShared => write!(f, "consume-shared"), + SourceType::ShareContainerShared => write!(f, "share-container-shared"), SourceType::Unknown => write!(f, "unknown"), SourceType::CssImport => write!(f, "css-import"), SourceType::Custom(source_type) => f.write_str(source_type), @@ -161,6 +163,7 @@ impl From<&str> for SourceType { "remote" => Self::Remote, "share-init" => Self::ShareInit, "consume-shared" => Self::ConsumeShared, + "share-container-shared" => Self::ShareContainerShared, "unknown" => Self::Unknown, "css-import" => Self::CssImport, other => SourceType::Custom(other.into()), @@ -176,6 +179,7 @@ impl From<&ModuleType> for SourceType { ModuleType::WasmSync | ModuleType::WasmAsync => Self::Wasm, ModuleType::Asset | ModuleType::AssetInline | ModuleType::AssetResource => Self::Asset, ModuleType::ConsumeShared => Self::ConsumeShared, + ModuleType::ShareContainerShared => Self::ShareContainerShared, _ => Self::Unknown, } } @@ -202,6 +206,7 @@ pub enum ModuleType { Fallback, ProvideShared, ConsumeShared, + ShareContainerShared, SelfReference, Custom(#[cacheable(with=AsPreset)] Ustr), } @@ -270,6 +275,7 @@ impl ModuleType { ModuleType::Fallback => "fallback-module", ModuleType::ProvideShared => "provide-module", ModuleType::ConsumeShared => "consume-shared-module", + ModuleType::ShareContainerShared => "share-container-shared-module", ModuleType::SelfReference => "self-reference-module", ModuleType::Custom(custom) => custom.as_str(), diff --git a/crates/rspack_plugin_javascript/Cargo.toml b/crates/rspack_plugin_javascript/Cargo.toml index 4482659d1fe0..2fa67518e5a2 100644 --- a/crates/rspack_plugin_javascript/Cargo.toml +++ b/crates/rspack_plugin_javascript/Cargo.toml @@ -13,6 +13,7 @@ bitflags = { workspace = true } cow-utils = { workspace = true } either = { workspace = true } fast-glob = { workspace = true } +futures = { workspace = true } indexmap = { workspace = true } itertools = { workspace = true } linked_hash_set = { workspace = true } diff --git a/crates/rspack_plugin_javascript/src/dependency/esm/esm_import_specifier_dependency.rs b/crates/rspack_plugin_javascript/src/dependency/esm/esm_import_specifier_dependency.rs index da1012f92600..88d553f052ae 100644 --- a/crates/rspack_plugin_javascript/src/dependency/esm/esm_import_specifier_dependency.rs +++ b/crates/rspack_plugin_javascript/src/dependency/esm/esm_import_specifier_dependency.rs @@ -107,6 +107,45 @@ impl ESMImportSpecifierDependency { .unwrap_or_else(|| self.ids.as_slice()) } + pub fn get_esm_import_specifier_referenced_exports( + &self, + module_graph: &ModuleGraph, + exports_type: Option, + ) -> Vec { + let mut ids = self.get_ids(module_graph); + if ids.is_empty() { + return self.get_referenced_exports_in_destructuring(None); + } + + let mut namespace_object_as_context = self.namespace_object_as_context; + if let Some(id) = ids.first() + && id == "default" + { + match exports_type { + Some(ExportsType::DefaultOnly) | Some(ExportsType::DefaultWithNamed) => { + if ids.len() == 1 { + return self.get_referenced_exports_in_destructuring(None); + } + ids = &ids[1..]; + namespace_object_as_context = true; + } + Some(ExportsType::Dynamic) => { + return create_exports_object_referenced(); + } + _ => {} + } + } + + if self.call && !self.direct_import && (namespace_object_as_context || ids.len() > 1) { + if ids.len() == 1 { + return create_exports_object_referenced(); + } + // remove last one + ids = &ids[..ids.len() - 1]; + } + self.get_referenced_exports_in_destructuring(Some(ids)) + } + pub fn get_referenced_exports_in_destructuring( &self, ids: Option<&[Atom]>, @@ -236,44 +275,28 @@ impl Dependency for ESMImportSpecifierDependency { module_graph_cache: &ModuleGraphCacheArtifact, _runtime: Option<&RuntimeSpec>, ) -> Vec { - let mut ids = self.get_ids(module_graph); - // namespace import + let ids = self.get_ids(module_graph); if ids.is_empty() { return self.get_referenced_exports_in_destructuring(None); } - let mut namespace_object_as_context = self.namespace_object_as_context; - if let Some(id) = ids.first() + let exports_type = if let Some(id) = ids.first() && id == "default" { let parent_module = module_graph .get_parent_module(&self.id) .expect("should have parent module"); - let exports_type = - get_exports_type(module_graph, module_graph_cache, &self.id, parent_module); - match exports_type { - ExportsType::DefaultOnly | ExportsType::DefaultWithNamed => { - if ids.len() == 1 { - return self.get_referenced_exports_in_destructuring(None); - } - ids = &ids[1..]; - namespace_object_as_context = true; - } - ExportsType::Dynamic => { - return create_exports_object_referenced(); - } - _ => {} - } - } + Some(get_exports_type( + module_graph, + module_graph_cache, + &self.id, + parent_module, + )) + } else { + None + }; - if self.call && !self.direct_import && (namespace_object_as_context || ids.len() > 1) { - if ids.len() == 1 { - return create_exports_object_referenced(); - } - // remove last one - ids = &ids[..ids.len() - 1]; - } - self.get_referenced_exports_in_destructuring(Some(ids)) + self.get_esm_import_specifier_referenced_exports(module_graph, exports_type) } fn could_affect_referencing_module(&self) -> rspack_core::AffectType { diff --git a/crates/rspack_plugin_javascript/src/plugin/flag_dependency_usage_plugin.rs b/crates/rspack_plugin_javascript/src/plugin/flag_dependency_usage_plugin.rs index 5359d19d063e..c8ac8bde09c5 100644 --- a/crates/rspack_plugin_javascript/src/plugin/flag_dependency_usage_plugin.rs +++ b/crates/rspack_plugin_javascript/src/plugin/flag_dependency_usage_plugin.rs @@ -96,20 +96,19 @@ impl<'a> FlagDependencyUsagePluginProxy<'a> { self.compilation.module_graph_cache_artifact.freeze(); // collect referenced exports from modules by calling `dependency.get_referenced_exports` - // and also added referenced modules to the queue for further processing - let batch_res = batch - .into_par_iter() - .map(|(block_id, runtime, force_side_effects)| { - let (referenced_exports, module_tasks) = - self.process_module(block_id, runtime.as_ref(), force_side_effects, self.global); - ( - runtime, - force_side_effects, - referenced_exports, - module_tasks, - ) - }) - .collect::>(); + // and also added referenced modules to queue for further processing + let mut batch_res = vec![]; + for (block_id, runtime, force_side_effects) in batch { + let (referenced_exports, module_tasks) = self + .process_module(block_id, runtime.as_ref(), force_side_effects, self.global) + .await; + batch_res.push(( + runtime, + force_side_effects, + referenced_exports, + module_tasks, + )); + } let mut nested_tasks = vec![]; let mut non_nested_tasks: IdentifierMap> = IdentifierMap::default(); @@ -236,7 +235,7 @@ impl<'a> FlagDependencyUsagePluginProxy<'a> { } } - fn process_module( + async fn process_module( &self, block_id: ModuleOrAsyncDependenciesBlock, runtime: Option<&RuntimeSpec>, @@ -260,19 +259,39 @@ impl<'a> FlagDependencyUsagePluginProxy<'a> { for (dep_id, module_id) in dependencies.into_iter() { let old_referenced_exports = map.remove(&module_id); - let Some(referenced_exports) = get_dependency_referenced_exports( + + let referenced_exports_result = get_dependency_referenced_exports( dep_id, &self.compilation.get_module_graph(), &self.compilation.module_graph_cache_artifact, runtime, - ) else { - continue; - }; + ); - if let Some(new_referenced_exports) = - merge_referenced_exports(old_referenced_exports, referenced_exports) - { - map.insert(module_id, new_referenced_exports); + // 直接使用 await 调用异步钩子 + self + .compilation + .plugin_driver + .compilation_hooks + .dependency_referenced_exports + .call( + &*self.compilation, + &dep_id, + &referenced_exports_result, + runtime, + ) + .await; + + match referenced_exports_result { + Some(mut referenced_exports) => { + if let Some(new_referenced_exports) = + merge_referenced_exports(old_referenced_exports, referenced_exports) + { + map.insert(module_id, new_referenced_exports); + } + } + None => { + continue; + } } } @@ -494,7 +513,7 @@ async fn optimize_dependencies( } let mut proxy = FlagDependencyUsagePluginProxy::new(self.global, compilation); - proxy.apply(); + proxy.apply().await; Ok(None) } diff --git a/crates/rspack_plugin_mf/src/lib.rs b/crates/rspack_plugin_mf/src/lib.rs index 2c079ace82da..e2422e90e8bd 100644 --- a/crates/rspack_plugin_mf/src/lib.rs +++ b/crates/rspack_plugin_mf/src/lib.rs @@ -16,6 +16,7 @@ pub use manifest::{ ModuleFederationManifestPluginOptions, RemoteAliasTarget, StatsBuildInfo, }; pub use sharing::{ + collect_shared_entry_plugin::{CollectSharedEntryPlugin, CollectSharedEntryPluginOptions}, consume_shared_module::ConsumeSharedModule, consume_shared_plugin::{ ConsumeOptions, ConsumeSharedPlugin, ConsumeSharedPluginOptions, ConsumeVersion, @@ -26,6 +27,11 @@ pub use sharing::{ CodeGenerationDataShareInit, DataInitStage, ShareInitData, ShareRuntimeModule, }, share_runtime_plugin::ShareRuntimePlugin, + shared_container_entry_dependency::ShareContainerEntryOptions, + shared_container_plugin::{SharedContainerPlugin, SharedContainerPluginOptions}, + shared_used_exports_optimizer_plugin::{ + OptimizeSharedConfig, SharedUsedExportsOptimizerPlugin, SharedUsedExportsOptimizerPluginOptions, + }, }; mod utils { diff --git a/crates/rspack_plugin_mf/src/manifest/data.rs b/crates/rspack_plugin_mf/src/manifest/data.rs index cac7ab0eebba..d2ca71591bae 100644 --- a/crates/rspack_plugin_mf/src/manifest/data.rs +++ b/crates/rspack_plugin_mf/src/manifest/data.rs @@ -1,6 +1,6 @@ -use serde::Serialize; +use serde::{Deserialize, Serialize}; -#[derive(Debug, Serialize, Clone, Default)] +#[derive(Debug, Serialize, Deserialize, Clone, Default)] pub struct StatsAssetsGroup { #[serde(default)] pub js: AssetsSplit, @@ -8,7 +8,7 @@ pub struct StatsAssetsGroup { pub css: AssetsSplit, } -#[derive(Debug, Serialize, Clone, Default)] +#[derive(Debug, Serialize, Deserialize, Clone, Default)] pub struct AssetsSplit { #[serde(default)] pub sync: Vec, @@ -16,7 +16,7 @@ pub struct AssetsSplit { pub r#async: Vec, } -#[derive(Debug, Serialize, Clone, Default)] +#[derive(Debug, Serialize, Deserialize, Clone, Default)] pub struct StatsBuildInfo { #[serde(rename = "buildVersion")] pub build_version: String, @@ -24,7 +24,7 @@ pub struct StatsBuildInfo { pub build_name: Option, } -#[derive(Debug, Serialize, Clone)] +#[derive(Debug, Serialize, Deserialize, Clone)] pub struct StatsExpose { pub path: String, pub id: String, @@ -35,7 +35,7 @@ pub struct StatsExpose { pub assets: StatsAssetsGroup, } -#[derive(Debug, Serialize, Clone)] +#[derive(Debug, Serialize, Deserialize, Clone)] pub struct StatsShared { pub id: String, pub name: String, @@ -48,9 +48,11 @@ pub struct StatsShared { pub assets: StatsAssetsGroup, #[serde(default)] pub usedIn: Vec, + #[serde(default)] + pub usedExports: Vec, } -#[derive(Debug, Serialize, Clone)] +#[derive(Debug, Serialize, Deserialize, Clone)] pub struct StatsRemote { pub alias: String, pub consumingFederationContainerName: String, @@ -62,7 +64,7 @@ pub struct StatsRemote { pub usedIn: Vec, } -#[derive(Debug, Serialize, Clone)] +#[derive(Debug, Serialize, Deserialize, Clone)] pub struct BasicStatsMetaData { pub name: String, pub globalName: String, @@ -76,7 +78,7 @@ pub struct BasicStatsMetaData { pub r#type: Option, } -#[derive(Debug, Serialize, Clone, Default)] +#[derive(Debug, Serialize, Deserialize, Clone, Default)] pub struct RemoteEntryMeta { #[serde(default)] pub name: String, @@ -86,7 +88,7 @@ pub struct RemoteEntryMeta { pub r#type: String, } -#[derive(Debug, Serialize, Clone)] +#[derive(Debug, Serialize, Deserialize, Clone)] pub struct StatsRoot { pub id: String, pub name: String, diff --git a/crates/rspack_plugin_mf/src/manifest/mod.rs b/crates/rspack_plugin_mf/src/manifest/mod.rs index 17cb95e13ecd..3214cc0606fd 100644 --- a/crates/rspack_plugin_mf/src/manifest/mod.rs +++ b/crates/rspack_plugin_mf/src/manifest/mod.rs @@ -11,11 +11,11 @@ use asset::{ collect_assets_for_module, collect_assets_from_chunk, collect_usage_files_for_module, empty_assets_group, module_source_path, normalize_assets_group, }; -pub use data::StatsBuildInfo; use data::{ BasicStatsMetaData, ManifestExpose, ManifestRemote, ManifestRoot, ManifestShared, - RemoteEntryMeta, StatsAssetsGroup, StatsExpose, StatsRemote, StatsRoot, StatsShared, + RemoteEntryMeta, StatsAssetsGroup, StatsExpose, StatsRemote, StatsShared, }; +pub use data::{StatsBuildInfo, StatsRoot}; pub use options::{ ManifestExposeOption, ManifestSharedOption, ModuleFederationManifestPluginOptions, RemoteAliasTarget, @@ -84,7 +84,7 @@ fn get_remote_entry_name(compilation: &Compilation, container_name: &str) -> Opt } None } -#[plugin_hook(CompilationProcessAssets for ModuleFederationManifestPlugin)] +#[plugin_hook(CompilationProcessAssets for ModuleFederationManifestPlugin, stage = 0)] async fn process_assets(&self, compilation: &mut Compilation) -> Result<()> { // Prepare entrypoint names let entry_point_names: HashSet = compilation @@ -169,6 +169,7 @@ async fn process_assets(&self, compilation: &mut Compilation) -> Result<()> { singleton: shared.singleton, assets: StatsAssetsGroup::default(), usedIn: Vec::new(), + usedExports: Vec::new(), }) .collect::>(); let remote_list = self diff --git a/crates/rspack_plugin_mf/src/manifest/utils.rs b/crates/rspack_plugin_mf/src/manifest/utils.rs index ec2e5d2c219e..ec7ab97c95ba 100644 --- a/crates/rspack_plugin_mf/src/manifest/utils.rs +++ b/crates/rspack_plugin_mf/src/manifest/utils.rs @@ -46,6 +46,7 @@ pub fn ensure_shared_entry<'a>( singleton: None, assets: super::data::StatsAssetsGroup::default(), usedIn: Vec::new(), + usedExports: Vec::new(), }) } diff --git a/crates/rspack_plugin_mf/src/sharing/collect_shared_entry_plugin.rs b/crates/rspack_plugin_mf/src/sharing/collect_shared_entry_plugin.rs new file mode 100644 index 000000000000..5dc8c3ba9624 --- /dev/null +++ b/crates/rspack_plugin_mf/src/sharing/collect_shared_entry_plugin.rs @@ -0,0 +1,232 @@ +use std::{ + path::{Path, PathBuf}, + sync::Arc, +}; + +use regex::Regex; +use rspack_core::{ + Compilation, CompilationAsset, CompilationProcessAssets, Context, DependenciesBlock, Module, + Plugin, + rspack_sources::{RawStringSource, SourceExt}, +}; +use rspack_error::Result; +use rspack_hook::{plugin, plugin_hook}; +use rustc_hash::FxHashMap; +use serde::Serialize; + +use super::consume_shared_plugin::ConsumeOptions; + +const DEFAULT_FILENAME: &str = "collect-shared-entries.json"; + +#[derive(Debug, Serialize)] +struct CollectSharedEntryAssetItem<'a> { + #[serde(rename = "shareScope")] + share_scope: &'a str, + requests: &'a [[String; 2]], +} + +#[derive(Debug)] +pub struct CollectSharedEntryPluginOptions { + pub consumes: Vec<(String, Arc)>, + pub filename: Option, +} + +#[plugin] +#[derive(Debug)] +pub struct CollectSharedEntryPlugin { + options: CollectSharedEntryPluginOptions, +} + +impl CollectSharedEntryPlugin { + pub fn new(options: CollectSharedEntryPluginOptions) -> Self { + Self::new_inner(options) + } + + /// Infer package version from a module request path + /// Example: ../../../.eden-mono/temp/node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/index.js + /// It locates react-dom's package.json and reads the version field + async fn infer_version(&self, request: &str) -> Option { + // 1) Try pnpm store path pattern: .pnpm/@_ + let pnpm_re = Regex::new(r"/\\.pnpm/[^/]*@([^/_]+)").ok(); + if let Some(re) = pnpm_re { + if let Some(caps) = re.captures(request) { + if let Some(m) = caps.get(1) { + return Some(m.as_str().to_string()); + } + } + } + + // 2) Fallback: read version from the deepest node_modules//package.json + let path = Path::new(request); + let comps: Vec = path + .components() + .map(|c| c.as_os_str().to_string_lossy().to_string()) + .collect(); + if let Some(idx) = comps.iter().rposition(|c| c == "node_modules") { + let mut pkg_parts: Vec<&str> = Vec::new(); + if let Some(next) = comps.get(idx + 1) { + if next.starts_with('@') { + if let Some(next2) = comps.get(idx + 2) { + pkg_parts.push(next.as_str()); + pkg_parts.push(next2.as_str()); + } + } else { + pkg_parts.push(next.as_str()); + } + } + if !pkg_parts.is_empty() { + let mut package_json_path = PathBuf::new(); + for c in comps.iter().take(idx + 1) { + package_json_path.push(c); + } + for p in &pkg_parts { + package_json_path.push(p); + } + package_json_path.push("package.json"); + if package_json_path.exists() { + if let Ok(content) = std::fs::read_to_string(&package_json_path) { + if let Ok(json) = serde_json::from_str::(&content) { + if let Some(version) = json.get("version").and_then(|v| v.as_str()) { + return Some(version.to_string()); + } + } + } + } + } + } + + None + } +} + +#[plugin_hook(CompilationProcessAssets for CollectSharedEntryPlugin)] +async fn process_assets(&self, compilation: &mut Compilation) -> Result<()> { + // Traverse ConsumeSharedModule in the graph and collect real resolved module paths from fallback + let module_graph = compilation.get_module_graph(); + let mut ordered_requests: FxHashMap> = FxHashMap::default(); + let mut share_scopes: FxHashMap = FxHashMap::default(); + + for (_id, module) in module_graph.modules().into_iter() { + let module_type = module.module_type(); + if !matches!(module_type, rspack_core::ModuleType::ConsumeShared) { + continue; + } + + if let Some(consume) = module + .as_any() + .downcast_ref::() + { + // Parse share_scope and share_key from readable_identifier + let ident = consume.readable_identifier(&Context::default()).to_string(); + // Format: "consume shared module ({scope}) {share_key}@..." + let (scope, key) = { + let mut scope = String::new(); + let mut key = String::new(); + if let Some(start) = ident.find("(") + && let Some(end) = ident.find(")") + && end > start + { + scope = ident[start + 1..end].to_string(); + } + if let Some(pos) = ident.find(") ") { + let rest = &ident[pos + 2..]; + let at = rest.find('@').unwrap_or(rest.len()); + key = rest[..at].to_string(); + } + (scope, key) + }; + if key.is_empty() { + continue; + } + // Collect target modules from dependencies and async blocks + let mut target_modules = Vec::new(); + for dep_id in consume.get_dependencies() { + if let Some(target_id) = module_graph.module_identifier_by_dependency_id(dep_id) { + target_modules.push(*target_id); + } + } + for block_id in consume.get_blocks() { + if let Some(block) = module_graph.block_by_id(block_id) { + for dep_id in block.get_dependencies() { + if let Some(target_id) = module_graph.module_identifier_by_dependency_id(dep_id) { + target_modules.push(*target_id); + } + } + } + } + + // Add real module resource paths to the map and infer version + let mut reqs = ordered_requests.remove(&key).unwrap_or_default(); + for target_id in target_modules { + if let Some(target) = module_graph.module_by_identifier(&target_id) { + if let Some(name) = target.name_for_condition() { + let resource: String = name.into(); + let version = self + .infer_version(&resource) + .await + .unwrap_or_else(|| "".to_string()); + let pair = [resource, version]; + if !reqs.iter().any(|p| p[0] == pair[0] && p[1] == pair[1]) { + reqs.push(pair); + } + } + } + } + reqs.sort_by(|a, b| a[0].cmp(&b[0]).then(a[1].cmp(&b[1]))); + ordered_requests.insert(key.clone(), reqs); + if !scope.is_empty() { + share_scopes.insert(key.clone(), scope); + } + } + } + + // Build asset content + let mut shared: FxHashMap<&str, CollectSharedEntryAssetItem<'_>> = FxHashMap::default(); + for (share_key, requests) in ordered_requests.iter() { + let scope = share_scopes + .get(share_key) + .map(|s| s.as_str()) + .unwrap_or(""); + shared.insert( + share_key.as_str(), + CollectSharedEntryAssetItem { + share_scope: scope, + requests: requests.as_slice(), + }, + ); + } + + let json = serde_json::to_string_pretty(&shared) + .expect("CollectSharedEntryPlugin: failed to serialize share entries"); + + // Get filename, or use default when absent + let filename = self + .options + .filename + .as_ref() + .map(|f| f.clone()) + .unwrap_or_else(|| DEFAULT_FILENAME.to_string()); + + compilation.emit_asset( + filename, + CompilationAsset::new( + Some(RawStringSource::from(json).boxed()), + Default::default(), + ), + ); + Ok(()) +} + +impl Plugin for CollectSharedEntryPlugin { + fn name(&self) -> &'static str { + "rspack.CollectSharedEntryPlugin" + } + + fn apply(&self, ctx: &mut rspack_core::ApplyContext<'_>) -> Result<()> { + ctx + .compilation_hooks + .process_assets + .tap(process_assets::new(self)); + Ok(()) + } +} diff --git a/crates/rspack_plugin_mf/src/sharing/consume_shared_module.rs b/crates/rspack_plugin_mf/src/sharing/consume_shared_module.rs index b0c966ec2b9c..5dfab6b123b4 100644 --- a/crates/rspack_plugin_mf/src/sharing/consume_shared_module.rs +++ b/crates/rspack_plugin_mf/src/sharing/consume_shared_module.rs @@ -236,6 +236,7 @@ impl Module for ConsumeSharedModule { singleton: self.options.singleton, eager: self.options.eager, fallback: factory, + treeshake_strategy: self.options.treeshake_strategy.clone(), }); Ok(code_generation_result) } diff --git a/crates/rspack_plugin_mf/src/sharing/consume_shared_plugin.rs b/crates/rspack_plugin_mf/src/sharing/consume_shared_plugin.rs index 7a08e8510054..cf6f61a6cca8 100644 --- a/crates/rspack_plugin_mf/src/sharing/consume_shared_plugin.rs +++ b/crates/rspack_plugin_mf/src/sharing/consume_shared_plugin.rs @@ -36,6 +36,7 @@ pub struct ConsumeOptions { pub strict_version: bool, pub singleton: bool, pub eager: bool, + pub treeshake_strategy: Option, } #[cacheable] @@ -54,21 +55,21 @@ impl fmt::Display for ConsumeVersion { } } -static RELATIVE_REQUEST: LazyLock = +pub static RELATIVE_REQUEST: LazyLock = LazyLock::new(|| Regex::new(r"^\.\.?(\/|$)").expect("Invalid regex")); -static ABSOLUTE_REQUEST: LazyLock = +pub static ABSOLUTE_REQUEST: LazyLock = LazyLock::new(|| Regex::new(r"^(\/|[A-Za-z]:\\|\\\\)").expect("Invalid regex")); -static PACKAGE_NAME: LazyLock = +pub static PACKAGE_NAME: LazyLock = LazyLock::new(|| Regex::new(r"^((?:@[^\\/]+[\\/])?[^\\/]+)").expect("Invalid regex")); #[derive(Debug)] -struct MatchedConsumes { - resolved: FxHashMap>, - unresolved: FxHashMap>, - prefixed: FxHashMap>, +pub struct MatchedConsumes { + pub resolved: FxHashMap>, + pub unresolved: FxHashMap>, + pub prefixed: FxHashMap>, } -async fn resolve_matched_configs( +pub async fn resolve_matched_configs( compilation: &mut Compilation, resolver: Arc, configs: &[(String, Arc)], @@ -104,7 +105,7 @@ async fn resolve_matched_configs( } } -async fn get_description_file( +pub async fn get_description_file( fs: Arc, mut dir: &Utf8Path, satisfies_description_file_data: Option) -> bool>, @@ -137,7 +138,7 @@ async fn get_description_file( } } -fn get_required_version_from_description_file( +pub fn get_required_version_from_description_file( data: serde_json::Value, package_name: &str, ) -> Option { @@ -368,6 +369,7 @@ impl ConsumeSharedPlugin { strict_version: config.strict_version, singleton: config.singleton, eager: config.eager, + treeshake_strategy: config.treeshake_strategy.clone(), }, ) } @@ -404,12 +406,15 @@ async fn factorize(&self, data: &mut ModuleFactoryCreateData) -> Result Result Result> { if matches!( data.dependencies[0].dependency_type(), - DependencyType::ConsumeSharedFallback | DependencyType::ProvideModuleForShared + DependencyType::ConsumeSharedFallback + | DependencyType::ProvideModuleForShared + | DependencyType::ShareContainerFallback ) { return Ok(None); } let resource = create_data.resource_resolve_data.resource(); let consumes = self.get_matched_consumes(); + if let Some(options) = consumes.resolved.get(resource) { let module = self .create_consume_shared_module(&data.context, resource, options.clone(), |d| { diff --git a/crates/rspack_plugin_mf/src/sharing/consume_shared_runtime_module.rs b/crates/rspack_plugin_mf/src/sharing/consume_shared_runtime_module.rs index aa7aa69aa8d9..176b68f9268a 100644 --- a/crates/rspack_plugin_mf/src/sharing/consume_shared_runtime_module.rs +++ b/crates/rspack_plugin_mf/src/sharing/consume_shared_runtime_module.rs @@ -89,7 +89,7 @@ impl RuntimeModule for ConsumeSharedRuntimeModule { .get(&module, Some(chunk.runtime())); if let Some(data) = code_gen.data.get::() { module_id_to_consume_data_mapping.insert(id, format!( - "{{ shareScope: {}, shareKey: {}, import: {}, requiredVersion: {}, strictVersion: {}, singleton: {}, eager: {}, fallback: {} }}", + "{{ shareScope: {}, shareKey: {}, import: {}, requiredVersion: {}, strictVersion: {}, singleton: {}, eager: {}, fallback: {}, treeshakeStrategy: {} }}", json_stringify(&data.share_scope), json_stringify(&data.share_key), json_stringify(&data.import), @@ -98,6 +98,7 @@ impl RuntimeModule for ConsumeSharedRuntimeModule { json_stringify(&data.singleton), json_stringify(&data.eager), data.fallback.as_deref().unwrap_or("undefined"), + json_stringify(&data.treeshake_strategy), )); } }; @@ -218,4 +219,5 @@ pub struct CodeGenerationDataConsumeShared { pub singleton: bool, pub eager: bool, pub fallback: Option, + pub treeshake_strategy: Option, } diff --git a/crates/rspack_plugin_mf/src/sharing/mod.rs b/crates/rspack_plugin_mf/src/sharing/mod.rs index a2f9e246e08b..606f650bc5f1 100644 --- a/crates/rspack_plugin_mf/src/sharing/mod.rs +++ b/crates/rspack_plugin_mf/src/sharing/mod.rs @@ -1,3 +1,4 @@ +pub mod collect_shared_entry_plugin; pub mod consume_shared_fallback_dependency; pub mod consume_shared_module; pub mod consume_shared_plugin; @@ -9,3 +10,11 @@ pub mod provide_shared_module_factory; pub mod provide_shared_plugin; pub mod share_runtime_module; pub mod share_runtime_plugin; +pub mod shared_container_dependency; +pub mod shared_container_entry_dependency; +pub mod shared_container_entry_module; +pub mod shared_container_entry_module_factory; +pub mod shared_container_plugin; +pub mod shared_container_runtime_module; +pub mod shared_used_exports_optimizer_plugin; +pub mod shared_used_exports_optimizer_runtime_module; diff --git a/crates/rspack_plugin_mf/src/sharing/provide_shared_dependency.rs b/crates/rspack_plugin_mf/src/sharing/provide_shared_dependency.rs index 2c68d7d3deff..902201d11d98 100644 --- a/crates/rspack_plugin_mf/src/sharing/provide_shared_dependency.rs +++ b/crates/rspack_plugin_mf/src/sharing/provide_shared_dependency.rs @@ -19,6 +19,7 @@ pub struct ProvideSharedDependency { pub singleton: Option, pub required_version: Option, pub strict_version: Option, + pub treeshake_strategy: Option, resource_identifier: ResourceIdentifier, factorize_info: FactorizeInfo, } @@ -34,6 +35,7 @@ impl ProvideSharedDependency { singleton: Option, required_version: Option, strict_version: Option, + treeshake_strategy: Option, ) -> Self { let resource_identifier = format!( "provide module ({}) {} as {} @ {} {}", @@ -54,6 +56,7 @@ impl ProvideSharedDependency { singleton, required_version, strict_version, + treeshake_strategy, resource_identifier, factorize_info: Default::default(), } diff --git a/crates/rspack_plugin_mf/src/sharing/provide_shared_module.rs b/crates/rspack_plugin_mf/src/sharing/provide_shared_module.rs index 888afd1f2301..bdf8e33c6c06 100644 --- a/crates/rspack_plugin_mf/src/sharing/provide_shared_module.rs +++ b/crates/rspack_plugin_mf/src/sharing/provide_shared_module.rs @@ -40,6 +40,7 @@ pub struct ProvideSharedModule { singleton: Option, required_version: Option, strict_version: Option, + treeshake_strategy: Option, factory_meta: Option, build_info: BuildInfo, build_meta: BuildMeta, @@ -56,6 +57,7 @@ impl ProvideSharedModule { singleton: Option, required_version: Option, strict_version: Option, + treeshake_strategy: Option, ) -> Self { let identifier = format!( "provide shared module ({}) {}@{} = {}", @@ -75,6 +77,7 @@ impl ProvideSharedModule { singleton, required_version, strict_version, + treeshake_strategy, factory_meta: None, build_info: BuildInfo { strict: true, @@ -84,6 +87,10 @@ impl ProvideSharedModule { source_map_kind: SourceMapKind::empty(), } } + + pub fn share_key(&self) -> &str { + &self.name + } } impl Identifiable for ProvideSharedModule { @@ -205,6 +212,7 @@ impl Module for ProvideSharedModule { singleton: self.singleton, strict_version: self.strict_version, required_version: self.required_version.clone(), + treeshake_strategy: self.treeshake_strategy.clone(), }), }], }); diff --git a/crates/rspack_plugin_mf/src/sharing/provide_shared_module_factory.rs b/crates/rspack_plugin_mf/src/sharing/provide_shared_module_factory.rs index 108a7b0fad6e..17475237bd17 100644 --- a/crates/rspack_plugin_mf/src/sharing/provide_shared_module_factory.rs +++ b/crates/rspack_plugin_mf/src/sharing/provide_shared_module_factory.rs @@ -31,6 +31,7 @@ impl ModuleFactory for ProvideSharedModuleFactory { dep.singleton, dep.required_version.clone(), dep.strict_version, + dep.treeshake_strategy.clone(), ) .boxed(), )) diff --git a/crates/rspack_plugin_mf/src/sharing/provide_shared_plugin.rs b/crates/rspack_plugin_mf/src/sharing/provide_shared_plugin.rs index 0d243d60e5fb..1b20fa0753e3 100644 --- a/crates/rspack_plugin_mf/src/sharing/provide_shared_plugin.rs +++ b/crates/rspack_plugin_mf/src/sharing/provide_shared_plugin.rs @@ -35,6 +35,7 @@ pub struct ProvideOptions { pub singleton: Option, pub required_version: Option, pub strict_version: Option, + pub treeshake_strategy: Option, } #[derive(Debug, Clone)] @@ -46,6 +47,7 @@ pub struct VersionedProvideOptions { pub singleton: Option, pub required_version: Option, pub strict_version: Option, + pub treeshake_strategy: Option, } impl ProvideOptions { @@ -58,6 +60,7 @@ impl ProvideOptions { singleton: self.singleton, required_version: self.required_version.clone(), strict_version: self.strict_version, + treeshake_strategy: self.treeshake_strategy.clone(), } } } @@ -109,6 +112,7 @@ impl ProvideSharedPlugin { singleton: Option, required_version: Option, strict_version: Option, + treeshake_strategy: Option, resource: &str, resource_data: &ResourceData, mut add_diagnostic: impl FnMut(Diagnostic), @@ -126,6 +130,7 @@ impl ProvideSharedPlugin { singleton, strict_version, required_version, + treeshake_strategy: treeshake_strategy.clone(), }, ); } else if let Some(description) = resource_data.description() { @@ -143,6 +148,7 @@ impl ProvideSharedPlugin { singleton, strict_version, required_version, + treeshake_strategy: treeshake_strategy.clone(), }, ); } else { @@ -213,6 +219,7 @@ async fn finish_make(&self, compilation: &mut Compilation) -> Result<()> { config.singleton, config.required_version.clone(), config.strict_version, + config.treeshake_strategy.clone(), )) as BoxDependency, EntryOptions { name: None, @@ -256,6 +263,7 @@ async fn normal_module_factory_module( config.singleton, config.required_version.clone(), config.strict_version, + config.treeshake_strategy.clone(), resource, resource_data, |d| data.diagnostics.push(d), @@ -276,6 +284,7 @@ async fn normal_module_factory_module( config.singleton, config.required_version.clone(), config.strict_version, + config.treeshake_strategy.clone(), resource, resource_data, |d| data.diagnostics.push(d), diff --git a/crates/rspack_plugin_mf/src/sharing/share_runtime_module.rs b/crates/rspack_plugin_mf/src/sharing/share_runtime_module.rs index bebc0483f831..feaea9951bf1 100644 --- a/crates/rspack_plugin_mf/src/sharing/share_runtime_module.rs +++ b/crates/rspack_plugin_mf/src/sharing/share_runtime_module.rs @@ -88,11 +88,12 @@ impl RuntimeModule for ShareRuntimeModule { DataInitInfo::ExternalModuleId(Some(id)) => json_stringify(&id), DataInitInfo::ProvideSharedInfo(info) => { let mut stage = format!( - "{{ name: {}, version: {}, factory: {}, eager: {}", + "{{ name: {}, version: {}, factory: {}, eager: {}, treeshakeStrategy: {}", json_stringify(&info.name), json_stringify(&info.version.to_string()), info.factory, if info.eager { "1" } else { "0" }, + json_stringify(&info.treeshake_strategy), ); if self.enhanced { if let Some(singleton) = info.singleton { @@ -182,4 +183,5 @@ pub struct ProvideSharedInfo { pub singleton: Option, pub required_version: Option, pub strict_version: Option, + pub treeshake_strategy: Option, } diff --git a/crates/rspack_plugin_mf/src/sharing/shared_container_dependency.rs b/crates/rspack_plugin_mf/src/sharing/shared_container_dependency.rs new file mode 100644 index 000000000000..81909a2bafed --- /dev/null +++ b/crates/rspack_plugin_mf/src/sharing/shared_container_dependency.rs @@ -0,0 +1,71 @@ +use rspack_cacheable::{cacheable, cacheable_dyn}; +use rspack_core::{ + AsContextDependency, AsDependencyCodeGeneration, Dependency, DependencyCategory, DependencyId, + DependencyType, FactorizeInfo, ModuleDependency, +}; + +#[cacheable] +#[derive(Debug, Clone)] +pub struct SharedContainerDependency { + id: DependencyId, + request: String, + resource_identifier: String, + factorize_info: FactorizeInfo, +} + +impl SharedContainerDependency { + pub fn new(request: String) -> Self { + let resource_identifier = format!("share-container-fallback:{}", request); + Self { + id: DependencyId::new(), + request, + resource_identifier, + factorize_info: Default::default(), + } + } +} + +#[cacheable_dyn] +impl Dependency for SharedContainerDependency { + fn id(&self) -> &DependencyId { + &self.id + } + + fn category(&self) -> &DependencyCategory { + &DependencyCategory::Esm + } + + fn dependency_type(&self) -> &DependencyType { + &DependencyType::ShareContainerFallback + } + + fn resource_identifier(&self) -> Option<&str> { + Some(&self.resource_identifier) + } + + fn could_affect_referencing_module(&self) -> rspack_core::AffectType { + rspack_core::AffectType::True + } +} + +#[cacheable_dyn] +impl ModuleDependency for SharedContainerDependency { + fn request(&self) -> &str { + &self.request + } + + fn user_request(&self) -> &str { + &self.request + } + + fn factorize_info(&self) -> &FactorizeInfo { + &self.factorize_info + } + + fn factorize_info_mut(&mut self) -> &mut FactorizeInfo { + &mut self.factorize_info + } +} + +impl AsContextDependency for SharedContainerDependency {} +impl AsDependencyCodeGeneration for SharedContainerDependency {} diff --git a/crates/rspack_plugin_mf/src/sharing/shared_container_entry_dependency.rs b/crates/rspack_plugin_mf/src/sharing/shared_container_entry_dependency.rs new file mode 100644 index 000000000000..e4774db0e147 --- /dev/null +++ b/crates/rspack_plugin_mf/src/sharing/shared_container_entry_dependency.rs @@ -0,0 +1,78 @@ +use rspack_cacheable::{cacheable, cacheable_dyn}; +use rspack_core::{ + AsContextDependency, AsDependencyCodeGeneration, Dependency, DependencyCategory, DependencyId, + DependencyType, FactorizeInfo, ModuleDependency, +}; +use serde::Serialize; + +#[cacheable] +#[derive(Debug, Clone)] +pub struct SharedContainerEntryDependency { + id: DependencyId, + pub name: String, + pub request: String, + pub version: String, + resource_identifier: String, + factorize_info: FactorizeInfo, +} + +#[cacheable] +#[derive(Debug, Clone, Serialize)] +pub struct ShareContainerEntryOptions { + pub request: String, +} + +impl SharedContainerEntryDependency { + pub fn new(name: String, request: String, version: String) -> Self { + let resource_identifier = format!("share-container-entry-{}", &name); + Self { + id: DependencyId::new(), + name, + request, + version, + resource_identifier, + factorize_info: Default::default(), + } + } +} + +#[cacheable_dyn] +impl Dependency for SharedContainerEntryDependency { + fn id(&self) -> &DependencyId { + &self.id + } + + fn category(&self) -> &DependencyCategory { + &DependencyCategory::Esm + } + + fn dependency_type(&self) -> &DependencyType { + &DependencyType::ShareContainerEntry + } + + fn resource_identifier(&self) -> Option<&str> { + Some(&self.resource_identifier) + } + + fn could_affect_referencing_module(&self) -> rspack_core::AffectType { + rspack_core::AffectType::Transitive + } +} + +#[cacheable_dyn] +impl ModuleDependency for SharedContainerEntryDependency { + fn request(&self) -> &str { + &self.resource_identifier + } + + fn factorize_info(&self) -> &FactorizeInfo { + &self.factorize_info + } + + fn factorize_info_mut(&mut self) -> &mut FactorizeInfo { + &mut self.factorize_info + } +} + +impl AsContextDependency for SharedContainerEntryDependency {} +impl AsDependencyCodeGeneration for SharedContainerEntryDependency {} diff --git a/crates/rspack_plugin_mf/src/sharing/shared_container_entry_module.rs b/crates/rspack_plugin_mf/src/sharing/shared_container_entry_module.rs new file mode 100644 index 000000000000..81b308e9e96b --- /dev/null +++ b/crates/rspack_plugin_mf/src/sharing/shared_container_entry_module.rs @@ -0,0 +1,268 @@ +use std::borrow::Cow; + +use async_trait::async_trait; +use rspack_cacheable::{cacheable, cacheable_dyn}; +use rspack_collections::{Identifiable, Identifier}; +use rspack_core::{ + AsyncDependenciesBlock, AsyncDependenciesBlockIdentifier, BoxDependency, BuildContext, BuildInfo, + BuildMeta, BuildMetaExportsType, BuildResult, CodeGenerationResult, Compilation, + ConcatenationScope, Context, DependenciesBlock, DependencyId, FactoryMeta, LibIdentOptions, + Module, ModuleDependency, ModuleGraph, ModuleIdentifier, ModuleType, RuntimeGlobals, RuntimeSpec, + SourceType, StaticExportsDependency, StaticExportsSpec, impl_module_meta_info, + module_update_hash, + rspack_sources::{BoxSource, RawStringSource, SourceExt}, +}; +use rspack_error::{Result, impl_empty_diagnosable_trait}; +use rspack_hash::{RspackHash, RspackHashDigest}; +use rspack_util::source_map::{ModuleSourceMapConfig, SourceMapKind}; +use rustc_hash::FxHashSet; + +use super::shared_container_dependency::SharedContainerDependency; + +#[cacheable] +#[derive(Debug)] +pub struct SharedContainerEntryModule { + blocks: Vec, + dependencies: Vec, + identifier: ModuleIdentifier, + lib_ident: String, + name: String, + request: String, + version: String, + factory_meta: Option, + build_info: BuildInfo, + build_meta: BuildMeta, + source_map_kind: SourceMapKind, +} + +impl SharedContainerEntryModule { + pub fn new(name: String, request: String, version: String) -> Self { + let lib_ident = format!("webpack/share/container/{}", &name); + Self { + blocks: Vec::new(), + dependencies: Vec::new(), + identifier: ModuleIdentifier::from(format!("share container entry {}@{}", &name, &version,)), + lib_ident, + name, + request, + version, + factory_meta: None, + build_info: BuildInfo { + strict: true, + top_level_declarations: Some(FxHashSet::default()), + ..Default::default() + }, + build_meta: BuildMeta { + exports_type: BuildMetaExportsType::Namespace, + ..Default::default() + }, + source_map_kind: SourceMapKind::empty(), + } + } +} + +impl Identifiable for SharedContainerEntryModule { + fn identifier(&self) -> Identifier { + self.identifier + } +} + +impl DependenciesBlock for SharedContainerEntryModule { + fn add_block_id(&mut self, block: AsyncDependenciesBlockIdentifier) { + self.blocks.push(block) + } + + fn get_blocks(&self) -> &[AsyncDependenciesBlockIdentifier] { + &self.blocks + } + + fn add_dependency_id(&mut self, dependency: DependencyId) { + self.dependencies.push(dependency) + } + + fn remove_dependency_id(&mut self, dependency: DependencyId) { + self.dependencies.retain(|d| d != &dependency) + } + + fn get_dependencies(&self) -> &[DependencyId] { + &self.dependencies + } +} + +#[cacheable_dyn] +#[async_trait] +impl Module for SharedContainerEntryModule { + impl_module_meta_info!(); + + fn size(&self, _source_type: Option<&SourceType>, _compilation: Option<&Compilation>) -> f64 { + 42.0 + } + + fn module_type(&self) -> &ModuleType { + &ModuleType::ShareContainerShared + } + + fn source_types(&self, _module_graph: &ModuleGraph) -> &[SourceType] { + &[SourceType::JavaScript, SourceType::Expose] + } + + fn source(&self) -> Option<&BoxSource> { + None + } + + fn readable_identifier(&self, _context: &Context) -> Cow<'_, str> { + "share container entry".into() + } + + fn lib_ident(&self, _options: LibIdentOptions) -> Option> { + Some(self.lib_ident.as_str().into()) + } + + async fn build( + &mut self, + _build_context: BuildContext, + _: Option<&Compilation>, + ) -> Result { + let mut dependencies: Vec = Vec::new(); + + dependencies.push(Box::new(StaticExportsDependency::new( + StaticExportsSpec::Array(vec!["get".into(), "init".into()]), + false, + ))); + dependencies.push(Box::new(SharedContainerDependency::new(self.name.clone()))); + + Ok(BuildResult { + dependencies, + blocks: Vec::>::new(), + ..Default::default() + }) + } + + async fn code_generation( + &self, + compilation: &Compilation, + _runtime: Option<&RuntimeSpec>, + _: Option, + ) -> Result { + let mut code_generation_result = CodeGenerationResult::default(); + code_generation_result + .runtime_requirements + .insert(RuntimeGlobals::DEFINE_PROPERTY_GETTERS); + code_generation_result + .runtime_requirements + .insert(RuntimeGlobals::EXPORTS); + code_generation_result + .runtime_requirements + .insert(RuntimeGlobals::REQUIRE); + + let module_graph = compilation.get_module_graph(); + let mut factory = String::new(); + for dependency_id in self.get_dependencies() { + let dependency = module_graph + .dependency_by_id(dependency_id) + .expect("share container dependency should exist"); + if let Some(dependency) = dependency.downcast_ref::() { + let module_expr = compilation.runtime_template.module_raw( + compilation, + &mut code_generation_result.runtime_requirements, + dependency_id, + dependency.user_request(), + false, + ); + factory = compilation + .runtime_template + .returning_function(&module_expr, ""); + } + } + + let federation_global = format!( + "{}.federation", + compilation + .runtime_template + .render_runtime_globals(&RuntimeGlobals::REQUIRE) + ); + + // Generate installInitialConsumes function using returning_function + let install_initial_consumes_call = format!( + r#"localBundlerRuntime.installInitialConsumes({{ + installedModules: localInstalledModules, + initialConsumes: __webpack_require__.consumesLoadingData.initialConsumes, + moduleToHandlerMapping: __webpack_require__.federation.consumesLoadingModuleToHandlerMapping, + webpackRequire: __webpack_require__, + asyncLoad: true + }})"# + ); + let install_initial_consumes_fn = compilation + .runtime_template + .returning_function(&install_initial_consumes_call, ""); + + // Create initShareContainer function using basic_function, supporting multi-statement body + let init_body = format!( + r#" + var installedModules = {{}}; + {federation_global}.instance = mfInstance; + {federation_global}.bundlerRuntime = bundlerRuntime; + + // Save parameters to local variables to avoid closure issues + var localBundlerRuntime = bundlerRuntime; + var localInstalledModules = installedModules; + + if(!__webpack_require__.consumesLoadingData){{return; }} + {federation_global}.installInitialConsumes = {install_initial_consumes_fn}; + + return {federation_global}.installInitialConsumes(); + "#, + federation_global = federation_global, + install_initial_consumes_fn = install_initial_consumes_fn + ); + let init_share_container_fn = compilation + .runtime_template + .basic_function("mfInstance, bundlerRuntime", &init_body); + + // Generate the final source string + let source = format!( + r#" + __webpack_require__.federation = {{ instance: undefined,bundlerRuntime: undefined }} + var factory = ()=>{factory}; + var initShareContainer = {init_share_container_fn}; +{runtime}(exports, {{ + get: function() {{ return factory;}}, + init: function() {{ return initShareContainer;}} +}}); +"#, + runtime = compilation + .runtime_template + .render_runtime_globals(&RuntimeGlobals::DEFINE_PROPERTY_GETTERS), + factory = factory, + init_share_container_fn = init_share_container_fn + ); + + // Update the code generation result with the generated source + code_generation_result = + code_generation_result.with_javascript(RawStringSource::from(source).boxed()); + code_generation_result.add(SourceType::Expose, RawStringSource::from_static("").boxed()); + Ok(code_generation_result) + } + + async fn get_runtime_hash( + &self, + compilation: &Compilation, + runtime: Option<&RuntimeSpec>, + ) -> Result { + let mut hasher = RspackHash::from(&compilation.options.output); + module_update_hash(self, &mut hasher, compilation, runtime); + Ok(hasher.digest(&compilation.options.output.hash_digest)) + } +} + +impl_empty_diagnosable_trait!(SharedContainerEntryModule); + +impl ModuleSourceMapConfig for SharedContainerEntryModule { + fn get_source_map_kind(&self) -> &SourceMapKind { + &self.source_map_kind + } + + fn set_source_map_kind(&mut self, source_map: SourceMapKind) { + self.source_map_kind = source_map; + } +} diff --git a/crates/rspack_plugin_mf/src/sharing/shared_container_entry_module_factory.rs b/crates/rspack_plugin_mf/src/sharing/shared_container_entry_module_factory.rs new file mode 100644 index 000000000000..d7c9d5c6a42c --- /dev/null +++ b/crates/rspack_plugin_mf/src/sharing/shared_container_entry_module_factory.rs @@ -0,0 +1,26 @@ +use async_trait::async_trait; +use rspack_core::{ModuleExt, ModuleFactory, ModuleFactoryCreateData, ModuleFactoryResult}; +use rspack_error::Result; + +use super::{ + shared_container_entry_dependency::SharedContainerEntryDependency, + shared_container_entry_module::SharedContainerEntryModule, +}; + +#[derive(Debug)] +pub struct SharedContainerEntryModuleFactory; + +#[async_trait] +impl ModuleFactory for SharedContainerEntryModuleFactory { + async fn create(&self, data: &mut ModuleFactoryCreateData) -> Result { + let dep = data.dependencies[0] + .downcast_ref::() + .expect( + "dependency of SharedContainerEntryModuleFactory should be SharedContainerEntryDependency", + ); + Ok(ModuleFactoryResult::new_with_module( + SharedContainerEntryModule::new(dep.name.clone(), dep.request.clone(), dep.version.clone()) + .boxed(), + )) + } +} diff --git a/crates/rspack_plugin_mf/src/sharing/shared_container_plugin.rs b/crates/rspack_plugin_mf/src/sharing/shared_container_plugin.rs new file mode 100644 index 000000000000..bf4ae375f968 --- /dev/null +++ b/crates/rspack_plugin_mf/src/sharing/shared_container_plugin.rs @@ -0,0 +1,107 @@ +use std::sync::Arc; + +use rspack_core::{ + ChunkUkey, Compilation, CompilationAdditionalTreeRuntimeRequirements, CompilationParams, + CompilerCompilation, CompilerMake, DependencyType, Filename, LibraryOptions, Plugin, + RuntimeGlobals, RuntimeModuleExt, +}; +use rspack_error::Result; +use rspack_hook::{plugin, plugin_hook}; + +use super::{ + shared_container_entry_dependency::SharedContainerEntryDependency, + shared_container_entry_module_factory::SharedContainerEntryModuleFactory, +}; +use crate::sharing::shared_container_runtime_module::ShareContainerRuntimeModule; + +#[derive(Debug)] +pub struct SharedContainerPluginOptions { + pub name: String, + pub request: String, + pub version: String, + pub file_name: Option, + pub library: LibraryOptions, +} + +#[plugin] +#[derive(Debug)] +pub struct SharedContainerPlugin { + options: SharedContainerPluginOptions, +} + +impl SharedContainerPlugin { + pub fn new(options: SharedContainerPluginOptions) -> Self { + Self::new_inner(options) + } +} + +#[plugin_hook(CompilerCompilation for SharedContainerPlugin)] +async fn compilation( + &self, + compilation: &mut Compilation, + params: &mut CompilationParams, +) -> Result<()> { + compilation.set_dependency_factory( + DependencyType::ShareContainerEntry, + Arc::new(SharedContainerEntryModuleFactory), + ); + compilation.set_dependency_factory( + DependencyType::ShareContainerFallback, + params.normal_module_factory.clone(), + ); + Ok(()) +} + +#[plugin_hook(CompilerMake for SharedContainerPlugin)] +async fn make(&self, compilation: &mut Compilation) -> Result<()> { + let dep = SharedContainerEntryDependency::new( + self.options.name.clone(), + self.options.request.clone(), + self.options.version.clone(), + ); + + compilation + .add_entry( + Box::new(dep), + rspack_core::EntryOptions { + name: Some(self.options.name.clone()), + filename: self.options.file_name.clone(), + library: Some(self.options.library.clone()), + ..Default::default() + }, + ) + .await?; + Ok(()) +} + +#[plugin_hook(CompilationAdditionalTreeRuntimeRequirements for SharedContainerPlugin)] +async fn additional_tree_runtime_requirements( + &self, + compilation: &mut Compilation, + chunk_ukey: &ChunkUkey, + _runtime_requirements: &mut RuntimeGlobals, +) -> Result<()> { + let chunk = compilation.chunk_by_ukey.expect_get(chunk_ukey); + if let Some(name) = chunk.name() + && name == self.options.name + { + compilation.add_runtime_module(chunk_ukey, ShareContainerRuntimeModule::new().boxed())?; + } + Ok(()) +} + +impl Plugin for SharedContainerPlugin { + fn name(&self) -> &'static str { + "rspack.SharedContainerPlugin" + } + + fn apply(&self, ctx: &mut rspack_core::ApplyContext<'_>) -> Result<()> { + ctx.compiler_hooks.compilation.tap(compilation::new(self)); + ctx.compiler_hooks.make.tap(make::new(self)); + ctx + .compilation_hooks + .additional_tree_runtime_requirements + .tap(additional_tree_runtime_requirements::new(self)); + Ok(()) + } +} diff --git a/crates/rspack_plugin_mf/src/sharing/shared_container_runtime_module.rs b/crates/rspack_plugin_mf/src/sharing/shared_container_runtime_module.rs new file mode 100644 index 000000000000..09c88b12441d --- /dev/null +++ b/crates/rspack_plugin_mf/src/sharing/shared_container_runtime_module.rs @@ -0,0 +1,40 @@ +use rspack_collections::Identifier; +use rspack_core::{ChunkUkey, Compilation, RuntimeModule, RuntimeModuleStage, impl_runtime_module}; + +#[impl_runtime_module] +#[derive(Debug)] +pub struct ShareContainerRuntimeModule { + id: Identifier, + chunk: Option, +} + +impl ShareContainerRuntimeModule { + pub fn new() -> Self { + Self::with_default( + Identifier::from("webpack/runtime/share_container_federation"), + None, + ) + } +} + +#[async_trait::async_trait] +impl RuntimeModule for ShareContainerRuntimeModule { + fn name(&self) -> Identifier { + self.id + } + + async fn generate(&self, _compilation: &Compilation) -> rspack_error::Result { + Ok( + "__webpack_require__.federation = { instance: undefined,bundlerRuntime: undefined };" + .to_string(), + ) + } + + fn attach(&mut self, chunk: ChunkUkey) { + self.chunk = Some(chunk); + } + + fn stage(&self) -> RuntimeModuleStage { + RuntimeModuleStage::Attach + } +} diff --git a/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_plugin.rs b/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_plugin.rs new file mode 100644 index 000000000000..684cea6323f9 --- /dev/null +++ b/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_plugin.rs @@ -0,0 +1,546 @@ +use std::{ + collections::BTreeMap, + sync::{Arc, RwLock}, +}; + +use rspack_collections::Identifiable; +use rspack_core::{ + AsyncDependenciesBlockIdentifier, ChunkUkey, Compilation, + CompilationAdditionalTreeRuntimeRequirements, CompilationDependencyReferencedExports, + CompilationOptimizeDependencies, CompilationProcessAssets, DependenciesBlock, DependencyId, + DependencyType, ExportsType, ExtendedReferencedExport, Module, ModuleGraph, ModuleIdentifier, + NormalModule, Plugin, RuntimeGlobals, RuntimeModuleExt, RuntimeSpec, + rspack_sources::{RawStringSource, SourceExt, SourceValue}, +}; +use rspack_error::Result; +use rspack_hook::{plugin, plugin_hook}; +use rspack_plugin_javascript::dependency::{ESMImportSpecifierDependency, ImportDependency}; +use rspack_util::atom::Atom; +use rustc_hash::{FxHashMap, FxHashSet}; + +use super::{ + consume_shared_module::ConsumeSharedModule, provide_shared_module::ProvideSharedModule, + shared_container_entry_module::SharedContainerEntryModule, + shared_used_exports_optimizer_runtime_module::SharedUsedExportsOptimizerRuntimeModule, +}; +use crate::manifest::StatsRoot; +#[derive(Debug, Clone)] +pub struct OptimizeSharedConfig { + pub share_key: String, + pub treeshake: bool, + pub used_exports: Vec, +} + +#[derive(Debug, Clone)] +pub struct SharedUsedExportsOptimizerPluginOptions { + pub shared: Vec, + pub inject_used_exports: bool, + pub stats_file_name: Option, + pub manifest_file_name: Option, +} + +#[derive(Debug, Clone)] +struct SharedEntryData { + used_exports: Vec, +} + +#[plugin] +#[derive(Debug, Clone)] +pub struct SharedUsedExportsOptimizerPlugin { + shared_map: FxHashMap, + shared_referenced_exports: Arc>>>, + inject_used_exports: bool, + stats_file_name: Option, + manifest_file_name: Option, +} + +impl SharedUsedExportsOptimizerPlugin { + pub fn new(options: SharedUsedExportsOptimizerPluginOptions) -> Self { + let mut shared_map = FxHashMap::default(); + let inject_used_exports = options.inject_used_exports.clone(); + for config in options.shared.into_iter().filter(|c| c.treeshake) { + let atoms = config + .used_exports + .into_iter() + .map(Atom::from) + .collect::>(); + shared_map.insert( + config.share_key, + SharedEntryData { + used_exports: atoms, + }, + ); + } + + let shared_referenced_exports = Arc::new(RwLock::new( + FxHashMap::>::default(), + )); + + Self::new_inner( + shared_map, + shared_referenced_exports, + inject_used_exports, + options.stats_file_name, + options.manifest_file_name, + ) + } + + fn apply_custom_exports(&self) { + let mut shared_referenced_exports = self + .shared_referenced_exports + .write() + .expect("lock poisoned"); + for (share_key, shared_entry_data) in &self.shared_map { + if let Some(export_set) = shared_referenced_exports.get_mut(share_key) { + for used_export in &shared_entry_data.used_exports { + export_set.insert(used_export.to_string()); + } + } + } + } +} + +fn collect_processed_modules( + module_graph: &ModuleGraph<'_>, + module_blocks: &[AsyncDependenciesBlockIdentifier], + module_deps: &[DependencyId], + out: &mut Vec, +) { + for dep_id in module_deps { + if let Some(target_id) = module_graph.module_identifier_by_dependency_id(dep_id) { + out.push(*target_id); + } + } + + for block_id in module_blocks { + if let Some(block) = module_graph.block_by_id(block_id) { + for dep_id in block.get_dependencies() { + if let Some(target_id) = module_graph.module_identifier_by_dependency_id(dep_id) { + out.push(*target_id); + } + } + } + } +} + +#[plugin_hook( + CompilationOptimizeDependencies for SharedUsedExportsOptimizerPlugin, + stage = 1 +)] +async fn optimize_dependencies(&self, compilation: &mut Compilation) -> Result> { + let module_ids: Vec<_> = { + let module_graph = compilation.get_module_graph(); + module_graph + .modules() + .into_iter() + .map(|(id, _)| id) + .collect() + }; + self.apply_custom_exports(); + + for module_id in module_ids { + let (share_key, modules_to_process) = match { + let module_graph = compilation.get_module_graph(); + let module = module_graph.module_by_identifier(&module_id); + module.and_then(|module| { + let module_type = module.module_type(); + if !matches!( + module_type, + rspack_core::ModuleType::ConsumeShared + | rspack_core::ModuleType::ProvideShared + | rspack_core::ModuleType::ShareContainerShared + ) { + return None; + } + + let mut modules_to_process = Vec::new(); + let share_key = match module_type { + rspack_core::ModuleType::ConsumeShared => { + let consume_shared_module = module.as_any().downcast_ref::()?; + // Use the readable_identifier to extract the share key + // The share key is part of the identifier string in format "consume shared module ({share_scope}) {share_key}@..." + let identifier = + consume_shared_module.readable_identifier(&rspack_core::Context::default()); + let identifier_str = identifier.to_string(); + let parts: Vec<&str> = identifier_str.split(") ").collect(); + if parts.len() < 2 { + return None; + } + let share_key_part = parts[1]; + let share_key_end = share_key_part.find('@').unwrap_or(share_key_part.len()); + let sk: String = share_key_part[..share_key_end].to_string(); + collect_processed_modules( + &module_graph, + consume_shared_module.get_blocks(), + consume_shared_module.get_dependencies(), + &mut modules_to_process, + ); + sk + } + rspack_core::ModuleType::ProvideShared => { + let provide_shared_module = module.as_any().downcast_ref::()?; + let sk = provide_shared_module.share_key().to_string(); + collect_processed_modules( + &module_graph, + provide_shared_module.get_blocks(), + provide_shared_module.get_dependencies(), + &mut modules_to_process, + ); + sk + } + rspack_core::ModuleType::ShareContainerShared => { + let share_container_entry_module = module + .as_any() + .downcast_ref::()?; + // Use the identifier to extract the share key + // The identifier is in format "share container entry {name}@{version}" + let identifier = share_container_entry_module.identifier().to_string(); + let parts: Vec<&str> = identifier.split(' ').collect(); + if parts.len() < 3 { + return None; + } + let name_part = parts[3]; + let name_end = name_part.find('@').unwrap_or(name_part.len()); + let sk = name_part[..name_end].to_string(); + collect_processed_modules( + &module_graph, + share_container_entry_module.get_blocks(), + share_container_entry_module.get_dependencies(), + &mut modules_to_process, + ); + sk + } + _ => return None, + }; + Some((share_key, modules_to_process)) + }) + } { + Some(result) => result, + None => continue, + }; + + if share_key.is_empty() { + continue; + } + + // Get the runtime referenced exports for this share key + let runtime_reference_exports = { + self + .shared_referenced_exports + .read() + .expect("lock poisoned") + .get(&share_key) + .cloned() + }; + // Check if this share key is in our shared map and has treeshake enabled + if !self.shared_map.contains_key(&share_key) { + continue; + } + + if let Some(runtime_reference_exports) = runtime_reference_exports { + if runtime_reference_exports.is_empty() { + continue; + } + + let real_shared_identifier = { + let module_graph = compilation.get_module_graph(); + module_graph.modules().into_iter().find_map(|(id, module)| { + module + .as_any() + .downcast_ref::() + .filter(|normal| normal.raw_request() == share_key) + .map(|_| id) + }) + }; + + // Check if the real shared module is side effect free + if let Some(real_shared_identifier) = real_shared_identifier { + let is_side_effect_free = { + let module_graph = compilation.get_module_graph(); + module_graph + .module_by_identifier(&real_shared_identifier) + .and_then(|module| module.factory_meta().and_then(|meta| meta.side_effect_free)) + .unwrap_or(false) + }; + + dbg!(&is_side_effect_free, &share_key); + if !is_side_effect_free { + // Clear referenced exports for this share_key when module is not side-effect free + if let Ok(mut shared_referenced_exports) = self.shared_referenced_exports.write() { + if let Some(set) = shared_referenced_exports.get_mut(&share_key) { + set.clear(); + } + } + continue; + } + + let mut module_graph_mut = compilation.get_module_graph_mut(); + module_graph_mut.active_all_exports_info(); + // mark used for collected modules + for module_id in &modules_to_process { + let exports_info = module_graph_mut.get_exports_info(module_id); + let exports_info_data = exports_info.as_data_mut(&mut module_graph_mut); + + for export_name in runtime_reference_exports.iter() { + let export_atom = Atom::from(export_name.as_str()); + if let Some(export_info) = exports_info_data.named_exports_mut(&export_atom) { + // export_info.set_used(rspack_core::UsageState::Used, Some(&runtime_spec)); + export_info.set_used(rspack_core::UsageState::Used, None); + } + } + } + + // find if can update real share module + let exports_info = module_graph_mut.get_exports_info(&real_shared_identifier); + let exports_info_data = exports_info.as_data_mut(&mut module_graph_mut); + let can_update_module_used_stage = { + let exports_view = exports_info_data.exports(); + if exports_view.is_empty() { + false + } else { + // Check if all used exports are in the runtime_reference_exports set + exports_view.iter().all(|(name, export_info)| { + let used = export_info.get_used(None); + if used != rspack_core::UsageState::Unknown && used != rspack_core::UsageState::Unused + { + runtime_reference_exports.contains(&name.to_string()) + } else { + true + } + }) + } + }; + if can_update_module_used_stage { + // mark used exports per runtime + // Mark used exports + for export_info in exports_info_data.exports_mut().values_mut() { + export_info.set_used_conditionally( + Box::new(|used| *used == rspack_core::UsageState::Unknown), + rspack_core::UsageState::Unused, + None, + ); + export_info.set_can_mangle_provide(Some(false)); + export_info.set_can_mangle_use(Some(false)); + } + // exports_info_data + // .other_exports_info_mut() + // .set_used_conditionally( + // Box::new(|used| *used == rspack_core::UsageState::Unknown), + // rspack_core::UsageState::Unused, + // None, + // ); + } + } + } + } + + Ok(None) +} + +#[plugin_hook(CompilationProcessAssets for SharedUsedExportsOptimizerPlugin, stage = 1)] +async fn process_assets(&self, compilation: &mut Compilation) -> Result<()> { + let file_names = vec![ + self.stats_file_name.clone(), + self.manifest_file_name.clone(), + ]; + for file_name in file_names { + if let Some(file_name) = &file_name { + if let Some(file) = compilation.assets().get(file_name) { + if let Some(source) = file.get_source() { + if let SourceValue::String(content) = source.source() { + if let Ok(mut stats_root) = serde_json::from_str::(&content) { + let shared_referenced_exports = self + .shared_referenced_exports + .read() + .expect("lock poisoned"); + + for shared in &mut stats_root.shared { + if let Some(exports_set) = shared_referenced_exports.get(&shared.name) { + shared.usedExports = exports_set.iter().cloned().collect::>(); + } + } + + let updated_content = serde_json::to_string_pretty(&stats_root) + .map_err(|e| rspack_error::error!("Failed to serialize stats root: {}", e))?; + + compilation.update_asset(file_name, |_, info| { + Ok((RawStringSource::from(updated_content).boxed(), info)) + })?; + } + } + } + } + } + } + + Ok(()) +} + +#[plugin_hook( + CompilationAdditionalTreeRuntimeRequirements for SharedUsedExportsOptimizerPlugin +)] +async fn additional_tree_runtime_requirements( + &self, + compilation: &mut Compilation, + chunk_ukey: &ChunkUkey, + runtime_requirements: &mut RuntimeGlobals, +) -> Result<()> { + if self.shared_map.is_empty() { + return Ok(()); + } + + runtime_requirements.insert(RuntimeGlobals::RUNTIME_ID); + compilation.add_runtime_module( + chunk_ukey, + SharedUsedExportsOptimizerRuntimeModule::new(Arc::new( + self + .shared_referenced_exports + .read() + .expect("lock poisoned") + .clone(), + )) + .boxed(), + )?; + + Ok(()) +} + +#[plugin_hook(CompilationDependencyReferencedExports for SharedUsedExportsOptimizerPlugin)] +async fn dependency_referenced_exports( + &self, + compilation: &Compilation, + dependency_id: &DependencyId, + referenced_exports: &Option>, + _runtime: Option<&RuntimeSpec>, +) -> Result<()> { + let module_graph = compilation.get_module_graph(); + if referenced_exports.is_none() { + return Ok(()); + } + let Some(exports) = referenced_exports else { + return Ok(()); + }; + + let Some(dependency) = module_graph.dependency_by_id(dependency_id) else { + return Ok(()); + }; + + let Some(module_dependency) = dependency.as_module_dependency() else { + return Ok(()); + }; + + let share_key = module_dependency.request(); + + // Check if dependency type is EsmImportSpecifier and share_key is in shared_map + if !self.shared_map.contains_key(share_key) { + return Ok(()); + } + let mut final_exports = exports.clone(); + // If it's an import dependency and referenced exports indicate "exports object referenced", + // clear any recorded shared referenced exports for this share key and stop here. + let is_exports_object = matches!( + final_exports.as_slice(), + [ExtendedReferencedExport::Array(arr)] if arr.is_empty() + ); + if dependency + .as_any() + .downcast_ref::() + .is_some() + && is_exports_object + { + let mut shared_referenced_exports = self + .shared_referenced_exports + .write() + .expect("lock poisoned"); + shared_referenced_exports.remove(share_key); + return Ok(()); + } + if final_exports.is_empty() || is_exports_object { + if dependency.dependency_type() == &DependencyType::EsmImportSpecifier { + if let Some(esm_dep) = dependency + .as_any() + .downcast_ref::() + { + let ids = esm_dep.get_ids(&module_graph); + if ids.is_empty() { + return Ok(()); + } + if let Some(first) = ids.first() + && *first == "default" + { + final_exports = esm_dep.get_referenced_exports_in_destructuring(Some(ids)); + } else { + final_exports = esm_dep.get_esm_import_specifier_referenced_exports( + &module_graph, + Some(ExportsType::DefaultWithNamed), + ); + } + } + } + } + + // Process each referenced export + if self.shared_map.contains_key(share_key) { + let mut shared_referenced_exports = self + .shared_referenced_exports + .write() + .expect("lock poisoned"); + let export_set = shared_referenced_exports + .entry(share_key.to_string()) + .or_insert_with(|| FxHashSet::default()); + + for referenced_export in &final_exports { + match referenced_export { + ExtendedReferencedExport::Array(exports_array) => { + for export in exports_array { + export_set.insert(export.to_string()); + } + } + ExtendedReferencedExport::Export(referenced) => { + if referenced.name.is_empty() { + continue; + } + let flattened = referenced + .name + .iter() + .map(|atom| atom.to_string()) + .collect::>() + .join("."); + export_set.insert(flattened); + } + } + } + } + Ok(()) +} + +impl Plugin for SharedUsedExportsOptimizerPlugin { + fn name(&self) -> &'static str { + "rspack.sharing.SharedUsedExportsOptimizerPlugin" + } + + fn apply(&self, ctx: &mut rspack_core::ApplyContext<'_>) -> Result<()> { + if self.shared_map.is_empty() { + return Ok(()); + } + ctx + .compilation_hooks + .dependency_referenced_exports + .tap(dependency_referenced_exports::new(self)); + ctx + .compilation_hooks + .optimize_dependencies + .tap(optimize_dependencies::new(self)); + ctx + .compilation_hooks + .process_assets + .tap(process_assets::new(self)); + if self.inject_used_exports { + ctx + .compilation_hooks + .additional_tree_runtime_requirements + .tap(additional_tree_runtime_requirements::new(self)); + } + Ok(()) + } +} diff --git a/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_runtime_module.rs b/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_runtime_module.rs new file mode 100644 index 000000000000..70a9f4b1044e --- /dev/null +++ b/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_runtime_module.rs @@ -0,0 +1,78 @@ +use std::{collections::BTreeMap, sync::Arc}; + +use async_trait::async_trait; +use rspack_collections::Identifier; +use rspack_core::{ + ChunkUkey, Compilation, RuntimeGlobals, RuntimeModule, RuntimeModuleStage, impl_runtime_module, +}; +use rspack_error::{Result, error}; +use rustc_hash::{FxHashMap, FxHashSet}; + +#[impl_runtime_module] +#[derive(Debug)] +pub struct SharedUsedExportsOptimizerRuntimeModule { + id: Identifier, + chunk: Option, + // Keep type consistent with plugin: FxHashMap> + shared_used_exports: Arc>>, +} + +impl SharedUsedExportsOptimizerRuntimeModule { + pub fn new(shared_used_exports: Arc>>) -> Self { + Self::with_default( + Identifier::from("module_federation/shared_used_exports"), + None, + shared_used_exports, + ) + } +} + +#[async_trait] +impl RuntimeModule for SharedUsedExportsOptimizerRuntimeModule { + fn name(&self) -> Identifier { + self.id + } + + fn attach(&mut self, chunk: ChunkUkey) { + self.chunk = Some(chunk); + } + + fn stage(&self) -> RuntimeModuleStage { + RuntimeModuleStage::Attach + } + + async fn generate(&self, compilation: &Compilation) -> Result { + if self.shared_used_exports.is_empty() { + return Ok(String::new()); + } + let federation_global = format!( + "{}.federation", + compilation + .runtime_template + .render_runtime_globals(&RuntimeGlobals::REQUIRE) + ); + // Convert set to vec for JSON serialization stability + let stable_map: BTreeMap> = self + .shared_used_exports + .iter() + .map(|(share_key, set)| { + let mut v: Vec = set.iter().cloned().collect(); + v.sort(); + (share_key.clone(), v) + }) + .collect(); + let used_exports_json = serde_json::to_string(&stable_map).map_err(|err| { + error!( + "OptimizeDependencyReferencedExportsRuntimeModule: failed to serialize used exports: {err}" + ) + })?; + Ok(format!( + r#" +if(!{federation_global}){{return;}} +{federation_global}.usedExports = {used_exports_json}; +"#, + federation_global = federation_global, + used_exports_json = used_exports_json + )) + } +} diff --git a/packages/rspack/etc/core.api.md b/packages/rspack/etc/core.api.md index 0d1a8ada2a6a..2008aae94c49 100644 --- a/packages/rspack/etc/core.api.md +++ b/packages/rspack/etc/core.api.md @@ -1328,6 +1328,7 @@ export type ConsumesConfig = { shareScope?: string; singleton?: boolean; strictVersion?: boolean; + treeshakeStrategy?: 'server' | 'infer'; }; // @public (undocumented) @@ -1346,6 +1347,7 @@ class ConsumeSharedPlugin extends RspackBuiltinPlugin { packageName: string | undefined; singleton: boolean; eager: boolean; + treeshakeStrategy: "server" | "infer" | undefined; }][]; enhanced: boolean; }; @@ -3413,6 +3415,18 @@ type IntermediateFileSystemExtras = { close: (arg0: number, arg1: (arg0: null | NodeJS.ErrnoException) => void) => void; }; +// @public (undocumented) +type InternalManifestPluginOptions = { + name?: string; + globalName?: string; + filePath?: string; + disableAssetsAnalyze?: boolean; + fileName?: string; + remoteAliasMap?: RemoteAliasMap; + exposes?: ManifestExposeOption[]; + shared?: ManifestSharedOption[]; +}; + // @public (undocumented) interface Invalid extends Node_4, HasSpan { // (undocumented) @@ -4822,16 +4836,7 @@ type ModuleDeclaration = ImportDeclaration | ExportDeclaration | ExportNamedDecl type ModuleExportName = Identifier | StringLiteral; // @public (undocumented) -type ModuleFederationManifestPluginOptions = { - name?: string; - globalName?: string; - filePath?: string; - disableAssetsAnalyze?: boolean; - fileName?: string; - remoteAliasMap?: RemoteAliasMap; - exposes?: ManifestExposeOption[]; - shared?: ManifestSharedOption[]; -}; +type ModuleFederationManifestPluginOptions = boolean | Pick; // @public (undocumented) class ModuleFederationPlugin { @@ -4845,7 +4850,11 @@ export interface ModuleFederationPluginOptions extends Omit; + independentShareDir?: string; + // (undocumented) + injectUsedExports?: boolean; + // (undocumented) + manifest?: ModuleFederationManifestPluginOptions; // (undocumented) runtimePlugins?: RuntimePlugins; // (undocumented) @@ -5238,6 +5247,9 @@ export type NoParseOption = NoParseOptionSingle | NoParseOptionSingle[]; // @public (undocumented) type NoParseOptionSingle = string | RegExp | ((request: string) => boolean); +// @public (undocumented) +type NormalizedSharedOptions = [string, SharedConfig][]; + // @public (undocumented) type NormalizedStatsOptions = KnownNormalizedStatsOptions & Omit & Record; @@ -5930,6 +5942,7 @@ type ProvidesEnhancedExtraConfig = { singleton?: boolean; strictVersion?: boolean; requiredVersion?: false | string; + treeshakeStrategy?: 'server' | 'infer'; }; // @public (undocumented) @@ -6630,6 +6643,7 @@ declare namespace rspackExports { SharedItem, SharedObject, SharePluginOptions, + TreeshakeSharedPluginOptions, sharing, LightningcssFeatureOptions, LightningcssLoaderOptions, @@ -7364,6 +7378,7 @@ export type SharedConfig = { singleton?: boolean; strictVersion?: boolean; version?: false | string; + treeshake?: TreeshakeConfig; }; // @public (undocumented) @@ -7392,6 +7407,9 @@ type SharedOptimizationSplitChunksCacheGroup = { automaticNameDelimiter?: string; }; +// @public (undocumented) +type ShareFallback = Record; + // @public (undocumented) class SharePlugin { constructor(options: SharePluginOptions); @@ -7408,6 +7426,7 @@ class SharePlugin { singleton: boolean | undefined; packageName: string | undefined; eager: boolean | undefined; + treeshakeStrategy: "server" | "infer" | undefined; }; }[]; // (undocumented) @@ -7422,9 +7441,12 @@ class SharePlugin { singleton: boolean | undefined; requiredVersion: string | false | undefined; strictVersion: boolean | undefined; + treeshakeStrategy: "server" | "infer" | undefined; }; }[]; // (undocumented) + _sharedOptions: NormalizedSharedOptions; + // (undocumented) _shareScope: string | undefined; } @@ -7438,6 +7460,7 @@ export type SharePluginOptions = { // @public (undocumented) export const sharing: { ProvideSharedPlugin: typeof ProvideSharedPlugin; + TreeShakeSharedPlugin: typeof TreeShakeSharedPlugin; ConsumeSharedPlugin: typeof ConsumeSharedPlugin; SharePlugin: typeof SharePlugin; }; @@ -8421,6 +8444,42 @@ interface TransformConfig { // @public (undocumented) function transformSync(source: string, options?: Options): TransformOutput; +// @public (undocumented) +type TreeshakeConfig = { + usedExports?: string[]; + strategy?: 'server' | 'infer'; + filename?: string; +}; + +// @public (undocumented) +class TreeShakeSharedPlugin { + constructor(options: TreeshakeSharedPluginOptions); + // (undocumented) + apply(compiler: Compiler): void; + // (undocumented) + get buildAssets(): ShareFallback; + // (undocumented) + mfConfig: ModuleFederationPluginOptions; + // (undocumented) + name: string; + // (undocumented) + outputDir: string; + // (undocumented) + plugins?: Plugins; + // (undocumented) + reshake?: boolean; +} + +// @public (undocumented) +export interface TreeshakeSharedPluginOptions { + // (undocumented) + mfConfig: ModuleFederationPluginOptions; + // (undocumented) + plugins?: Plugins; + // (undocumented) + reshake?: boolean; +} + // @public (undocumented) type TruePlusMinus = true | "+" | "-"; diff --git a/packages/rspack/package.json b/packages/rspack/package.json index 6c21f18e179a..c17986b6dd77 100644 --- a/packages/rspack/package.json +++ b/packages/rspack/package.json @@ -60,7 +60,7 @@ "webpack-sources": "3.3.3" }, "dependencies": { - "@module-federation/runtime-tools": "0.21.6", + "@module-federation/runtime-tools": "0.0.0-feat-shared-treeshake-poc-20251208061713", "@rspack/binding": "workspace:*", "@rspack/lite-tapable": "1.1.0" }, diff --git a/packages/rspack/src/container/ContainerPlugin.ts b/packages/rspack/src/container/ContainerPlugin.ts index aecdf9b78d9b..b8540fe07b88 100644 --- a/packages/rspack/src/container/ContainerPlugin.ts +++ b/packages/rspack/src/container/ContainerPlugin.ts @@ -42,7 +42,7 @@ export class ContainerPlugin extends RspackBuiltinPlugin { name: options.name, shareScope: options.shareScope || "default", library: options.library || { - type: "var", + type: "global", name: options.name }, runtime: options.runtime, diff --git a/packages/rspack/src/container/ModuleFederationManifestPlugin.ts b/packages/rspack/src/container/ModuleFederationManifestPlugin.ts index c26bc37909bb..601bf7f5eca2 100644 --- a/packages/rspack/src/container/ModuleFederationManifestPlugin.ts +++ b/packages/rspack/src/container/ModuleFederationManifestPlugin.ts @@ -10,6 +10,13 @@ import { RspackBuiltinPlugin } from "../builtin-plugin/base"; import type { Compiler } from "../Compiler"; +import type { SharedConfig } from "../sharing/SharePlugin"; +import { isRequiredVersion } from "../sharing/utils"; +import { + getRemoteInfos, + type ModuleFederationPluginOptions +} from "./ModuleFederationPlugin"; +import { parseOptions } from "./options"; const MANIFEST_FILE_NAME = "mf-manifest.json"; const STATS_FILE_NAME = "mf-stats.json"; @@ -88,7 +95,7 @@ export type ManifestSharedOption = { singleton?: boolean; }; -export type ModuleFederationManifestPluginOptions = { +type InternalManifestPluginOptions = { name?: string; globalName?: string; filePath?: string; @@ -99,11 +106,27 @@ export type ModuleFederationManifestPluginOptions = { shared?: ManifestSharedOption[]; }; -function getFileName(manifestOptions: ModuleFederationManifestPluginOptions): { +export type ModuleFederationManifestPluginOptions = + | boolean + | Pick< + InternalManifestPluginOptions, + "disableAssetsAnalyze" | "filePath" | "fileName" + >; + +export function getFileName( + manifestOptions: ModuleFederationManifestPluginOptions +): { statsFileName: string; manifestFileName: string; } { if (!manifestOptions) { + return { + statsFileName: "", + manifestFileName: "" + }; + } + + if (typeof manifestOptions === "boolean") { return { statsFileName: STATS_FILE_NAME, manifestFileName: MANIFEST_FILE_NAME @@ -135,16 +158,140 @@ function getFileName(manifestOptions: ModuleFederationManifestPluginOptions): { }; } +function resolveLibraryGlobalName( + library: ModuleFederationPluginOptions["library"] +): string | undefined { + if (!library) { + return undefined; + } + const libName = library.name; + if (!libName) { + return undefined; + } + if (typeof libName === "string") { + return libName; + } + if (Array.isArray(libName)) { + return libName[0]; + } + if (typeof libName === "object") { + return libName.root?.[0] ?? libName.amd ?? libName.commonjs ?? undefined; + } + return undefined; +} + +function collectManifestExposes( + exposes: ModuleFederationPluginOptions["exposes"] +): ManifestExposeOption[] | undefined { + if (!exposes) return undefined; + type NormalizedExpose = { import: string[]; name?: string }; + type ExposesConfigInput = { import: string | string[]; name?: string }; + const parsed = parseOptions( + exposes, + value => ({ + import: Array.isArray(value) ? value : [value], + name: undefined + }), + value => ({ + import: Array.isArray(value.import) ? value.import : [value.import], + name: value.name ?? undefined + }) + ); + const result = parsed.map(([exposeKey, info]) => { + const exposeName = info.name ?? exposeKey.replace(/^\.\//, ""); + return { + path: exposeKey, + name: exposeName + }; + }); + return result.length > 0 ? result : undefined; +} + +function collectManifestShared( + shared: ModuleFederationPluginOptions["shared"] +): ManifestSharedOption[] | undefined { + if (!shared) return undefined; + const parsed = parseOptions( + shared, + (item, key) => { + if (typeof item !== "string") { + throw new Error("Unexpected array in shared"); + } + return item === key || !isRequiredVersion(item) + ? { import: item } + : { import: key, requiredVersion: item }; + }, + item => item + ); + const result = parsed.map(([key, config]) => { + const name = config.shareKey || key; + const version = + typeof config.version === "string" ? config.version : undefined; + const requiredVersion = + typeof config.requiredVersion === "string" + ? config.requiredVersion + : undefined; + return { + name, + version, + requiredVersion, + singleton: config.singleton + }; + }); + return result.length > 0 ? result : undefined; +} + +function normalizeManifestOptions(mfConfig: ModuleFederationPluginOptions) { + const manifestOptions: InternalManifestPluginOptions = + mfConfig.manifest === true ? {} : { ...mfConfig.manifest }; + const containerName = mfConfig.name; + const globalName = + resolveLibraryGlobalName(mfConfig.library) ?? containerName; + const remoteAliasMap: RemoteAliasMap = Object.entries( + getRemoteInfos(mfConfig) + ).reduce((sum, cur) => { + if (cur[1].length > 1) { + // no support multiple remotes + return sum; + } + const remoteInfo = cur[1][0]; + const { entry, alias, name } = remoteInfo; + if (entry && name) { + sum[alias] = { + name, + entry + }; + } + return sum; + }, {}); + + const manifestExposes = collectManifestExposes(mfConfig.exposes); + if (manifestOptions.exposes === undefined && manifestExposes) { + manifestOptions.exposes = manifestExposes; + } + const manifestShared = collectManifestShared(mfConfig.shared); + if (manifestOptions.shared === undefined && manifestShared) { + manifestOptions.shared = manifestShared; + } + + return { + ...manifestOptions, + remoteAliasMap, + globalName, + name: containerName + }; +} + /** * JS-side post-processing plugin: reads mf-manifest.json and mf-stats.json, executes additionalData callback and merges/overwrites manifest. * To avoid cross-NAPI callback complexity, this plugin runs at the afterProcessAssets stage to ensure Rust-side MfManifestPlugin has already output its artifacts. */ export class ModuleFederationManifestPlugin extends RspackBuiltinPlugin { name = BuiltinPluginName.ModuleFederationManifestPlugin; - private opts: ModuleFederationManifestPluginOptions; - constructor(opts: ModuleFederationManifestPluginOptions) { + private opts: InternalManifestPluginOptions; + constructor(opts: ModuleFederationPluginOptions) { super(); - this.opts = opts; + this.opts = normalizeManifestOptions(opts); } raw(compiler: Compiler): BuiltinPlugin { diff --git a/packages/rspack/src/container/ModuleFederationPlugin.ts b/packages/rspack/src/container/ModuleFederationPlugin.ts index 505e56bd5b58..ada7a1334639 100644 --- a/packages/rspack/src/container/ModuleFederationPlugin.ts +++ b/packages/rspack/src/container/ModuleFederationPlugin.ts @@ -1,13 +1,12 @@ import type { Compiler } from "../Compiler"; import type { ExternalsType } from "../config"; +import type { ShareFallback } from "../sharing/IndependentSharedPlugin"; import type { SharedConfig } from "../sharing/SharePlugin"; +import { TreeShakeSharedPlugin } from "../sharing/TreeShakeSharedPlugin"; import { isRequiredVersion } from "../sharing/utils"; import { - type ManifestExposeOption, - type ManifestSharedOption, ModuleFederationManifestPlugin, - type ModuleFederationManifestPluginOptions, - type RemoteAliasMap + type ModuleFederationManifestPluginOptions } from "./ModuleFederationManifestPlugin"; import type { ModuleFederationPluginV1Options } from "./ModuleFederationPluginV1"; import { ModuleFederationRuntimePlugin } from "./ModuleFederationRuntimePlugin"; @@ -20,16 +19,15 @@ export interface ModuleFederationPluginOptions runtimePlugins?: RuntimePlugins; implementation?: string; shareStrategy?: "version-first" | "loaded-first"; - manifest?: - | boolean - | Omit< - ModuleFederationManifestPluginOptions, - "remoteAliasMap" | "globalName" | "name" | "exposes" | "shared" - >; + injectUsedExports?: boolean; + independentShareDir?: string; + manifest?: ModuleFederationManifestPluginOptions; } export type RuntimePlugins = string[] | [string, Record][]; export class ModuleFederationPlugin { + private _treeShakeSharedPlugin?: TreeShakeSharedPlugin; + constructor(private _options: ModuleFederationPluginOptions) {} apply(compiler: Compiler) { @@ -41,13 +39,38 @@ export class ModuleFederationPlugin { ...compiler.options.resolve.alias }; - // Generate the runtime entry content - const entryRuntime = getDefaultEntryRuntime(paths, this._options, compiler); + const sharedOptions = getSharedOptions(this._options); + const treeshakeEntries = sharedOptions.filter( + ([, config]) => config.treeshake + ); + if (treeshakeEntries.length > 0) { + this._treeShakeSharedPlugin = new TreeShakeSharedPlugin({ + mfConfig: this._options, + reshake: false + }); + this._treeShakeSharedPlugin.apply(compiler); + } - // Pass only the entry runtime to the Rust-side plugin - new ModuleFederationRuntimePlugin({ - entryRuntime - }).apply(compiler); + let runtimePluginApplied = false; + compiler.hooks.beforeRun.tapPromise( + { + name: "ModuleFederationPlugin", + stage: 100 + }, + async () => { + if (runtimePluginApplied) return; + runtimePluginApplied = true; + const entryRuntime = getDefaultEntryRuntime( + paths, + this._options, + compiler, + this._treeShakeSharedPlugin?.buildAssets || {} + ); + new ModuleFederationRuntimePlugin({ + entryRuntime + }).apply(compiler); + } + ); new webpack.container.ModuleFederationPluginV1({ ...this._options, @@ -55,46 +78,7 @@ export class ModuleFederationPlugin { }).apply(compiler); if (this._options.manifest) { - const manifestOptions: ModuleFederationManifestPluginOptions = - this._options.manifest === true ? {} : { ...this._options.manifest }; - const containerName = manifestOptions.name ?? this._options.name; - const globalName = - manifestOptions.globalName ?? - resolveLibraryGlobalName(this._options.library) ?? - containerName; - const remoteAliasMap: RemoteAliasMap = Object.entries( - getRemoteInfos(this._options) - ).reduce((sum, cur) => { - if (cur[1].length > 1) { - // no support multiple remotes - return sum; - } - const remoteInfo = cur[1][0]; - const { entry, alias, name } = remoteInfo; - if (entry && name) { - sum[alias] = { - name, - entry - }; - } - return sum; - }, {}); - - const manifestExposes = collectManifestExposes(this._options.exposes); - if (manifestOptions.exposes === undefined && manifestExposes) { - manifestOptions.exposes = manifestExposes; - } - const manifestShared = collectManifestShared(this._options.shared); - if (manifestOptions.shared === undefined && manifestShared) { - manifestOptions.shared = manifestShared; - } - - new ModuleFederationManifestPlugin({ - ...manifestOptions, - name: containerName, - globalName, - remoteAliasMap - }).apply(compiler); + new ModuleFederationManifestPlugin(this._options).apply(compiler); } } } @@ -115,90 +99,9 @@ interface RemoteInfo { type RemoteInfos = Record; -function collectManifestExposes( - exposes: ModuleFederationPluginOptions["exposes"] -): ManifestExposeOption[] | undefined { - if (!exposes) return undefined; - type NormalizedExpose = { import: string[]; name?: string }; - type ExposesConfigInput = { import: string | string[]; name?: string }; - const parsed = parseOptions( - exposes, - (value, key) => ({ - import: Array.isArray(value) ? value : [value], - name: undefined - }), - value => ({ - import: Array.isArray(value.import) ? value.import : [value.import], - name: value.name ?? undefined - }) - ); - const result = parsed.map(([exposeKey, info]) => { - const exposeName = info.name ?? exposeKey.replace(/^\.\//, ""); - return { - path: exposeKey, - name: exposeName - }; - }); - return result.length > 0 ? result : undefined; -} - -function collectManifestShared( - shared: ModuleFederationPluginOptions["shared"] -): ManifestSharedOption[] | undefined { - if (!shared) return undefined; - const parsed = parseOptions( - shared, - (item, key) => { - if (typeof item !== "string") { - throw new Error("Unexpected array in shared"); - } - return item === key || !isRequiredVersion(item) - ? { import: item } - : { import: key, requiredVersion: item }; - }, - item => item - ); - const result = parsed.map(([key, config]) => { - const name = config.shareKey || key; - const version = - typeof config.version === "string" ? config.version : undefined; - const requiredVersion = - typeof config.requiredVersion === "string" - ? config.requiredVersion - : undefined; - return { - name, - version, - requiredVersion, - singleton: config.singleton - }; - }); - return result.length > 0 ? result : undefined; -} - -function resolveLibraryGlobalName( - library: ModuleFederationPluginOptions["library"] -): string | undefined { - if (!library) { - return undefined; - } - const libName = library.name; - if (!libName) { - return undefined; - } - if (typeof libName === "string") { - return libName; - } - if (Array.isArray(libName)) { - return libName[0]; - } - if (typeof libName === "object") { - return libName.root?.[0] ?? libName.amd ?? libName.commonjs ?? undefined; - } - return undefined; -} - -function getRemoteInfos(options: ModuleFederationPluginOptions): RemoteInfos { +export function getRemoteInfos( + options: ModuleFederationPluginOptions +): RemoteInfos { if (!options.remotes) { return {}; } @@ -281,6 +184,24 @@ function getRuntimePlugins(options: ModuleFederationPluginOptions) { return options.runtimePlugins ?? []; } +function getSharedOptions( + options: ModuleFederationPluginOptions +): [string, SharedConfig][] { + if (!options.shared) return []; + return parseOptions( + options.shared, + (item, key) => { + if (typeof item !== "string") { + throw new Error("Unexpected array in shared"); + } + return item === key || !isRequiredVersion(item) + ? { import: item } + : { import: key, requiredVersion: item }; + }, + item => item + ); +} + function getPaths(options: ModuleFederationPluginOptions): RuntimePaths { if (IS_BROWSER) { return { @@ -310,12 +231,14 @@ function getPaths(options: ModuleFederationPluginOptions): RuntimePaths { function getDefaultEntryRuntime( paths: RuntimePaths, options: ModuleFederationPluginOptions, - compiler: Compiler + compiler: Compiler, + treeshakeShareFallbacks: ShareFallback ) { const runtimePlugins = getRuntimePlugins(options); const remoteInfos = getRemoteInfos(options); const runtimePluginImports = []; const runtimePluginVars = []; + const libraryType = options.library?.type || "var"; for (let i = 0; i < runtimePlugins.length; i++) { const runtimePluginVar = `__module_federation_runtime_plugin_${i}__`; const pluginSpec = runtimePlugins[i]; @@ -345,6 +268,10 @@ function getDefaultEntryRuntime( `const __module_federation_share_strategy__ = ${JSON.stringify( options.shareStrategy ?? "version-first" )}`, + `const __module_federation_share_fallbacks__ = ${JSON.stringify( + treeshakeShareFallbacks + )}`, + `const __module_federation_library_type__ = ${JSON.stringify(libraryType)}`, IS_BROWSER ? MF_RUNTIME_CODE : compiler.webpack.Template.getFunctionContent( diff --git a/packages/rspack/src/exports.ts b/packages/rspack/src/exports.ts index 40fef1ca250e..52cee9868820 100644 --- a/packages/rspack/src/exports.ts +++ b/packages/rspack/src/exports.ts @@ -270,6 +270,7 @@ export const container = { import { ConsumeSharedPlugin } from "./sharing/ConsumeSharedPlugin"; import { ProvideSharedPlugin } from "./sharing/ProvideSharedPlugin"; import { SharePlugin } from "./sharing/SharePlugin"; +import { TreeShakeSharedPlugin } from "./sharing/TreeShakeSharedPlugin"; export type { ConsumeSharedPluginOptions, @@ -292,8 +293,10 @@ export type { SharedObject, SharePluginOptions } from "./sharing/SharePlugin"; +export type { TreeshakeSharedPluginOptions } from "./sharing/TreeShakeSharedPlugin"; export const sharing = { ProvideSharedPlugin, + TreeShakeSharedPlugin, ConsumeSharedPlugin, SharePlugin }; diff --git a/packages/rspack/src/runtime/moduleFederationDefaultRuntime.js b/packages/rspack/src/runtime/moduleFederationDefaultRuntime.js index a19796cf01ab..8d86ca703544 100644 --- a/packages/rspack/src/runtime/moduleFederationDefaultRuntime.js +++ b/packages/rspack/src/runtime/moduleFederationDefaultRuntime.js @@ -3,7 +3,9 @@ var __module_federation_bundler_runtime__, __module_federation_runtime_plugins__, __module_federation_remote_infos__, __module_federation_container_name__, - __module_federation_share_strategy__; + __module_federation_share_strategy__, + __module_federation_share_fallbacks__, + __module_federation_library_type__; module.exports = function () { if ( (__webpack_require__.initializeSharingData || @@ -51,6 +53,17 @@ module.exports = function () { __module_federation_bundler_runtime__[key]; } + early( + __webpack_require__.federation, + "libraryType", + () => __module_federation_library_type__ + ); + early( + __webpack_require__.federation, + "sharedFallback", + () => __module_federation_share_fallbacks__ + ); + const sharedFallback = __webpack_require__.federation.sharedFallback; early( __webpack_require__.federation, "consumesLoadingModuleToHandlerMapping", @@ -60,7 +73,17 @@ module.exports = function () { consumesLoadingModuleToConsumeDataMapping )) { consumesLoadingModuleToHandlerMapping[moduleId] = { - getter: data.fallback, + getter: sharedFallback + ? __webpack_require__.federation.bundlerRuntime?.getSharedFallbackGetter( + { + shareKey: data.shareKey, + factory: data.fallback, + webpackRequire: __webpack_require__, + libraryType: __webpack_require__.federation.libraryType + } + ) + : data.fallback, + treeshakeGetter: sharedFallback ? data.fallback : undefined, shareInfo: { shareConfig: { fixedDependencies: false, @@ -71,7 +94,13 @@ module.exports = function () { }, scope: [data.shareScope] }, - shareKey: data.shareKey + shareKey: data.shareKey, + treeshake: __webpack_require__.federation.sharedFallback + ? { + get: data.fallback, + strategy: data.treeshakeStrategy + } + : undefined }; } return consumesLoadingModuleToHandlerMapping; @@ -103,7 +132,8 @@ module.exports = function () { eager, singleton, requiredVersion, - strictVersion + strictVersion, + treeshakeStrategy } = stage; const shareConfig = {}; const isValidValue = function (val) { @@ -125,7 +155,12 @@ module.exports = function () { version, scope: [scope], shareConfig, - get: factory + get: factory, + treeshake: treeshakeStrategy + ? { + strategy: treeshakeStrategy + } + : undefined }; if (shared[name]) { shared[name].push(options); @@ -273,9 +308,9 @@ module.exports = function () { }); __webpack_require__.federation.instance = - __webpack_require__.federation.runtime.init( - __webpack_require__.federation.initOptions - ); + __webpack_require__.federation.bundlerRuntime.init({ + webpackRequire: __webpack_require__ + }); if (__webpack_require__.consumesLoadingData?.initialConsumes) { __webpack_require__.federation.bundlerRuntime.installInitialConsumes({ diff --git a/packages/rspack/src/sharing/CollectSharedEntryPlugin.ts b/packages/rspack/src/sharing/CollectSharedEntryPlugin.ts new file mode 100644 index 000000000000..19f97ea92c69 --- /dev/null +++ b/packages/rspack/src/sharing/CollectSharedEntryPlugin.ts @@ -0,0 +1,89 @@ +import { + type BuiltinPlugin, + BuiltinPluginName, + type RawCollectShareEntryPluginOptions +} from "@rspack/binding"; +import { + createBuiltinPlugin, + RspackBuiltinPlugin +} from "../builtin-plugin/base"; +import type { Compiler } from "../Compiler"; +import { normalizeConsumeShareOptions } from "./ConsumeSharedPlugin"; +import { + createConsumeShareOptions, + type NormalizedSharedOptions +} from "./SharePlugin"; + +export type CollectSharedEntryPluginOptions = { + sharedOptions: NormalizedSharedOptions; + shareScope?: string; +}; + +export type ShareRequestsMap = Record< + string, + { + shareScope: string; + requests: [string, string][]; + } +>; + +const SHARE_ENTRY_ASSET = "collect-shared-entries.json"; +export class CollectSharedEntryPlugin extends RspackBuiltinPlugin { + name = BuiltinPluginName.CollectSharedEntryPlugin; + sharedOptions: NormalizedSharedOptions; + private _collectedEntries: ShareRequestsMap; + + constructor(options: CollectSharedEntryPluginOptions) { + super(); + const { sharedOptions } = options; + + this.sharedOptions = sharedOptions; + this._collectedEntries = {}; + } + + getData() { + return this._collectedEntries; + } + + getFilename() { + return SHARE_ENTRY_ASSET; + } + + apply(compiler: Compiler) { + super.apply(compiler); + + compiler.hooks.thisCompilation.tap("Collect shared entry", compilation => { + compilation.hooks.processAssets.tapPromise( + { + name: "CollectSharedEntry", + stage: + compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_INLINE + }, + async () => { + compilation.getAssets().forEach(asset => { + if (asset.name === SHARE_ENTRY_ASSET) { + this._collectedEntries = JSON.parse( + asset.source.source().toString() + ); + } + compilation.deleteAsset(asset.name); + }); + } + ); + }); + } + + raw(): BuiltinPlugin { + const consumeShareOptions = createConsumeShareOptions(this.sharedOptions); + const normalizedConsumeShareOptions = + normalizeConsumeShareOptions(consumeShareOptions); + const rawOptions: RawCollectShareEntryPluginOptions = { + consumes: normalizedConsumeShareOptions.map(([key, v]) => ({ + key, + ...v + })), + filename: this.getFilename() + }; + return createBuiltinPlugin(this.name, rawOptions); + } +} diff --git a/packages/rspack/src/sharing/ConsumeSharedPlugin.ts b/packages/rspack/src/sharing/ConsumeSharedPlugin.ts index fe5e24105797..ea551b00a9b1 100644 --- a/packages/rspack/src/sharing/ConsumeSharedPlugin.ts +++ b/packages/rspack/src/sharing/ConsumeSharedPlugin.ts @@ -31,8 +31,66 @@ export type ConsumesConfig = { shareScope?: string; singleton?: boolean; strictVersion?: boolean; + /** + * Tree shaking strategy for the shared module. + */ + treeshakeStrategy?: "server" | "infer"; }; +export function normalizeConsumeShareOptions( + consumes: Consumes, + shareScope?: string +) { + return parseOptions( + consumes, + (item, key) => { + if (Array.isArray(item)) throw new Error("Unexpected array in options"); + const result = + item === key || !isRequiredVersion(item) + ? // item is a request/key + { + import: key, + shareScope: shareScope || "default", + shareKey: key, + requiredVersion: undefined, + packageName: undefined, + strictVersion: false, + singleton: false, + eager: false, + treeshakeStrategy: undefined + } + : // key is a request/key + // item is a version + { + import: key, + shareScope: shareScope || "default", + shareKey: key, + requiredVersion: item, + strictVersion: true, + packageName: undefined, + singleton: false, + eager: false, + treeshakeStrategy: undefined + }; + return result; + }, + (item, key) => ({ + import: item.import === false ? undefined : item.import || key, + shareScope: item.shareScope || shareScope || "default", + shareKey: item.shareKey || key, + requiredVersion: item.requiredVersion, + strictVersion: + typeof item.strictVersion === "boolean" + ? item.strictVersion + : item.import !== false && !item.singleton, + packageName: item.packageName, + singleton: !!item.singleton, + eager: !!item.eager, + treeshakeStrategy: item.treeshakeStrategy + }) + ); +} + export class ConsumeSharedPlugin extends RspackBuiltinPlugin { name = BuiltinPluginName.ConsumeSharedPlugin; _options; @@ -40,51 +98,9 @@ export class ConsumeSharedPlugin extends RspackBuiltinPlugin { constructor(options: ConsumeSharedPluginOptions) { super(); this._options = { - consumes: parseOptions( + consumes: normalizeConsumeShareOptions( options.consumes, - (item, key) => { - if (Array.isArray(item)) - throw new Error("Unexpected array in options"); - const result = - item === key || !isRequiredVersion(item) - ? // item is a request/key - { - import: key, - shareScope: options.shareScope || "default", - shareKey: key, - requiredVersion: undefined, - packageName: undefined, - strictVersion: false, - singleton: false, - eager: false - } - : // key is a request/key - // item is a version - { - import: key, - shareScope: options.shareScope || "default", - shareKey: key, - requiredVersion: item, - strictVersion: true, - packageName: undefined, - singleton: false, - eager: false - }; - return result; - }, - (item, key) => ({ - import: item.import === false ? undefined : item.import || key, - shareScope: item.shareScope || options.shareScope || "default", - shareKey: item.shareKey || key, - requiredVersion: item.requiredVersion, - strictVersion: - typeof item.strictVersion === "boolean" - ? item.strictVersion - : item.import !== false && !item.singleton, - packageName: item.packageName, - singleton: !!item.singleton, - eager: !!item.eager - }) + options.shareScope ), enhanced: options.enhanced ?? false }; diff --git a/packages/rspack/src/sharing/IndependentSharedPlugin.ts b/packages/rspack/src/sharing/IndependentSharedPlugin.ts new file mode 100644 index 000000000000..eb8bc1c62415 --- /dev/null +++ b/packages/rspack/src/sharing/IndependentSharedPlugin.ts @@ -0,0 +1,445 @@ +import { join, resolve } from "node:path"; + +import type { Compiler } from "../Compiler"; +import type { LibraryOptions, Plugins, RspackOptions } from "../config"; +import { + getFileName, + type ModuleFederationManifestPluginOptions +} from "../container/ModuleFederationManifestPlugin"; +import { parseOptions } from "../container/options"; +import { + CollectSharedEntryPlugin, + type ShareRequestsMap +} from "./CollectSharedEntryPlugin"; +import { ConsumeSharedPlugin } from "./ConsumeSharedPlugin"; +import { + SharedContainerPlugin, + type SharedContainerPluginOptions +} from "./SharedContainerPlugin"; +import { SharedUsedExportsOptimizerPlugin } from "./SharedUsedExportsOptimizerPlugin"; +import type { Shared, SharedConfig } from "./SharePlugin"; +import { encodeName, isRequiredVersion } from "./utils"; + +const VIRTUAL_ENTRY = "./virtual-entry.js"; +const VIRTUAL_ENTRY_NAME = "virtual-entry"; + +export type MakeRequired = Required> & + Omit; + +const filterPlugin = (plugin: Plugins[0]) => { + if (!plugin) { + return true; + } + const pluginName = plugin.name || plugin.constructor?.name; + if (!pluginName) { + return true; + } + return ![ + "TreeShakeSharedPlugin", + "IndependentSharedPlugin", + "ModuleFederationPlugin", + "SharedUsedExportsOptimizerPlugin", + "HtmlWebpackPlugin" + ].includes(pluginName); +}; + +export interface IndependentSharePluginOptions { + name: string; + shared: Shared; + library?: LibraryOptions; + outputDir?: string; + plugins?: Plugins; + treeshake?: boolean; + manifest?: ModuleFederationManifestPluginOptions; + injectUsedExports?: boolean; +} + +// { react: [ [ react/19.0.0/index.js , 19.0.0, react_global_name ] ] } +export type ShareFallback = Record; + +class VirtualEntryPlugin { + sharedOptions: [string, SharedConfig][]; + constructor(sharedOptions: [string, SharedConfig][]) { + this.sharedOptions = sharedOptions; + } + createEntry() { + const { sharedOptions } = this; + const entryContent = sharedOptions.reduce((acc, cur, index) => { + return `${acc}import shared_${index} from '${cur[0]}';\n`; + }, ""); + return entryContent; + } + + static entry() { + return { + [VIRTUAL_ENTRY_NAME]: VIRTUAL_ENTRY + }; + } + + apply(compiler: Compiler) { + new compiler.rspack.experiments.VirtualModulesPlugin({ + [VIRTUAL_ENTRY]: this.createEntry() + }).apply(compiler); + + compiler.hooks.thisCompilation.tap( + "RemoveVirtualEntryAsset", + compilation => { + compilation.hooks.processAssets.tapPromise( + { + name: "RemoveVirtualEntryAsset", + stage: compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE + }, + async () => { + try { + const chunk = compilation.namedChunks.get(VIRTUAL_ENTRY_NAME); + + chunk?.files.forEach(f => { + compilation.deleteAsset(f); + }); + } catch (_e) { + console.error("Failed to remove virtual entry file!"); + } + } + ); + } + ); + } +} + +const resolveOutputDir = (outputDir: string, shareName?: string) => { + return shareName ? join(outputDir, encodeName(shareName)) : outputDir; +}; + +export class IndependentSharedPlugin { + mfName: string; + shared: Shared; + library?: LibraryOptions; + sharedOptions: [string, SharedConfig][]; + outputDir: string; + plugins: Plugins; + treeshake?: boolean; + manifest?: ModuleFederationManifestPluginOptions; + buildAssets: ShareFallback = {}; + injectUsedExports?: boolean; + + name = "IndependentSharedPlugin"; + constructor(options: IndependentSharePluginOptions) { + const { + outputDir, + plugins, + treeshake, + shared, + name, + manifest, + injectUsedExports, + library + } = options; + this.shared = shared; + this.mfName = name; + this.outputDir = outputDir || "independent-packages"; + this.plugins = plugins || []; + this.treeshake = treeshake; + this.manifest = manifest; + this.injectUsedExports = injectUsedExports ?? true; + this.library = library; + this.sharedOptions = parseOptions( + shared, + (item, key) => { + if (typeof item !== "string") + throw new Error( + `Unexpected array in shared configuration for key "${key}"` + ); + const config: SharedConfig = + item === key || !isRequiredVersion(item) + ? { + import: item + } + : { + import: key, + requiredVersion: item + }; + + return config; + }, + item => { + return item; + } + ); + } + + apply(compiler: Compiler) { + const { manifest } = this; + let runCount = 0; + + compiler.hooks.beforeRun.tapPromise("IndependentSharedPlugin", async () => { + if (runCount) { + return; + } + await this.createIndependentCompilers(compiler); + runCount++; + }); + + compiler.hooks.watchRun.tapPromise("IndependentSharedPlugin", async () => { + if (runCount) { + return; + } + await this.createIndependentCompilers(compiler); + runCount++; + }); + + // clean hooks + compiler.hooks.shutdown.tapAsync("IndependentSharedPlugin", callback => { + callback(); + }); + + // inject buildAssets to stats + if (manifest) { + compiler.hooks.compilation.tap("IndependentSharedPlugin", compilation => { + compilation.hooks.processAssets.tapPromise( + { + name: "injectBuildAssets", + stage: (compilation.constructor as any) + .PROCESS_ASSETS_STAGE_OPTIMIZE_TRANSFER + }, + async () => { + const { statsFileName, manifestFileName } = getFileName(manifest); + const injectBuildAssetsIntoStatsOrManifest = (filename: string) => { + const stats = compilation.getAsset(filename); + if (!stats) { + return; + } + const statsContent = JSON.parse( + stats.source.source().toString() + ) as { + shared: { + name: string; + version: string; + fallback?: string; + fallbackName?: string; + }[]; + }; + + const { shared } = statsContent; + Object.entries(this.buildAssets).forEach(([key, item]) => { + const targetShared = shared.find(s => s.name === key); + if (!targetShared) { + return; + } + item.forEach(([entry, version, globalName]) => { + if (version === targetShared.version) { + targetShared.fallback = entry; + targetShared.fallbackName = globalName; + } + }); + }); + + compilation.updateAsset( + filename, + new compiler.webpack.sources.RawSource( + JSON.stringify(statsContent) + ) + ); + }; + + injectBuildAssetsIntoStatsOrManifest(statsFileName); + injectBuildAssetsIntoStatsOrManifest(manifestFileName); + } + ); + }); + } + } + + private async createIndependentCompilers(parentCompiler: Compiler) { + const { sharedOptions, buildAssets, outputDir } = this; + console.log("🚀 Start creating a standalone compiler..."); + + // collect share requests for each shareName and then build share container + const shareRequestsMap: ShareRequestsMap = + await this.createIndependentCompiler(parentCompiler); + + await Promise.all( + sharedOptions.map(async ([shareName, shareConfig]) => { + if (!shareConfig.treeshake || shareConfig.import === false) { + return; + } + const shareRequests = shareRequestsMap[shareName].requests; + await Promise.all( + shareRequests.map(async ([request, version]) => { + const sharedConfig = sharedOptions.find( + ([name]) => name === shareName + )?.[1]; + const [shareFileName, globalName, sharedVersion] = + await this.createIndependentCompiler(parentCompiler, { + shareRequestsMap, + currentShare: { + shareName, + version, + request, + independentShareFileName: sharedConfig?.treeshake?.filename + } + }); + if (typeof shareFileName === "string") { + buildAssets[shareName] ||= []; + buildAssets[shareName].push([ + join(resolveOutputDir(outputDir, shareName), shareFileName), + sharedVersion, + globalName + ]); + } + }) + ); + }) + ); + + console.log("✅ All independent packages have been compiled successfully"); + } + + private async createIndependentCompiler( + parentCompiler: Compiler, + extraOptions?: { + currentShare: Omit; + shareRequestsMap: ShareRequestsMap; + } + ) { + const { mfName, plugins, outputDir, sharedOptions, treeshake, library } = + this; + + const outputDirWithShareName = resolveOutputDir( + outputDir, + extraOptions?.currentShare?.shareName || "" + ); + const parentConfig = parentCompiler.options; + + const finalPlugins = []; + const rspack = parentCompiler.rspack; + let extraPlugin: CollectSharedEntryPlugin | SharedContainerPlugin; + if (!extraOptions) { + extraPlugin = new CollectSharedEntryPlugin({ + sharedOptions, + shareScope: "default" + }); + } else { + extraPlugin = new SharedContainerPlugin({ + mfName, + library, + ...extraOptions.currentShare + }); + } + (parentConfig.plugins || []).forEach(plugin => { + if ( + plugin !== undefined && + typeof plugin !== "string" && + filterPlugin(plugin) + ) { + finalPlugins.push(plugin); + } + }); + plugins.forEach(plugin => { + finalPlugins.push(plugin); + }); + finalPlugins.push(extraPlugin); + + finalPlugins.push( + new ConsumeSharedPlugin({ + consumes: sharedOptions + .filter( + ([key, options]) => + extraOptions?.currentShare.shareName !== (options.shareKey || key) + ) + .map(([key, options]) => ({ + [key]: { + import: !extraOptions ? options.import : false, + shareKey: options.shareKey || key, + shareScope: options.shareScope, + requiredVersion: options.requiredVersion, + strictVersion: options.strictVersion, + singleton: options.singleton, + packageName: options.packageName, + eager: options.eager + } + })), + enhanced: true + }) + ); + + if (treeshake) { + finalPlugins.push( + new SharedUsedExportsOptimizerPlugin( + sharedOptions, + this.injectUsedExports + ) + ); + } + finalPlugins.push( + new VirtualEntryPlugin(sharedOptions) + // new rspack.experiments.VirtualModulesPlugin({ + // [VIRTUAL_ENTRY]: this.createEntry() + // }) + ); + const fullOutputDir = resolve( + parentCompiler.outputPath, + outputDirWithShareName + ); + const compilerConfig: RspackOptions = { + ...parentConfig, + mode: parentConfig.mode || "development", + + entry: VirtualEntryPlugin.entry, + + output: { + path: fullOutputDir, + clean: true, + publicPath: parentConfig.output?.publicPath || "auto" + }, + + plugins: finalPlugins, + + optimization: { + ...parentConfig.optimization, + splitChunks: false + } + }; + + const compiler = rspack.rspack(compilerConfig); + + compiler.inputFileSystem = parentCompiler.inputFileSystem; + compiler.outputFileSystem = parentCompiler.outputFileSystem; + compiler.intermediateFileSystem = parentCompiler.intermediateFileSystem; + + const { currentShare } = extraOptions || {}; + + return new Promise((resolve, reject) => { + compiler.run((err: any, stats: any) => { + if (err || stats?.hasErrors()) { + const target = currentShare ? currentShare.shareName : "收集依赖"; + console.error( + `❌ ${target} 编译失败:`, + err || + stats + .toJson() + .errors.map((e: Error) => e.message) + .join("\n") + ); + reject(err || new Error(`${target} 编译失败`)); + return; + } + + currentShare && + console.log(`✅ 独立包 ${currentShare.shareName} 编译成功`); + + if (stats) { + currentShare && console.log(`📊 ${currentShare.shareName} 编译统计:`); + console.log( + stats.toString({ + colors: true, + chunks: false, + modules: false + }) + ); + } + + resolve(extraPlugin.getData()); + }); + }); + } +} diff --git a/packages/rspack/src/sharing/ProvideSharedPlugin.ts b/packages/rspack/src/sharing/ProvideSharedPlugin.ts index e3c048de42ed..28d049ee3e49 100644 --- a/packages/rspack/src/sharing/ProvideSharedPlugin.ts +++ b/packages/rspack/src/sharing/ProvideSharedPlugin.ts @@ -37,8 +37,49 @@ type ProvidesEnhancedExtraConfig = { singleton?: boolean; strictVersion?: boolean; requiredVersion?: false | string; + /** + * Tree shaking strategy for the shared module. + */ + treeshakeStrategy?: "server" | "infer"; }; +export function normalizeProvideShareOptions( + options: Provides, + shareScope?: string, + enhanced?: boolean +) { + return parseOptions( + options, + item => { + if (Array.isArray(item)) throw new Error("Unexpected array of provides"); + return { + shareKey: item, + version: undefined, + shareScope: shareScope || "default", + eager: false + }; + }, + item => { + const raw = { + shareKey: item.shareKey, + version: item.version, + shareScope: item.shareScope || shareScope || "default", + eager: !!item.eager + }; + if (enhanced) { + const enhancedItem: ProvidesConfig = item; + return { + ...raw, + singleton: enhancedItem.singleton, + requiredVersion: enhancedItem.requiredVersion, + strictVersion: enhancedItem.strictVersion, + treeshakeStrategy: enhancedItem.treeshakeStrategy + }; + } + return raw; + } + ); +} export class ProvideSharedPlugin< Enhanced extends boolean = false > extends RspackBuiltinPlugin { @@ -48,36 +89,10 @@ export class ProvideSharedPlugin< constructor(options: ProvideSharedPluginOptions) { super(); - this._provides = parseOptions( + this._provides = normalizeProvideShareOptions( options.provides, - item => { - if (Array.isArray(item)) - throw new Error("Unexpected array of provides"); - return { - shareKey: item, - version: undefined, - shareScope: options.shareScope || "default", - eager: false - }; - }, - item => { - const raw = { - shareKey: item.shareKey, - version: item.version, - shareScope: item.shareScope || options.shareScope || "default", - eager: !!item.eager - }; - if (options.enhanced) { - const enhancedItem: ProvidesConfig = item; - return { - ...raw, - singleton: enhancedItem.singleton, - requiredVersion: enhancedItem.requiredVersion, - strictVersion: enhancedItem.strictVersion - }; - } - return raw; - } + options.shareScope, + options.enhanced ); this._enhanced = options.enhanced; } diff --git a/packages/rspack/src/sharing/SharePlugin.ts b/packages/rspack/src/sharing/SharePlugin.ts index 571ebf8bf194..14253f5de90c 100644 --- a/packages/rspack/src/sharing/SharePlugin.ts +++ b/packages/rspack/src/sharing/SharePlugin.ts @@ -14,6 +14,12 @@ export type SharedItem = string; export type SharedObject = { [k: string]: SharedConfig | SharedItem; }; +export type TreeshakeConfig = { + usedExports?: string[]; + strategy?: "server" | "infer"; + filename?: string; +}; + export type SharedConfig = { eager?: boolean; import?: false | SharedItem; @@ -24,62 +30,86 @@ export type SharedConfig = { singleton?: boolean; strictVersion?: boolean; version?: false | string; + treeshake?: TreeshakeConfig; }; -export class SharePlugin { - _shareScope; - _consumes; - _provides; - _enhanced; +export type NormalizedSharedOptions = [string, SharedConfig][]; - constructor(options: SharePluginOptions) { - const sharedOptions = parseOptions( - options.shared, - (item, key) => { - if (typeof item !== "string") - throw new Error("Unexpected array in shared"); - const config: SharedConfig = - item === key || !isRequiredVersion(item) - ? { - import: item - } - : { - import: key, - requiredVersion: item - }; - return config; - }, - item => item - ); - const consumes = sharedOptions.map(([key, options]) => ({ - [key]: { - import: options.import, +export function normalizeSharedOptions( + shared: Shared +): NormalizedSharedOptions { + return parseOptions( + shared, + (item, key) => { + if (typeof item !== "string") + throw new Error("Unexpected array in shared"); + const config: SharedConfig = + item === key || !isRequiredVersion(item) + ? { + import: item + } + : { + import: key, + requiredVersion: item + }; + return config; + }, + item => item + ); +} + +export function createProvideShareOptions( + normalizedSharedOptions: NormalizedSharedOptions +) { + return normalizedSharedOptions + .filter(([, options]) => options.import !== false) + .map(([key, options]) => ({ + [options.import || key]: { shareKey: options.shareKey || key, shareScope: options.shareScope, + version: options.version, + eager: options.eager, + singleton: options.singleton, requiredVersion: options.requiredVersion, strictVersion: options.strictVersion, - singleton: options.singleton, - packageName: options.packageName, - eager: options.eager + treeshakeStrategy: options.treeshake?.strategy } })); - const provides = sharedOptions - .filter(([, options]) => options.import !== false) - .map(([key, options]) => ({ - [options.import || key]: { - shareKey: options.shareKey || key, - shareScope: options.shareScope, - version: options.version, - eager: options.eager, - singleton: options.singleton, - requiredVersion: options.requiredVersion, - strictVersion: options.strictVersion - } - })); +} + +export function createConsumeShareOptions( + normalizedSharedOptions: NormalizedSharedOptions +) { + return normalizedSharedOptions.map(([key, options]) => ({ + [key]: { + import: options.import, + shareKey: options.shareKey || key, + shareScope: options.shareScope, + requiredVersion: options.requiredVersion, + strictVersion: options.strictVersion, + singleton: options.singleton, + packageName: options.packageName, + eager: options.eager, + treeshakeStrategy: options.treeshake?.strategy + } + })); +} +export class SharePlugin { + _shareScope; + _consumes; + _provides; + _enhanced; + _sharedOptions; + + constructor(options: SharePluginOptions) { + const sharedOptions = normalizeSharedOptions(options.shared); + const consumes = createConsumeShareOptions(sharedOptions); + const provides = createProvideShareOptions(sharedOptions); this._shareScope = options.shareScope; this._consumes = consumes; this._provides = provides; this._enhanced = options.enhanced ?? false; + this._sharedOptions = sharedOptions; } apply(compiler: Compiler) { diff --git a/packages/rspack/src/sharing/SharedContainerPlugin.ts b/packages/rspack/src/sharing/SharedContainerPlugin.ts new file mode 100644 index 000000000000..97c87f6a86a2 --- /dev/null +++ b/packages/rspack/src/sharing/SharedContainerPlugin.ts @@ -0,0 +1,116 @@ +import { + type BuiltinPlugin, + BuiltinPluginName, + type RawSharedContainerPluginOptions +} from "@rspack/binding"; +import { + createBuiltinPlugin, + RspackBuiltinPlugin +} from "../builtin-plugin/base"; +import type { Compilation } from "../Compilation"; +import type { Compiler } from "../Compiler"; +import type { LibraryOptions } from "../config"; +import { encodeName } from "./utils"; + +export type SharedContainerPluginOptions = { + mfName: string; + shareName: string; + version: string; + request: string; + library?: LibraryOptions; + independentShareFileName?: string; +}; + +function assert(condition: any, msg: string): asserts condition { + if (!condition) { + throw new Error(msg); + } +} + +const HOT_UPDATE_SUFFIX = ".hot-update"; + +export class SharedContainerPlugin extends RspackBuiltinPlugin { + name = BuiltinPluginName.SharedContainerPlugin; + filename = ""; + _options: RawSharedContainerPluginOptions; + _shareName: string; + _globalName: string; + + constructor(options: SharedContainerPluginOptions) { + super(); + const { shareName, library, request, independentShareFileName, mfName } = + options; + const version = options.version || "0.0.0"; + this._globalName = encodeName(`${mfName}_${shareName}_${version}`); + const fileName = independentShareFileName || `${version}/share-entry.js`; + this._shareName = shareName; + this._options = { + name: shareName, + request: request, + library: (library + ? { ...library, name: this._globalName } + : undefined) || { + type: "global", + name: this._globalName + }, + version, + fileName + }; + } + getData() { + return [this._options.fileName, this._globalName, this._options.version]; + } + + raw(compiler: Compiler): BuiltinPlugin { + const { library } = this._options; + if (!compiler.options.output.enabledLibraryTypes!.includes(library.type)) { + compiler.options.output.enabledLibraryTypes!.push(library.type); + } + return createBuiltinPlugin(this.name, this._options); + } + + apply(compiler: Compiler) { + super.apply(compiler); + const shareName = this._shareName; + compiler.hooks.thisCompilation.tap( + this.name, + (compilation: Compilation) => { + compilation.hooks.processAssets.tapPromise( + { + name: "getShareContainerFile" + }, + async () => { + const remoteEntryPoint = compilation.entrypoints.get(shareName); + assert( + remoteEntryPoint, + `Can not get shared ${shareName} entryPoint!` + ); + const remoteEntryNameChunk = compilation.namedChunks.get(shareName); + assert( + remoteEntryNameChunk, + `Can not get shared ${shareName} chunk!` + ); + + const files = Array.from( + remoteEntryNameChunk.files as Iterable + ).filter( + (f: string) => + !f.includes(HOT_UPDATE_SUFFIX) && !f.endsWith(".css") + ); + assert( + files.length > 0, + `no files found for shared ${shareName} chunk` + ); + assert( + files.length === 1, + `shared ${shareName} chunk should not have multiple files!, current files: ${files.join( + "," + )}` + ); + this.filename = files[0]; + } + ); + } + ); + } +} diff --git a/packages/rspack/src/sharing/SharedUsedExportsOptimizerPlugin.ts b/packages/rspack/src/sharing/SharedUsedExportsOptimizerPlugin.ts new file mode 100644 index 000000000000..7fbbaa1b0a41 --- /dev/null +++ b/packages/rspack/src/sharing/SharedUsedExportsOptimizerPlugin.ts @@ -0,0 +1,65 @@ +import type { + BuiltinPlugin, + RawSharedUsedExportsOptimizerPluginOptions +} from "@rspack/binding"; +import { BuiltinPluginName } from "@rspack/binding"; + +import { + createBuiltinPlugin, + RspackBuiltinPlugin +} from "../builtin-plugin/base"; +import { + getFileName, + type ModuleFederationManifestPluginOptions +} from "../container/ModuleFederationManifestPlugin"; +import type { NormalizedSharedOptions } from "./SharePlugin"; + +type OptimizeSharedConfig = { + shareKey: string; + treeshake: boolean; + usedExports?: string[]; +}; + +export class SharedUsedExportsOptimizerPlugin extends RspackBuiltinPlugin { + name = BuiltinPluginName.SharedUsedExportsOptimizerPlugin; + private sharedOptions: NormalizedSharedOptions; + private injectUsedExports: boolean; + private manifestOptions: ModuleFederationManifestPluginOptions; + + constructor( + sharedOptions: NormalizedSharedOptions, + injectUsedExports?: boolean, + manifestOptions?: ModuleFederationManifestPluginOptions + ) { + super(); + this.sharedOptions = sharedOptions; + this.injectUsedExports = injectUsedExports ?? true; + this.manifestOptions = manifestOptions ?? {}; + } + + private buildOptions(): RawSharedUsedExportsOptimizerPluginOptions { + const shared: OptimizeSharedConfig[] = this.sharedOptions.map( + ([shareKey, config]) => ({ + shareKey, + treeshake: !!config.treeshake, + usedExports: config.treeshake?.usedExports + }) + ); + const { manifestFileName, statsFileName } = getFileName( + this.manifestOptions + ); + return { + shared, + injectUsedExports: this.injectUsedExports, + manifestFileName, + statsFileName + }; + } + + raw(): BuiltinPlugin | undefined { + if (!this.sharedOptions.length) { + return; + } + return createBuiltinPlugin(this.name, this.buildOptions()); + } +} diff --git a/packages/rspack/src/sharing/TreeShakeSharedPlugin.ts b/packages/rspack/src/sharing/TreeShakeSharedPlugin.ts new file mode 100644 index 000000000000..c180cd2ddf4c --- /dev/null +++ b/packages/rspack/src/sharing/TreeShakeSharedPlugin.ts @@ -0,0 +1,69 @@ +import type { Compiler } from "../Compiler"; +import type { Plugins } from "../config"; +import type { ModuleFederationPluginOptions } from "../container/ModuleFederationPlugin"; +import { IndependentSharedPlugin } from "./IndependentSharedPlugin"; +import { SharedUsedExportsOptimizerPlugin } from "./SharedUsedExportsOptimizerPlugin"; +import { normalizeSharedOptions } from "./SharePlugin"; + +export interface TreeshakeSharedPluginOptions { + mfConfig: ModuleFederationPluginOptions; + plugins?: Plugins; + reshake?: boolean; +} + +export class TreeShakeSharedPlugin { + mfConfig: ModuleFederationPluginOptions; + outputDir: string; + plugins?: Plugins; + reshake?: boolean; + private _independentSharePlugin?: IndependentSharedPlugin; + + name = "TreeShakeSharedPlugin"; + constructor(options: TreeshakeSharedPluginOptions) { + const { mfConfig, plugins, reshake } = options; + this.mfConfig = mfConfig; + this.outputDir = mfConfig.independentShareDir || "independent-packages"; + this.plugins = plugins; + this.reshake = Boolean(reshake); + } + + apply(compiler: Compiler) { + const { mfConfig, outputDir, plugins, reshake } = this; + const { name, shared, library } = mfConfig; + if (!shared) { + return; + } + const sharedOptions = normalizeSharedOptions(shared); + if (!sharedOptions.length) { + return; + } + + if ( + sharedOptions.some( + ([_, config]) => config.treeshake && config.import !== false + ) + ) { + if (!reshake) { + new SharedUsedExportsOptimizerPlugin( + sharedOptions, + mfConfig.injectUsedExports, + mfConfig.manifest + ).apply(compiler); + } + this._independentSharePlugin = new IndependentSharedPlugin({ + name: name, + shared: shared, + outputDir, + plugins, + treeshake: reshake, + library, + manifest: mfConfig.manifest + }); + this._independentSharePlugin.apply(compiler); + } + } + + get buildAssets() { + return this._independentSharePlugin?.buildAssets || {}; + } +} diff --git a/packages/rspack/src/sharing/utils.ts b/packages/rspack/src/sharing/utils.ts index 3a89dbd573f3..83d5d62e145d 100644 --- a/packages/rspack/src/sharing/utils.ts +++ b/packages/rspack/src/sharing/utils.ts @@ -3,3 +3,16 @@ const VERSION_PATTERN_REGEXP = /^([\d^=v<>~]|[*xX]$)/; export function isRequiredVersion(str: string) { return VERSION_PATTERN_REGEXP.test(str); } + +export const encodeName = function ( + name: string, + prefix = "", + withExt = false +): string { + const ext = withExt ? ".js" : ""; + return `${prefix}${name + .replace(/@/g, "scope_") + .replace(/-/g, "_") + .replace(/\//g, "__") + .replace(/\./g, "")}${ext}`; +}; diff --git a/packages/rspack/src/taps/types.ts b/packages/rspack/src/taps/types.ts index 2e914497d233..aa56f3cb73fb 100644 --- a/packages/rspack/src/taps/types.ts +++ b/packages/rspack/src/taps/types.ts @@ -19,6 +19,7 @@ type RegisterTapKeys< T, L extends string > = T extends keyof binding.RegisterJsTaps ? (T extends L ? T : never) : never; + type PartialRegisters = { [K in RegisterTapKeys< keyof binding.RegisterJsTaps, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0c0b59af2928..bbc48f169486 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -293,8 +293,8 @@ importers: packages/rspack: dependencies: '@module-federation/runtime-tools': - specifier: 0.21.6 - version: 0.21.6 + specifier: 0.0.0-feat-shared-treeshake-poc-20251208061713 + version: 0.0.0-feat-shared-treeshake-poc-20251208061713 '@rspack/binding': specifier: workspace:* version: link:../../crates/node_binding @@ -2216,36 +2216,54 @@ packages: '@microsoft/tsdoc@0.16.0': resolution: {integrity: sha512-xgAyonlVVS+q7Vc7qLW0UrJU7rSFcETRWsqdXZtjzRU8dF+6CkozTK4V4y1LwOX7j8r/vHphjDeMeGI4tNGeGA==} + '@module-federation/error-codes@0.0.0-feat-shared-treeshake-poc-20251208061713': + resolution: {integrity: sha512-XHG824maYpsTW5AxnAyr/UdZk7Nzjn2eBg+cYhhS6Lkv6E2Zfr7B+kcJex2bjJFso3aHVQ7XXgWjDryI36Lzxw==} + '@module-federation/error-codes@0.21.4': resolution: {integrity: sha512-ClpL5MereWNXh+EgDjz7w4RrC1JlisQTvXDa1gLxpviHafzNDfdViVmuhi9xXVuj+EYo8KU70Y999KHhk9424Q==} '@module-federation/error-codes@0.21.6': resolution: {integrity: sha512-MLJUCQ05KnoVl8xd6xs9a5g2/8U+eWmVxg7xiBMeR0+7OjdWUbHwcwgVFatRIwSZvFgKHfWEiI7wsU1q1XbTRQ==} + '@module-federation/runtime-core@0.0.0-feat-shared-treeshake-poc-20251208061713': + resolution: {integrity: sha512-Cur3LcnigycBkpZt4JCGb1wGPzuvZoedjtKcbqtWLf9C7dQH4uPKkBmcvo+QW/vzzd9HX17ADQAPgQnsmC7z6g==} + '@module-federation/runtime-core@0.21.4': resolution: {integrity: sha512-SGpmoOLGNxZofpTOk6Lxb2ewaoz5wMi93AFYuuJB04HTVcngEK+baNeUZ2D/xewrqNIJoMY6f5maUjVfIIBPUA==} '@module-federation/runtime-core@0.21.6': resolution: {integrity: sha512-5Hd1Y5qp5lU/aTiK66lidMlM/4ji2gr3EXAtJdreJzkY+bKcI5+21GRcliZ4RAkICmvdxQU5PHPL71XmNc7Lsw==} + '@module-federation/runtime-tools@0.0.0-feat-shared-treeshake-poc-20251208061713': + resolution: {integrity: sha512-vyLbzv9vRnxTLpk1OhnHNsExgQsqy3DRnOUHeG0nOauFswetzfrNxPjqMKeaDORoiggIPjlMQkhEPnAalV9q9g==} + '@module-federation/runtime-tools@0.21.4': resolution: {integrity: sha512-RzFKaL0DIjSmkn76KZRfzfB6dD07cvID84950jlNQgdyoQFUGkqD80L6rIpVCJTY/R7LzR3aQjHnoqmq4JPo3w==} '@module-federation/runtime-tools@0.21.6': resolution: {integrity: sha512-fnP+ZOZTFeBGiTAnxve+axGmiYn2D60h86nUISXjXClK3LUY1krUfPgf6MaD4YDJ4i51OGXZWPekeMe16pkd8Q==} + '@module-federation/runtime@0.0.0-feat-shared-treeshake-poc-20251208061713': + resolution: {integrity: sha512-NnO7kaeGipZrOMxHrD8qDtcJwt7WBrr8mS4NrTS5Xxg98MuoRe4H4hD5XvL//o1td9tkbM8Lasr0Nz64k4mnSw==} + '@module-federation/runtime@0.21.4': resolution: {integrity: sha512-wgvGqryurVEvkicufJmTG0ZehynCeNLklv8kIk5BLIsWYSddZAE+xe4xov1kgH5fIJQAoQNkRauFFjVNlHoAkA==} '@module-federation/runtime@0.21.6': resolution: {integrity: sha512-+caXwaQqwTNh+CQqyb4mZmXq7iEemRDrTZQGD+zyeH454JAYnJ3s/3oDFizdH6245pk+NiqDyOOkHzzFQorKhQ==} + '@module-federation/sdk@0.0.0-feat-shared-treeshake-poc-20251208061713': + resolution: {integrity: sha512-89aKxad8ZNLobKRRQI7ipRzHYQx5dbKHcVtFW/nYkZN4HBqooWoaam+l3XcfKWWMRIOXWYg9Q424cR9BIorbSw==} + '@module-federation/sdk@0.21.4': resolution: {integrity: sha512-tzvhOh/oAfX++6zCDDxuvioHY4Jurf8vcfoCbKFxusjmyKr32GPbwFDazUP+OPhYCc3dvaa9oWU6X/qpUBLfJw==} '@module-federation/sdk@0.21.6': resolution: {integrity: sha512-x6hARETb8iqHVhEsQBysuWpznNZViUh84qV2yE7AD+g7uIzHKiYdoWqj10posbo5XKf/147qgWDzKZoKoEP2dw==} + '@module-federation/webpack-bundler-runtime@0.0.0-feat-shared-treeshake-poc-20251208061713': + resolution: {integrity: sha512-ED/yxAQbDDIJLg4PSpuL6eyg9kNJeSyU4/48u9yszSxlFG0AjGjJUAwVEL/HQ9vrS+bc0Y4E6tDSp752L1S3hQ==} + '@module-federation/webpack-bundler-runtime@0.21.4': resolution: {integrity: sha512-dusmR3uPnQh9u9ChQo3M+GLOuGFthfvnh7WitF/a1eoeTfRmXqnMFsXtZCUK+f/uXf+64874Zj/bhAgbBcVHZA==} @@ -9932,10 +9950,17 @@ snapshots: '@microsoft/tsdoc@0.16.0': {} + '@module-federation/error-codes@0.0.0-feat-shared-treeshake-poc-20251208061713': {} + '@module-federation/error-codes@0.21.4': {} '@module-federation/error-codes@0.21.6': {} + '@module-federation/runtime-core@0.0.0-feat-shared-treeshake-poc-20251208061713': + dependencies: + '@module-federation/error-codes': 0.0.0-feat-shared-treeshake-poc-20251208061713 + '@module-federation/sdk': 0.0.0-feat-shared-treeshake-poc-20251208061713 + '@module-federation/runtime-core@0.21.4': dependencies: '@module-federation/error-codes': 0.21.4 @@ -9946,6 +9971,11 @@ snapshots: '@module-federation/error-codes': 0.21.6 '@module-federation/sdk': 0.21.6 + '@module-federation/runtime-tools@0.0.0-feat-shared-treeshake-poc-20251208061713': + dependencies: + '@module-federation/runtime': 0.0.0-feat-shared-treeshake-poc-20251208061713 + '@module-federation/webpack-bundler-runtime': 0.0.0-feat-shared-treeshake-poc-20251208061713 + '@module-federation/runtime-tools@0.21.4': dependencies: '@module-federation/runtime': 0.21.4 @@ -9956,6 +9986,12 @@ snapshots: '@module-federation/runtime': 0.21.6 '@module-federation/webpack-bundler-runtime': 0.21.6 + '@module-federation/runtime@0.0.0-feat-shared-treeshake-poc-20251208061713': + dependencies: + '@module-federation/error-codes': 0.0.0-feat-shared-treeshake-poc-20251208061713 + '@module-federation/runtime-core': 0.0.0-feat-shared-treeshake-poc-20251208061713 + '@module-federation/sdk': 0.0.0-feat-shared-treeshake-poc-20251208061713 + '@module-federation/runtime@0.21.4': dependencies: '@module-federation/error-codes': 0.21.4 @@ -9968,10 +10004,17 @@ snapshots: '@module-federation/runtime-core': 0.21.6 '@module-federation/sdk': 0.21.6 + '@module-federation/sdk@0.0.0-feat-shared-treeshake-poc-20251208061713': {} + '@module-federation/sdk@0.21.4': {} '@module-federation/sdk@0.21.6': {} + '@module-federation/webpack-bundler-runtime@0.0.0-feat-shared-treeshake-poc-20251208061713': + dependencies: + '@module-federation/runtime': 0.0.0-feat-shared-treeshake-poc-20251208061713 + '@module-federation/sdk': 0.0.0-feat-shared-treeshake-poc-20251208061713 + '@module-federation/webpack-bundler-runtime@0.21.4': dependencies: '@module-federation/runtime': 0.21.4 diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/App.js b/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/App.js new file mode 100644 index 000000000000..89e10a92feb9 --- /dev/null +++ b/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/App.js @@ -0,0 +1,23 @@ +import UiLib from 'ui-lib'; +import { Button } from 'ui-lib-es'; + +export default () => { + return `default Uilib has ${Object.keys(UiLib).join( + ', ', + )} exports not treeshake, and ui-lib-es Button value is ${Button} should treeshake`; +}; + +export const dynamicUISpecificExport = async () => { + const { List } = await import('ui-lib-dynamic-specific-export'); + return `dynamic Uilib has ${List} exports treeshake`; +}; + +export const dynamicUIDefaultExport = async () => { + const uiLib = await import('ui-lib-dynamic-default-export'); + return `dynamic Uilib has ${uiLib.List} exports treeshake`; +}; + +export const dynamicUISideEffectExport = async () => { + const uiLibSideEffect = await import('ui-lib-side-effect'); + return `dynamic Uilib has ${uiLibSideEffect.List} exports not treeshake`; +}; diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/index.js b/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/index.js new file mode 100644 index 000000000000..05c24370341d --- /dev/null +++ b/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/index.js @@ -0,0 +1,124 @@ +const fs = __non_webpack_require__('fs'); +const path = __non_webpack_require__('path'); + +__webpack_require__.p = 'PUBLIC_PATH'; +it('should load treeshake shared via set infer strategy', async () => { + const app = await import('./App.js'); + expect(app.default()).toEqual( + 'default Uilib has Button, List, Badge exports not treeshake, and ui-lib-es Button value is Button should treeshake', + ); + + const bundlePath = path.join(__dirname, 'node_modules_ui-lib_index_js.js'); + const bundleContent = fs.readFileSync(bundlePath, 'utf-8'); + expect(bundleContent).toContain('Button'); + expect(bundleContent).toContain('Badge'); + expect(bundleContent).toContain('List'); + + const uiLibShared = + __FEDERATION__.__SHARE__['treeshake_share'].default['ui-lib'][ + '1.0.0' + ]; + expect(uiLibShared.loaded).toEqual(undefined); + expect(uiLibShared.treeshake.loaded).toEqual(true); + expect(Object.keys(uiLibShared.treeshake.lib()).sort()).toEqual([ + 'Button', + 'default', + ]); + + const uiLibFallback = (await uiLibShared.get())(); + expect(Object.keys(uiLibFallback).sort()).toEqual([ + 'Badge', + 'Button', + 'List', + 'default', + ]); + + const uiLibESBundlePath = path.join( + __dirname, + 'node_modules_ui-lib-es_index_js.js', + ); + const uiLibESBundleContent = fs.readFileSync(uiLibESBundlePath, 'utf-8'); + expect(uiLibESBundleContent).toContain('Button'); + expect(uiLibESBundleContent).not.toContain('Badge'); + expect(uiLibESBundleContent).not.toContain('List'); + + const uiLibESShared = + __FEDERATION__.__SHARE__['treeshake_share'].default['ui-lib-es'][ + '1.0.0' + ]; + expect(uiLibESShared.loaded).toEqual(undefined); + expect(uiLibESShared.treeshake.loaded).toEqual(true); + + expect(Object.keys(uiLibESShared.treeshake.lib()).sort()).toEqual(['Button']); + + const esFallback = (await uiLibESShared.get())(); + expect(Object.keys(esFallback).sort()).toEqual(['Badge', 'Button', 'List']); +}); + +it('should treeshake ui-lib-dynamic-specific-export correctly', async () => { + const { dynamicUISpecificExport } = await import('./App.js'); + expect(await dynamicUISpecificExport()).toEqual( + 'dynamic Uilib has List exports treeshake', + ); + + const bundlePath = path.join( + __dirname, + 'node_modules_ui-lib-dynamic-specific-export_index_js.js', + ); + const bundleContent = fs.readFileSync(bundlePath, 'utf-8'); + expect(bundleContent).toContain('List'); + expect(bundleContent).not.toContain('Button'); + expect(bundleContent).not.toContain('Badge'); +}); + +// different from webpack, webpack can not treeshake dynamic import +it('should treeshake ui-lib-dynamic-default-export', async () => { + const { dynamicUIDefaultExport } = await import('./App.js'); + expect(await dynamicUIDefaultExport()).toEqual( + 'dynamic Uilib has List exports treeshake', + ); + + const bundlePath = path.join( + __dirname, + 'node_modules_ui-lib-dynamic-default-export_index_js.js', + ); + const bundleContent = fs.readFileSync(bundlePath, 'utf-8'); + expect(bundleContent).toContain('List'); + expect(bundleContent).not.toContain('Button'); + expect(bundleContent).not.toContain('Badge'); +}); + +it('should not treeshake ui-lib-side-effect if not set sideEffect:false ', async () => { + const { dynamicUISideEffectExport } = await import('./App.js'); + expect(await dynamicUISideEffectExport()).toEqual( + 'dynamic Uilib has List exports not treeshake', + ); + + const bundlePath = path.join( + __dirname, + 'node_modules_ui-lib-side-effect_index_js.js', + ); + const bundleContent = fs.readFileSync(bundlePath, 'utf-8'); + expect(bundleContent).toContain('List'); + expect(bundleContent).toContain('Button'); + expect(bundleContent).toContain('Badge'); +}); + +it('should inject usedExports into entry chunk by default', async () => { + expect( + __webpack_require__.federation.usedExports['ui-lib'].sort(), + ).toEqual(['Button', 'default']); +}); + +it('should inject usedExports into manifest and stats if enable manifest', async () => { + const { Button } = await import('ui-lib'); + expect(Button).toEqual('Button'); + + const statsPath = path.join(__dirname, 'mf-stats.json'); + const statsContent = JSON.parse(fs.readFileSync(statsPath, 'utf-8')); + expect( + JSON.stringify( + statsContent.shared.find((s) => s.name === 'ui-lib').usedExports.sort(), + ), + ).toEqual(JSON.stringify(['Button', 'default'])); +}); diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib-dynamic-default-export/index.js b/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib-dynamic-default-export/index.js new file mode 100644 index 000000000000..9dd1824aaaad --- /dev/null +++ b/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib-dynamic-default-export/index.js @@ -0,0 +1,9 @@ +export const Button = 'Button'; +export const List = 'List' +export const Badge = 'Badge' + +export default { + Button, + List, + Badge +} diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib-dynamic-default-export/package.json b/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib-dynamic-default-export/package.json new file mode 100644 index 000000000000..34effdfca837 --- /dev/null +++ b/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib-dynamic-default-export/package.json @@ -0,0 +1,6 @@ +{ + "name": "ui-lib-dynamic-default-export", + "main": "./index.js", + "version": "1.0.0", + "sideEffects": false +} diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib-dynamic-specific-export/index.js b/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib-dynamic-specific-export/index.js new file mode 100644 index 000000000000..6d4fe4c20ea5 --- /dev/null +++ b/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib-dynamic-specific-export/index.js @@ -0,0 +1,3 @@ +export const Button = 'Button'; +export const List = 'List' +export const Badge = 'Badge' diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib-dynamic-specific-export/package.json b/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib-dynamic-specific-export/package.json new file mode 100644 index 000000000000..e1e4830eb438 --- /dev/null +++ b/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib-dynamic-specific-export/package.json @@ -0,0 +1,6 @@ +{ + "name": "ui-lib-dynamic-specific-export", + "main": "./index.js", + "version": "1.0.0", + "sideEffects": false +} diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib-es/index.js b/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib-es/index.js new file mode 100644 index 000000000000..6d4fe4c20ea5 --- /dev/null +++ b/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib-es/index.js @@ -0,0 +1,3 @@ +export const Button = 'Button'; +export const List = 'List' +export const Badge = 'Badge' diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib-es/package.json b/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib-es/package.json new file mode 100644 index 000000000000..4e05f3fb8558 --- /dev/null +++ b/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib-es/package.json @@ -0,0 +1,6 @@ +{ + "name": "ui-lib-es", + "main": "./index.js", + "version": "1.0.0", + "sideEffects": false +} diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib-side-effect/index.js b/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib-side-effect/index.js new file mode 100644 index 000000000000..0568c23344ad --- /dev/null +++ b/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib-side-effect/index.js @@ -0,0 +1,12 @@ +export const Button = 'Button'; +export const List = 'List' +export const Badge = 'Badge' + +globalThis.Button = Button; +globalThis.List = List; +globalThis.Badge = Badge; +export default { + Button, + List, + Badge +} diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib-side-effect/package.json b/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib-side-effect/package.json new file mode 100644 index 000000000000..08f52aa758de --- /dev/null +++ b/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib-side-effect/package.json @@ -0,0 +1,6 @@ +{ + "name": "ui-lib-side-effect", + "main": "./index.js", + "version": "1.0.0", + "sideEffects": true +} diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib/index.js b/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib/index.js new file mode 100644 index 000000000000..dffb614be886 --- /dev/null +++ b/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib/index.js @@ -0,0 +1,9 @@ +export const List = 'List' +export const Button = 'Button'; +export const Badge = 'Badge' + +export default { + Button, + List, + Badge +} diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib/package.json b/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib/package.json new file mode 100644 index 000000000000..90f9db2691b3 --- /dev/null +++ b/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib/package.json @@ -0,0 +1,6 @@ +{ + "name": "ui-lib", + "main": "./index.js", + "version": "1.0.0", + "sideEffects": false +} diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/rspack.config.js b/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/rspack.config.js new file mode 100644 index 000000000000..34500eda0ce6 --- /dev/null +++ b/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/rspack.config.js @@ -0,0 +1,68 @@ +// eslint-disable-next-line node/no-unpublished-require +const { ModuleFederationPlugin } = require("@rspack/core").container; + +/** @type {import("@rspack/core").Configuration} */ + +module.exports = { + entry: './index.js', + output: { + ignoreBrowserWarnings: true + }, + optimization: { + minimize: true, + chunkIds: 'named', + moduleIds: 'named', + }, + output: { + publicPath: '/', + chunkFilename: '[id].js', + }, + target: 'async-node', + plugins: [ + new ModuleFederationPlugin({ + name: 'treeshake_share', + manifest: true, + filename: 'remoteEntry.js', + library: { + type: 'commonjs-module', + name: 'treeshake_share', + }, + exposes: { + './App': './App.js', + }, + runtimePlugins: [require.resolve('./runtime-plugin.js')], + shared: { + 'ui-lib': { + requiredVersion: '*', + treeshake: { + strategy: 'infer', + }, + }, + 'ui-lib-es': { + requiredVersion: '*', + treeshake: { + strategy: 'infer', + }, + }, + 'ui-lib-dynamic-specific-export': { + requiredVersion: '*', + treeshake: { + strategy: 'infer', + }, + }, + 'ui-lib-dynamic-default-export': { + requiredVersion: '*', + treeshake: { + strategy: 'infer', + }, + }, + 'ui-lib-side-effect': { + requiredVersion: '*', + treeshake: { + strategy: 'infer', + }, + }, + }, + }), + ], +}; diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/runtime-plugin.js b/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/runtime-plugin.js new file mode 100644 index 000000000000..ab2827958f6c --- /dev/null +++ b/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/runtime-plugin.js @@ -0,0 +1,18 @@ +// const path = require('path'); + +// default strategy will use fallback asset if no server data. And the fallback will load asset via fetch + eval. +// Cause the asset not deploy, so we need to proxy the asset to local. +module.exports = function () { + return { + name: 'proxy-shared-asset', + loadEntry: ({ remoteInfo }) => { + const { entry, entryGlobalName } = remoteInfo; + if (entry.includes('PUBLIC_PATH')) { + const relativePath = entry.replace('PUBLIC_PATH', './'); + globalThis[entryGlobalName] = + __non_webpack_require__(relativePath)[entryGlobalName]; + return globalThis[entryGlobalName]; + } + }, + }; +}; diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/test.config.js b/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/test.config.js new file mode 100644 index 000000000000..37df1bd8548c --- /dev/null +++ b/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/test.config.js @@ -0,0 +1,5 @@ +module.exports = { + findBundle: function (i, options) { + return './bundle0.js'; + }, +}; diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/App.js b/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/App.js new file mode 100644 index 000000000000..823b48b590e9 --- /dev/null +++ b/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/App.js @@ -0,0 +1,23 @@ +import UiLib from 'ui-lib'; +import { Button } from 'ui-lib-es'; + +export default () => { + return `default Uilib has ${Object.values(UiLib).join( + ', ', + )} exports not treeshake, and ui-lib-es Button value is ${Button} should treeshake`; +}; + +export const dynamicUISpecificExport = async () => { + const { List } = await import('ui-lib-dynamic-specific-export'); + return `dynamic Uilib has ${List} exports treeshake`; +}; + +export const dynamicUIDefaultExport = async () => { + const uiLib = await import('ui-lib-dynamic-default-export'); + return `dynamic Uilib has ${uiLib.List} exports treeshake`; +}; + +export const dynamicUISideEffectExport = async () => { + const uiLibSideEffect = await import('ui-lib-side-effect'); + return `dynamic Uilib has ${uiLibSideEffect.List} exports not treeshake`; +}; diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/index.js b/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/index.js new file mode 100644 index 000000000000..fb90573cec0b --- /dev/null +++ b/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/index.js @@ -0,0 +1,125 @@ +const fs = __non_webpack_require__('fs'); +const path = __non_webpack_require__('path'); + +__webpack_require__.p = 'PUBLIC_PATH'; +it('should not load treeshake shared via set server strategy and no server data dispatch', async () => { + const app = await import('./App.js'); + expect(app.default()).toEqual( + 'default Uilib has Button, List, Badge exports not treeshake, and ui-lib-es Button value is Button should treeshake', + ); + + const bundlePath = path.join(__dirname, 'node_modules_ui-lib_index_js.js'); + const bundleContent = fs.readFileSync(bundlePath, 'utf-8'); + expect(bundleContent).toContain('Button'); + expect(bundleContent).toContain('Badge'); + expect(bundleContent).toContain('List'); + + const uiLibShared = + __FEDERATION__.__SHARE__['treeshake_share_server:0.0.0'].default['ui-lib'][ + '1.0.0' + ]; + expect(uiLibShared.loaded).toEqual(true); + expect(uiLibShared.treeshake.loaded).toEqual(undefined); + expect(Object.keys(uiLibShared.lib()).sort()).toEqual([ + 'Badge', + 'Button', + 'List', + 'default', + ]); + + const uiLibTreeshake = (await uiLibShared.treeshake.get())(); + expect(Object.keys(uiLibTreeshake).sort()).toEqual(['Button', 'default']); + + const uiLibESBundlePath = path.join( + __dirname, + 'node_modules_ui-lib-es_index_js.js', + ); + const uiLibESBundleContent = fs.readFileSync(uiLibESBundlePath, 'utf-8'); + expect(uiLibESBundleContent).toContain('Button'); + expect(uiLibESBundleContent).not.toContain('Badge'); + expect(uiLibESBundleContent).not.toContain('List'); + + const uiLibESShared = + __FEDERATION__.__SHARE__['treeshake_share_server:0.0.0'].default[ + 'ui-lib-es' + ]['1.0.0']; + expect(uiLibESShared.loaded).toEqual(true); + expect(uiLibESShared.treeshake.loaded).toEqual(undefined); + + expect(Object.keys(uiLibESShared.lib()).sort()).toEqual([ + 'Badge', + 'Button', + 'List', + ]); + + const esTreeshake = (await uiLibESShared.treeshake.get())(); + expect(Object.keys(esTreeshake).sort()).toEqual(['Button']); +}); + +it('should treeshake ui-lib-dynamic-specific-export correctly', async () => { + const { dynamicUISpecificExport } = await import('./App.js'); + expect(await dynamicUISpecificExport()).toEqual( + 'dynamic Uilib has List exports not treeshake', + ); + + const bundlePath = path.join( + __dirname, + 'node_modules_ui-lib-dynamic-specific-export_index_js.js', + ); + const bundleContent = fs.readFileSync(bundlePath, 'utf-8'); + expect(bundleContent).toContain('List'); + expect(bundleContent).not.toContain('Button'); + expect(bundleContent).not.toContain('Badge'); +}); + +it('should treeshake ui-lib-dynamic-default-export', async () => { + const { dynamicUIDefaultExport } = await import('./App.js'); + expect(await dynamicUIDefaultExport()).toEqual( + 'dynamic Uilib has List exports treeshake', + ); + + const bundlePath = path.join( + __dirname, + 'node_modules_ui-lib-dynamic-default-export_index_js.js', + ); + const bundleContent = fs.readFileSync(bundlePath, 'utf-8'); + expect(bundleContent).toContain('List'); + expect(bundleContent).toContain('Button'); + expect(bundleContent).toContain('Badge'); +}); + +it('should not treeshake ui-lib-side-effect if not set sideEffect:false ', async () => { + const { dynamicUISideEffectExport } = await import('./App.js'); + expect(await dynamicUISideEffectExport()).toEqual( + 'dynamic Uilib has List exports not treeshake', + ); + + const bundlePath = path.join( + __dirname, + 'node_modules_ui-lib-side-effect_index_js.js', + ); + const bundleContent = fs.readFileSync(bundlePath, 'utf-8'); + expect(bundleContent).toContain('List'); + expect(bundleContent).toContain('Button'); + expect(bundleContent).toContain('Badge'); +}); + +it('should inject usedExports into entry chunk by default', async () => { + expect(__webpack_require__.federation.usedExports['ui-lib'].sort()).toEqual([ + 'Button', + 'default', + ]); +}); + +it('should inject usedExports into manifest and stats if enable manifest', async () => { + const { Button } = await import('ui-lib'); + expect(Button).toEqual('Button'); + + const statsPath = path.join(__dirname, 'mf-stats.json'); + const statsContent = JSON.parse(fs.readFileSync(statsPath, 'utf-8')); + expect( + JSON.stringify( + statsContent.shared.find((s) => s.name === 'ui-lib').usedExports.sort(), + ), + ).toEqual(JSON.stringify(['Button', 'default'])); +}); diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/.federation/shared-entry.js b/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/.federation/shared-entry.js new file mode 100644 index 000000000000..5d7cf88327ca --- /dev/null +++ b/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/.federation/shared-entry.js @@ -0,0 +1,5 @@ +import shared_0 from 'ui-lib'; +import shared_1 from 'ui-lib-es'; +import shared_2 from 'ui-lib-dynamic-specific-export'; +import shared_3 from 'ui-lib-dynamic-default-export'; +import shared_4 from 'ui-lib-side-effect'; diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib-dynamic-default-export/index.js b/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib-dynamic-default-export/index.js new file mode 100644 index 000000000000..9dd1824aaaad --- /dev/null +++ b/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib-dynamic-default-export/index.js @@ -0,0 +1,9 @@ +export const Button = 'Button'; +export const List = 'List' +export const Badge = 'Badge' + +export default { + Button, + List, + Badge +} diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib-dynamic-default-export/package.json b/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib-dynamic-default-export/package.json new file mode 100644 index 000000000000..34effdfca837 --- /dev/null +++ b/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib-dynamic-default-export/package.json @@ -0,0 +1,6 @@ +{ + "name": "ui-lib-dynamic-default-export", + "main": "./index.js", + "version": "1.0.0", + "sideEffects": false +} diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib-dynamic-specific-export/index.js b/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib-dynamic-specific-export/index.js new file mode 100644 index 000000000000..6d4fe4c20ea5 --- /dev/null +++ b/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib-dynamic-specific-export/index.js @@ -0,0 +1,3 @@ +export const Button = 'Button'; +export const List = 'List' +export const Badge = 'Badge' diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib-dynamic-specific-export/package.json b/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib-dynamic-specific-export/package.json new file mode 100644 index 000000000000..e1e4830eb438 --- /dev/null +++ b/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib-dynamic-specific-export/package.json @@ -0,0 +1,6 @@ +{ + "name": "ui-lib-dynamic-specific-export", + "main": "./index.js", + "version": "1.0.0", + "sideEffects": false +} diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib-es/index.js b/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib-es/index.js new file mode 100644 index 000000000000..6d4fe4c20ea5 --- /dev/null +++ b/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib-es/index.js @@ -0,0 +1,3 @@ +export const Button = 'Button'; +export const List = 'List' +export const Badge = 'Badge' diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib-es/package.json b/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib-es/package.json new file mode 100644 index 000000000000..4e05f3fb8558 --- /dev/null +++ b/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib-es/package.json @@ -0,0 +1,6 @@ +{ + "name": "ui-lib-es", + "main": "./index.js", + "version": "1.0.0", + "sideEffects": false +} diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib-side-effect/index.js b/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib-side-effect/index.js new file mode 100644 index 000000000000..0568c23344ad --- /dev/null +++ b/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib-side-effect/index.js @@ -0,0 +1,12 @@ +export const Button = 'Button'; +export const List = 'List' +export const Badge = 'Badge' + +globalThis.Button = Button; +globalThis.List = List; +globalThis.Badge = Badge; +export default { + Button, + List, + Badge +} diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib-side-effect/package.json b/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib-side-effect/package.json new file mode 100644 index 000000000000..08f52aa758de --- /dev/null +++ b/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib-side-effect/package.json @@ -0,0 +1,6 @@ +{ + "name": "ui-lib-side-effect", + "main": "./index.js", + "version": "1.0.0", + "sideEffects": true +} diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib/index.js b/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib/index.js new file mode 100644 index 000000000000..9dd1824aaaad --- /dev/null +++ b/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib/index.js @@ -0,0 +1,9 @@ +export const Button = 'Button'; +export const List = 'List' +export const Badge = 'Badge' + +export default { + Button, + List, + Badge +} diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib/package.json b/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib/package.json new file mode 100644 index 000000000000..90f9db2691b3 --- /dev/null +++ b/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib/package.json @@ -0,0 +1,6 @@ +{ + "name": "ui-lib", + "main": "./index.js", + "version": "1.0.0", + "sideEffects": false +} diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/rspack.config.js b/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/rspack.config.js new file mode 100644 index 000000000000..d4142514e6d6 --- /dev/null +++ b/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/rspack.config.js @@ -0,0 +1,68 @@ +// eslint-disable-next-line node/no-unpublished-require +const { ModuleFederationPlugin } = require("@rspack/core").container; + +/** @type {import("@rspack/core").Configuration} */ + +module.exports = { + entry: './index.js', + output: { + ignoreBrowserWarnings: true + }, + optimization: { + minimize: true, + chunkIds: 'named', + moduleIds: 'named', + }, + output: { + publicPath: '/', + chunkFilename: '[id].js', + }, + target: 'async-node', + plugins: [ + new ModuleFederationPlugin({ + name: 'treeshake_share', + manifest: true, + filename: 'remoteEntry.js', + library: { + type: 'commonjs-module', + name: 'treeshake_share', + }, + exposes: { + './App': './App.js', + }, + runtimePlugins: [require.resolve('./runtime-plugin.js')], + shared: { + 'ui-lib': { + requiredVersion: '*', + treeshake: { + strategy: 'server', + }, + }, + 'ui-lib-es': { + requiredVersion: '*', + treeshake: { + strategy: 'server', + }, + }, + 'ui-lib-dynamic-specific-export': { + requiredVersion: '*', + treeshake: { + strategy: 'server', + }, + }, + 'ui-lib-dynamic-default-export': { + requiredVersion: '*', + treeshake: { + strategy: 'server', + }, + }, + 'ui-lib-side-effect': { + requiredVersion: '*', + treeshake: { + strategy: 'server', + }, + }, + }, + }), + ], +}; diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/runtime-plugin.js b/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/runtime-plugin.js new file mode 100644 index 000000000000..ab2827958f6c --- /dev/null +++ b/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/runtime-plugin.js @@ -0,0 +1,18 @@ +// const path = require('path'); + +// default strategy will use fallback asset if no server data. And the fallback will load asset via fetch + eval. +// Cause the asset not deploy, so we need to proxy the asset to local. +module.exports = function () { + return { + name: 'proxy-shared-asset', + loadEntry: ({ remoteInfo }) => { + const { entry, entryGlobalName } = remoteInfo; + if (entry.includes('PUBLIC_PATH')) { + const relativePath = entry.replace('PUBLIC_PATH', './'); + globalThis[entryGlobalName] = + __non_webpack_require__(relativePath)[entryGlobalName]; + return globalThis[entryGlobalName]; + } + }, + }; +}; diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/test.config.js b/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/test.config.js new file mode 100644 index 000000000000..37df1bd8548c --- /dev/null +++ b/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/test.config.js @@ -0,0 +1,5 @@ +module.exports = { + findBundle: function (i, options) { + return './bundle0.js'; + }, +}; diff --git a/tests/rspack-test/configCases/sharing/collect-share-entry-plugin/index.js b/tests/rspack-test/configCases/sharing/collect-share-entry-plugin/index.js new file mode 100644 index 000000000000..1831496118e5 --- /dev/null +++ b/tests/rspack-test/configCases/sharing/collect-share-entry-plugin/index.js @@ -0,0 +1,14 @@ +const fs = __non_webpack_require__("fs"); +const path = __non_webpack_require__("path"); + +it("should emit collect share entry asset with expected requests", async () => { + await import('./module'); + const assetPath = path.join(__dirname, "independent-packages/collect-shared-entries-copy.json"); + const content = JSON.parse(fs.readFileSync(assetPath, "utf-8")); + + const collectInfo = content.xreact; + expect(collectInfo).toBeDefined(); + expect(collectInfo.shareScope).toBe("default"); + expect(collectInfo.requests[0][0]).toContain("sharing/collect-share-entry-plugin/node_modules/xreact/index.js"); + expect(collectInfo.requests[0][1]).toEqual("1.0.0"); +}); diff --git a/tests/rspack-test/configCases/sharing/collect-share-entry-plugin/module.js b/tests/rspack-test/configCases/sharing/collect-share-entry-plugin/module.js new file mode 100644 index 000000000000..70a7cb73256d --- /dev/null +++ b/tests/rspack-test/configCases/sharing/collect-share-entry-plugin/module.js @@ -0,0 +1,3 @@ +import "xreact"; + +export default "collect-share-entry-plugin"; diff --git a/tests/rspack-test/configCases/sharing/collect-share-entry-plugin/node_modules/xreact/index.js b/tests/rspack-test/configCases/sharing/collect-share-entry-plugin/node_modules/xreact/index.js new file mode 100644 index 000000000000..ecafa5007699 --- /dev/null +++ b/tests/rspack-test/configCases/sharing/collect-share-entry-plugin/node_modules/xreact/index.js @@ -0,0 +1,4 @@ +module.exports = { + default: "react-mock", + version: "1.0.0" +}; diff --git a/tests/rspack-test/configCases/sharing/collect-share-entry-plugin/node_modules/xreact/package.json b/tests/rspack-test/configCases/sharing/collect-share-entry-plugin/node_modules/xreact/package.json new file mode 100644 index 000000000000..2b5f633e943a --- /dev/null +++ b/tests/rspack-test/configCases/sharing/collect-share-entry-plugin/node_modules/xreact/package.json @@ -0,0 +1,5 @@ +{ + "name": "xreact", + "version": "1.0.0", + "main": "index.js" +} diff --git a/tests/rspack-test/configCases/sharing/collect-share-entry-plugin/package.json b/tests/rspack-test/configCases/sharing/collect-share-entry-plugin/package.json new file mode 100644 index 000000000000..2f0551fad629 --- /dev/null +++ b/tests/rspack-test/configCases/sharing/collect-share-entry-plugin/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "xreact": "1.2.3" + } +} diff --git a/tests/rspack-test/configCases/sharing/collect-share-entry-plugin/rspack.config.js b/tests/rspack-test/configCases/sharing/collect-share-entry-plugin/rspack.config.js new file mode 100644 index 000000000000..c59903ca11af --- /dev/null +++ b/tests/rspack-test/configCases/sharing/collect-share-entry-plugin/rspack.config.js @@ -0,0 +1,39 @@ + +const { container,sources } = require("@rspack/core"); + +/** @type {import("@rspack/core").Configuration} */ +module.exports = { + plugins: [ + new container.ModuleFederationPlugin({ + shared: { + xreact: { + import: "xreact", + shareKey: "xreact", + shareScope: "default", + version: "1.0.0", + treeshake: true + } + }, + }), + { + apply(compiler) { + compiler.hooks.thisCompilation.tap("CollectSharedEntryPlugin", (compilation) => { + compilation.hooks.processAssets.tapPromise( + { + name: "emitCollectSharedEntry", + stage: compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_SIZE + }, + async () => { + const filename = 'collect-shared-entries.json'; + const asset = compilation.getAsset(filename); + if (!asset) { + return; + } + compilation.emitAsset('collect-shared-entries-copy.json', new sources.RawSource(asset.source.source().toString())); + } + ); + }); + } + } + ] +}; diff --git a/tests/rspack-test/configCases/sharing/reshake-share/index.js b/tests/rspack-test/configCases/sharing/reshake-share/index.js new file mode 100644 index 000000000000..d1143f0d5890 --- /dev/null +++ b/tests/rspack-test/configCases/sharing/reshake-share/index.js @@ -0,0 +1,61 @@ +const fs = __non_webpack_require__("fs"); +const path = __non_webpack_require__("path"); + +const independentShareDir = path.join( + __dirname, + "independent-packages" +); + +const customPluginAssetPath = path.join( + independentShareDir, + "apply-plugin.json" +); + +const uiLibShareContainerPath = path.join( + independentShareDir, + "ui_lib/1.0.0", + "share-entry.js" +); + +const uiLibDepShareContainerPath = path.join( + independentShareDir, + "ui_lib_dep/1.0.0", + "share-entry.js" +); + + +it("should build independent share file", () => { + expect(fs.existsSync(uiLibShareContainerPath)).toBe(true); + expect(fs.existsSync(uiLibDepShareContainerPath)).toBe(true); + expect(fs.existsSync(customPluginAssetPath)).toBe(true); +}); + +it("reshake share container should only have specify usedExports", async () => { + const uiLibDepShareContainerModule = __non_webpack_require__(uiLibDepShareContainerPath).reshake_share_ui_lib_dep_100; + await uiLibDepShareContainerModule.init({},{ + installInitialConsumes: async ()=>{ + return 'call init' + } + }); + const shareModules = await uiLibDepShareContainerModule.get(); + expect(shareModules.Message).toBe('Message'); + expect(shareModules.Text).not.toBeDefined(); +}); + + +it("correct handle share dep while reshake", async () => { + const uiLibShareContainerModule = __non_webpack_require__(uiLibShareContainerPath).reshake_share_ui_lib_100; + await uiLibShareContainerModule.init({},{ + installInitialConsumes: async ({webpackRequire})=>{ + webpackRequire.m['webpack/sharing/consume/default/ui-lib-dep'] = (m)=>{ + m.exports = { + Message: 'Message', + } + } + return 'call init' + } + }); + const shareModules = await uiLibShareContainerModule.get(); + expect(shareModules.Badge).toBe('Badge'); + expect(shareModules.MessagePro).toBe('MessagePro'); +}); diff --git a/tests/rspack-test/configCases/sharing/reshake-share/node_modules/ui-lib-dep/index.js b/tests/rspack-test/configCases/sharing/reshake-share/node_modules/ui-lib-dep/index.js new file mode 100644 index 000000000000..c6939e2c6206 --- /dev/null +++ b/tests/rspack-test/configCases/sharing/reshake-share/node_modules/ui-lib-dep/index.js @@ -0,0 +1,9 @@ +export const Message = 'Message'; +export const Spin = 'Spin' +export const Text = 'Text' + +export default { + Message, + Spin, + Text +} diff --git a/tests/rspack-test/configCases/sharing/reshake-share/node_modules/ui-lib-dep/package.json b/tests/rspack-test/configCases/sharing/reshake-share/node_modules/ui-lib-dep/package.json new file mode 100644 index 000000000000..436a74b6795a --- /dev/null +++ b/tests/rspack-test/configCases/sharing/reshake-share/node_modules/ui-lib-dep/package.json @@ -0,0 +1,6 @@ +{ + "name": "ui-lib-dep", + "main": "./index.js", + "version": "1.0.0", + "sideEffects": false +} diff --git a/tests/rspack-test/configCases/sharing/reshake-share/node_modules/ui-lib/index.js b/tests/rspack-test/configCases/sharing/reshake-share/node_modules/ui-lib/index.js new file mode 100644 index 000000000000..c158056185a4 --- /dev/null +++ b/tests/rspack-test/configCases/sharing/reshake-share/node_modules/ui-lib/index.js @@ -0,0 +1,16 @@ +import {Message,Spin} from 'ui-lib-dep'; + +export const Button = 'Button'; +export const List = 'List' +export const Badge = 'Badge' + +export const MessagePro = `${Message}Pro`; +export const SpinPro = `${Spin}Pro`; + +export default { + Button, + List, + Badge, + MessagePro, + SpinPro +} diff --git a/tests/rspack-test/configCases/sharing/reshake-share/node_modules/ui-lib/package.json b/tests/rspack-test/configCases/sharing/reshake-share/node_modules/ui-lib/package.json new file mode 100644 index 000000000000..90f9db2691b3 --- /dev/null +++ b/tests/rspack-test/configCases/sharing/reshake-share/node_modules/ui-lib/package.json @@ -0,0 +1,6 @@ +{ + "name": "ui-lib", + "main": "./index.js", + "version": "1.0.0", + "sideEffects": false +} diff --git a/tests/rspack-test/configCases/sharing/reshake-share/rspack.config.js b/tests/rspack-test/configCases/sharing/reshake-share/rspack.config.js new file mode 100644 index 000000000000..47d774a07270 --- /dev/null +++ b/tests/rspack-test/configCases/sharing/reshake-share/rspack.config.js @@ -0,0 +1,55 @@ +const { TreeShakeSharedPlugin } = require("@rspack/core").sharing; + +/** @type {import("@rspack/core").Configuration} */ +module.exports = { + // entry:'./index.js', + optimization: { + // minimize:false, + chunkIds: "named", + moduleIds: "named" + }, + output: { + chunkFilename: "[id].js" + }, + plugins: [ + new TreeShakeSharedPlugin({ + reshake: true, + plugins: [ + { + apply(compiler) { + compiler.hooks.thisCompilation.tap('applyPlugins', (compilation) => { + compilation.hooks.processAssets.tapPromise( + { + name: 'applyPlugins', + }, + async () => { + compilation.emitAsset('apply-plugin.json', new compilation.compiler.rspack.sources.RawSource(JSON.stringify({ + reshake: true + }))) + }) + }) + } + } + ], + mfConfig: { + name: 'reshake_share', + library: { + type: 'commonjs2', + }, + shared: { + 'ui-lib': { + treeshake: true, + requiredVersion: '*', + usedExports:['Badge','MessagePro'] + }, + 'ui-lib-dep': { + treeshake: true, + requiredVersion: '*', + usedExports:['Message'] + } + }, + + } + }) + ] +}; diff --git a/tests/rspack-test/configCases/sharing/treeshake-share/index.js b/tests/rspack-test/configCases/sharing/treeshake-share/index.js new file mode 100644 index 000000000000..c65b698326b3 --- /dev/null +++ b/tests/rspack-test/configCases/sharing/treeshake-share/index.js @@ -0,0 +1,74 @@ +const fs = __non_webpack_require__("fs"); +const path = __non_webpack_require__("path"); + +it("should treeshake ui-lib correctly", async () => { + const { Button } = await import("ui-lib"); + expect(Button).toEqual('Button'); + + const bundlePath = path.join( + __dirname, + "node_modules_ui-lib_index_js.js" + ); + const bundleContent = fs.readFileSync(bundlePath, "utf-8"); + expect(bundleContent).toContain("Button"); + expect(bundleContent).not.toContain("List"); +}); + +it("should treeshake ui-lib2 correctly", async () => { + const uiLib2 = await import("ui-lib2"); + expect(uiLib2.List).toEqual('List'); + + const bundlePath = path.join( + __dirname, + "node_modules_ui-lib2_index_js.js" + ); + const bundleContent = fs.readFileSync(bundlePath, "utf-8"); + expect(bundleContent).toContain("List"); + expect(bundleContent).not.toContain("Button"); + expect(bundleContent).not.toContain("Badge"); +}); + +it("should not treeshake ui-lib-side-effect if not set sideEffect:false ", async () => { + const uiLibSideEffect = await import("ui-lib-side-effect"); + expect(uiLibSideEffect.List).toEqual('List'); + + const bundlePath = path.join( + __dirname, + "node_modules_ui-lib-side-effect_index_js.js" + ); + const bundleContent = fs.readFileSync(bundlePath, "utf-8"); + expect(bundleContent).toContain("List"); + expect(bundleContent).toContain("Button"); + expect(bundleContent).toContain("Badge"); +}); + +it("should inject usedExports into entry chunk by default", async () => { + expect(__webpack_require__.federation.usedExports['ui-lib']['main'].sort()).toEqual([ 'Badge', 'Button' ]) +}); + +it("should inject usedExports into manifest and stats if enable manifest", async () => { + const { Button } = await import("ui-lib"); + expect(Button).toEqual('Button'); + + const manifestPath = path.join( + __dirname, + "mf-manifest.json" + ); + const manifestContent = JSON.parse(fs.readFileSync(manifestPath, "utf-8")); + expect(JSON.stringify(manifestContent.shared.find(s=>s.name === 'ui-lib').usedExports.sort())).toEqual(JSON.stringify([ + "Badge", + "Button" + ])); + + const statsPath = path.join( + __dirname, + "mf-stats.json" + ); + const statsContent = JSON.parse(fs.readFileSync(statsPath, "utf-8")); + expect(JSON.stringify(statsContent.shared.find(s=>s.name === 'ui-lib').usedExports.sort())).toEqual(JSON.stringify([ + "Badge", + "Button" + ])); +}); + +// it("should ") diff --git a/tests/rspack-test/configCases/sharing/treeshake-share/node_modules/ui-lib-side-effect/index.js b/tests/rspack-test/configCases/sharing/treeshake-share/node_modules/ui-lib-side-effect/index.js new file mode 100644 index 000000000000..0568c23344ad --- /dev/null +++ b/tests/rspack-test/configCases/sharing/treeshake-share/node_modules/ui-lib-side-effect/index.js @@ -0,0 +1,12 @@ +export const Button = 'Button'; +export const List = 'List' +export const Badge = 'Badge' + +globalThis.Button = Button; +globalThis.List = List; +globalThis.Badge = Badge; +export default { + Button, + List, + Badge +} diff --git a/tests/rspack-test/configCases/sharing/treeshake-share/node_modules/ui-lib-side-effect/package.json b/tests/rspack-test/configCases/sharing/treeshake-share/node_modules/ui-lib-side-effect/package.json new file mode 100644 index 000000000000..08f52aa758de --- /dev/null +++ b/tests/rspack-test/configCases/sharing/treeshake-share/node_modules/ui-lib-side-effect/package.json @@ -0,0 +1,6 @@ +{ + "name": "ui-lib-side-effect", + "main": "./index.js", + "version": "1.0.0", + "sideEffects": true +} diff --git a/tests/rspack-test/configCases/sharing/treeshake-share/node_modules/ui-lib/index.js b/tests/rspack-test/configCases/sharing/treeshake-share/node_modules/ui-lib/index.js new file mode 100644 index 000000000000..9dd1824aaaad --- /dev/null +++ b/tests/rspack-test/configCases/sharing/treeshake-share/node_modules/ui-lib/index.js @@ -0,0 +1,9 @@ +export const Button = 'Button'; +export const List = 'List' +export const Badge = 'Badge' + +export default { + Button, + List, + Badge +} diff --git a/tests/rspack-test/configCases/sharing/treeshake-share/node_modules/ui-lib/package.json b/tests/rspack-test/configCases/sharing/treeshake-share/node_modules/ui-lib/package.json new file mode 100644 index 000000000000..90f9db2691b3 --- /dev/null +++ b/tests/rspack-test/configCases/sharing/treeshake-share/node_modules/ui-lib/package.json @@ -0,0 +1,6 @@ +{ + "name": "ui-lib", + "main": "./index.js", + "version": "1.0.0", + "sideEffects": false +} diff --git a/tests/rspack-test/configCases/sharing/treeshake-share/node_modules/ui-lib2/index.js b/tests/rspack-test/configCases/sharing/treeshake-share/node_modules/ui-lib2/index.js new file mode 100644 index 000000000000..9dd1824aaaad --- /dev/null +++ b/tests/rspack-test/configCases/sharing/treeshake-share/node_modules/ui-lib2/index.js @@ -0,0 +1,9 @@ +export const Button = 'Button'; +export const List = 'List' +export const Badge = 'Badge' + +export default { + Button, + List, + Badge +} diff --git a/tests/rspack-test/configCases/sharing/treeshake-share/node_modules/ui-lib2/package.json b/tests/rspack-test/configCases/sharing/treeshake-share/node_modules/ui-lib2/package.json new file mode 100644 index 000000000000..1299fb07efbe --- /dev/null +++ b/tests/rspack-test/configCases/sharing/treeshake-share/node_modules/ui-lib2/package.json @@ -0,0 +1,6 @@ +{ + "name": "ui-lib2", + "main": "./index.js", + "version": "1.0.0", + "sideEffects": false +} diff --git a/tests/rspack-test/configCases/sharing/treeshake-share/rspack.config.js b/tests/rspack-test/configCases/sharing/treeshake-share/rspack.config.js new file mode 100644 index 000000000000..deba8c91a473 --- /dev/null +++ b/tests/rspack-test/configCases/sharing/treeshake-share/rspack.config.js @@ -0,0 +1,36 @@ +const { container } = require("@rspack/core"); + +const { ModuleFederationPlugin } = container; + +/** @type {import("@rspack/core").Configuration} */ +module.exports = { + optimization:{ + minimize: false, + chunkIds:'named', + moduleIds: 'named' + }, + output: { + chunkFilename: "[id].js" + }, + plugins: [ + new ModuleFederationPlugin({ + name:'treeshake_share', + manifest: true, + shared: { + 'ui-lib': { + requiredVersion:'*', + treeshake:true, + usedExports: ['Badge'] + }, + 'ui-lib2': { + requiredVersion:'*', + treeshake:true, + }, + 'ui-lib-side-effect': { + requiredVersion:'*', + treeshake:true, + } + } + }) + ] +}; diff --git a/website/docs/en/plugins/webpack/tree-shake-shared-plugin.mdx b/website/docs/en/plugins/webpack/tree-shake-shared-plugin.mdx new file mode 100644 index 000000000000..1b16d5496b58 --- /dev/null +++ b/website/docs/en/plugins/webpack/tree-shake-shared-plugin.mdx @@ -0,0 +1,45 @@ +import { Stability, ApiMeta } from '@components/ApiMeta'; + +# TreeShakeSharedPlugin + + + +**Overview** + +- Performs on-demand build and export optimization for `shared` dependencies based on Module Federation configuration. + +**Options** + +- `mfConfig`: `ModuleFederationPluginOptions`, configuration passed to the Module Federation plugin. +- `plugins`: extra plugins reused during independent builds. +- `reshake`: whether to perform a second tree-shake during independent builds (typically used when the deployment platform has determined complete dependency info and triggers a fresh build to improve tree-shake accuracy for shared dependencies). + +**Usage** + +```js +// rspack.config.js +const { TreeShakeSharedPlugin } = require('@rspack/core'); + +module.exports = { + plugins: [ + new TreeShakeSharedPlugin({ + reshake: true, + mfConfig: { + name: 'app', + shared: { + 'lodash-es': { treeshake: true }, + }, + library: { type: 'var', name: 'App' }, + manifest: true, + }, + plugins: [], + }), + ], +}; +``` + +**Behavior** + +- Normalizes `shared` into `[shareName, SharedConfig][]`. +- Registers `SharedUsedExportsOptimizerPlugin` when `reshake` is `false` to inject used-exports from the stats manifest. +- Triggers independent compilation for shared entries with `treeshake: true`, and writes the produced assets back to the `stats/manifest` (fallback fields). diff --git a/website/docs/zh/plugins/webpack/tree-shake-shared-plugin.mdx b/website/docs/zh/plugins/webpack/tree-shake-shared-plugin.mdx new file mode 100644 index 000000000000..eda8c1f393bc --- /dev/null +++ b/website/docs/zh/plugins/webpack/tree-shake-shared-plugin.mdx @@ -0,0 +1,45 @@ +import { Stability, ApiMeta } from '@components/ApiMeta'; + +# TreeShakeSharedPlugin + + + +**概览** + +基于模块联邦配置对 shared 依赖进行按需构建与导出优化。 + +**选项** + +- `mfConfig`:`ModuleFederationPluginOptions`,传入模块联邦插件所需要的配置项。 +- `plugins`:额外插件列表,可在独立编译中复用。 +- `reshake`:是否在独立编译阶段执行二次摇树优化(二次摇树通常在部署平台确定了完整的依赖信息后重新触发的一次全新构建,提高共享依赖 treeshake 命中的准确率)。 + +**使用示例** + +```js +// rspack.config.js +const { TreeShakeSharedPlugin } = require('@rspack/core'); + +module.exports = { + plugins: [ + new TreeShakeSharedPlugin({ + reshake: true, + mfConfig: { + name: 'app', + shared: { + 'lodash-es': { treeshake: true }, + }, + library: { type: 'var', name: 'App' }, + manifest: true, + }, + plugins: [], + }), + ], +}; +``` + +**行为说明** + +- 读取 `shared` 配置后标准化为 `[shareName, SharedConfig][]`。 +- 当 `reshake` 为 `false` 时,注册 `SharedUsedExportsOptimizerPlugin`,基于 stats 清单注入已用导出集合。 +- 对 `treeshake` 的共享包触发独立编译,产出回写到 stats/manifest 中的 fallback 字段。 From e27a87e9c3345e49454ee133dbef2e0822e2bf7b Mon Sep 17 00:00:00 2001 From: "zhanghang.heal" Date: Tue, 9 Dec 2025 17:23:53 +0800 Subject: [PATCH 02/87] fix(module-federation): correct shared module name and optimize tree shaking fix incorrect module name in shared config and test cases change async process_module to sync using block_on for better performance update shared exports optimization to handle side effects properly --- .../plugin/flag_dependency_usage_plugin.rs | 12 ++++++++---- .../shared_used_exports_optimizer_plugin.rs | 19 ++++++++++--------- packages/rspack/etc/core.api.md | 6 +++--- .../treeshake-shared-server-strategy/index.js | 10 +++++----- .../rspack.config.js | 2 +- 5 files changed, 27 insertions(+), 22 deletions(-) diff --git a/crates/rspack_plugin_javascript/src/plugin/flag_dependency_usage_plugin.rs b/crates/rspack_plugin_javascript/src/plugin/flag_dependency_usage_plugin.rs index c8ac8bde09c5..cb2329b1ac5a 100644 --- a/crates/rspack_plugin_javascript/src/plugin/flag_dependency_usage_plugin.rs +++ b/crates/rspack_plugin_javascript/src/plugin/flag_dependency_usage_plugin.rs @@ -1,5 +1,6 @@ use std::collections::{VecDeque, hash_map::Entry}; +use futures::executor::block_on; use rayon::prelude::*; use rspack_collections::{IdentifierMap, UkeyMap}; use rspack_core::{ @@ -99,9 +100,12 @@ impl<'a> FlagDependencyUsagePluginProxy<'a> { // and also added referenced modules to queue for further processing let mut batch_res = vec![]; for (block_id, runtime, force_side_effects) in batch { - let (referenced_exports, module_tasks) = self - .process_module(block_id, runtime.as_ref(), force_side_effects, self.global) - .await; + let (referenced_exports, module_tasks) = block_on(self.process_module( + block_id, + runtime.as_ref(), + force_side_effects, + self.global, + )); batch_res.push(( runtime, force_side_effects, @@ -513,7 +517,7 @@ async fn optimize_dependencies( } let mut proxy = FlagDependencyUsagePluginProxy::new(self.global, compilation); - proxy.apply().await; + proxy.apply(); Ok(None) } diff --git a/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_plugin.rs b/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_plugin.rs index 684cea6323f9..047ca4337892 100644 --- a/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_plugin.rs +++ b/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_plugin.rs @@ -1,7 +1,4 @@ -use std::{ - collections::BTreeMap, - sync::{Arc, RwLock}, -}; +use std::sync::{Arc, RwLock}; use rspack_collections::Identifiable; use rspack_core::{ @@ -9,10 +6,10 @@ use rspack_core::{ CompilationAdditionalTreeRuntimeRequirements, CompilationDependencyReferencedExports, CompilationOptimizeDependencies, CompilationProcessAssets, DependenciesBlock, DependencyId, DependencyType, ExportsType, ExtendedReferencedExport, Module, ModuleGraph, ModuleIdentifier, - NormalModule, Plugin, RuntimeGlobals, RuntimeModuleExt, RuntimeSpec, + NormalModule, Plugin, RuntimeGlobals, RuntimeModuleExt, RuntimeSpec, SideEffectsOptimizeArtifact, rspack_sources::{RawStringSource, SourceExt, SourceValue}, }; -use rspack_error::Result; +use rspack_error::{Diagnostic, Result}; use rspack_hook::{plugin, plugin_hook}; use rspack_plugin_javascript::dependency::{ESMImportSpecifierDependency, ImportDependency}; use rspack_util::atom::Atom; @@ -127,7 +124,12 @@ fn collect_processed_modules( CompilationOptimizeDependencies for SharedUsedExportsOptimizerPlugin, stage = 1 )] -async fn optimize_dependencies(&self, compilation: &mut Compilation) -> Result> { +async fn optimize_dependencies( + &self, + compilation: &mut Compilation, + _side_effects_optimize_artifact: &mut SideEffectsOptimizeArtifact, + _diagnostics: &mut Vec, +) -> Result> { let module_ids: Vec<_> = { let module_graph = compilation.get_module_graph(); module_graph @@ -263,7 +265,6 @@ async fn optimize_dependencies(&self, compilation: &mut Compilation) -> Result Result { const { dynamicUISpecificExport } = await import('./App.js'); expect(await dynamicUISpecificExport()).toEqual( - 'dynamic Uilib has List exports not treeshake', + 'dynamic Uilib has List exports treeshake', ); const bundlePath = path.join( @@ -84,8 +84,8 @@ it('should treeshake ui-lib-dynamic-default-export', async () => { ); const bundleContent = fs.readFileSync(bundlePath, 'utf-8'); expect(bundleContent).toContain('List'); - expect(bundleContent).toContain('Button'); - expect(bundleContent).toContain('Badge'); + expect(bundleContent).not.toContain('Button'); + expect(bundleContent).not.toContain('Badge'); }); it('should not treeshake ui-lib-side-effect if not set sideEffect:false ', async () => { diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/rspack.config.js b/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/rspack.config.js index d4142514e6d6..78fae988a34e 100644 --- a/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/rspack.config.js +++ b/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/rspack.config.js @@ -20,7 +20,7 @@ module.exports = { target: 'async-node', plugins: [ new ModuleFederationPlugin({ - name: 'treeshake_share', + name: 'treeshake_share_server', manifest: true, filename: 'remoteEntry.js', library: { From f7e6adf480d4a5a29889b061017aac99724147da Mon Sep 17 00:00:00 2001 From: "zhanghang.heal" Date: Thu, 11 Dec 2025 20:34:56 +0800 Subject: [PATCH 03/87] feat(module-federation): add treeshakeSharedExcludedPlugins option --- packages/rspack/etc/core.api.md | 2 ++ .../src/container/ModuleFederationPlugin.ts | 1 + .../src/sharing/IndependentSharedPlugin.ts | 24 ++++++++++++++----- .../src/sharing/TreeShakeSharedPlugin.ts | 3 ++- 4 files changed, 23 insertions(+), 7 deletions(-) diff --git a/packages/rspack/etc/core.api.md b/packages/rspack/etc/core.api.md index 4c60a126233a..ff4970c6ea14 100644 --- a/packages/rspack/etc/core.api.md +++ b/packages/rspack/etc/core.api.md @@ -4859,6 +4859,8 @@ export interface ModuleFederationPluginOptions extends Omit][]; diff --git a/packages/rspack/src/sharing/IndependentSharedPlugin.ts b/packages/rspack/src/sharing/IndependentSharedPlugin.ts index eb8bc1c62415..280ccb829706 100644 --- a/packages/rspack/src/sharing/IndependentSharedPlugin.ts +++ b/packages/rspack/src/sharing/IndependentSharedPlugin.ts @@ -26,7 +26,7 @@ const VIRTUAL_ENTRY_NAME = "virtual-entry"; export type MakeRequired = Required> & Omit; -const filterPlugin = (plugin: Plugins[0]) => { +const filterPlugin = (plugin: Plugins[0], excludedPlugins: string[] = []) => { if (!plugin) { return true; } @@ -39,7 +39,8 @@ const filterPlugin = (plugin: Plugins[0]) => { "IndependentSharedPlugin", "ModuleFederationPlugin", "SharedUsedExportsOptimizerPlugin", - "HtmlWebpackPlugin" + "HtmlWebpackPlugin", + ...excludedPlugins ].includes(pluginName); }; @@ -52,6 +53,7 @@ export interface IndependentSharePluginOptions { treeshake?: boolean; manifest?: ModuleFederationManifestPluginOptions; injectUsedExports?: boolean; + treeshakeSharedExcludedPlugins?: string[]; } // { react: [ [ react/19.0.0/index.js , 19.0.0, react_global_name ] ] } @@ -121,6 +123,7 @@ export class IndependentSharedPlugin { manifest?: ModuleFederationManifestPluginOptions; buildAssets: ShareFallback = {}; injectUsedExports?: boolean; + treeshakeSharedExcludedPlugins?: string[]; name = "IndependentSharedPlugin"; constructor(options: IndependentSharePluginOptions) { @@ -132,7 +135,8 @@ export class IndependentSharedPlugin { name, manifest, injectUsedExports, - library + library, + treeshakeSharedExcludedPlugins } = options; this.shared = shared; this.mfName = name; @@ -142,6 +146,7 @@ export class IndependentSharedPlugin { this.manifest = manifest; this.injectUsedExports = injectUsedExports ?? true; this.library = library; + this.treeshakeSharedExcludedPlugins = treeshakeSharedExcludedPlugins || []; this.sharedOptions = parseOptions( shared, (item, key) => { @@ -301,8 +306,15 @@ export class IndependentSharedPlugin { shareRequestsMap: ShareRequestsMap; } ) { - const { mfName, plugins, outputDir, sharedOptions, treeshake, library } = - this; + const { + mfName, + plugins, + outputDir, + sharedOptions, + treeshake, + library, + treeshakeSharedExcludedPlugins + } = this; const outputDirWithShareName = resolveOutputDir( outputDir, @@ -329,7 +341,7 @@ export class IndependentSharedPlugin { if ( plugin !== undefined && typeof plugin !== "string" && - filterPlugin(plugin) + filterPlugin(plugin, treeshakeSharedExcludedPlugins) ) { finalPlugins.push(plugin); } diff --git a/packages/rspack/src/sharing/TreeShakeSharedPlugin.ts b/packages/rspack/src/sharing/TreeShakeSharedPlugin.ts index c180cd2ddf4c..84c8744450e8 100644 --- a/packages/rspack/src/sharing/TreeShakeSharedPlugin.ts +++ b/packages/rspack/src/sharing/TreeShakeSharedPlugin.ts @@ -57,7 +57,8 @@ export class TreeShakeSharedPlugin { plugins, treeshake: reshake, library, - manifest: mfConfig.manifest + manifest: mfConfig.manifest, + treeshakeSharedExcludedPlugins: mfConfig.treeshakeSharedExcludedPlugins }); this._independentSharePlugin.apply(compiler); } From 4c2435c72a04969755501b14ae67b82f71aec3b9 Mon Sep 17 00:00:00 2001 From: "zhanghang.heal" Date: Fri, 12 Dec 2025 15:04:55 +0800 Subject: [PATCH 04/87] chore: add watchRun --- .../src/container/ModuleFederationPlugin.ts | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/packages/rspack/src/container/ModuleFederationPlugin.ts b/packages/rspack/src/container/ModuleFederationPlugin.ts index 49ca7f409164..7e55c948aac5 100644 --- a/packages/rspack/src/container/ModuleFederationPlugin.ts +++ b/packages/rspack/src/container/ModuleFederationPlugin.ts @@ -52,6 +52,7 @@ export class ModuleFederationPlugin { this._treeShakeSharedPlugin.apply(compiler); } + // need to wait treeShakeSharedPlugin buildAssets let runtimePluginApplied = false; compiler.hooks.beforeRun.tapPromise( { @@ -72,6 +73,25 @@ export class ModuleFederationPlugin { }).apply(compiler); } ); + compiler.hooks.watchRun.tapPromise( + { + name: "ModuleFederationPlugin", + stage: 100 + }, + async () => { + if (runtimePluginApplied) return; + runtimePluginApplied = true; + const entryRuntime = getDefaultEntryRuntime( + paths, + this._options, + compiler, + this._treeShakeSharedPlugin?.buildAssets || {} + ); + new ModuleFederationRuntimePlugin({ + entryRuntime + }).apply(compiler); + } + ); new webpack.container.ModuleFederationPluginV1({ ...this._options, From 617f52259ccb5ec180bd8ad1cce9f02594f68a36 Mon Sep 17 00:00:00 2001 From: "zhanghang.heal" Date: Mon, 15 Dec 2025 11:02:55 +0800 Subject: [PATCH 05/87] fix(shared-modules): handle undefined moduleToHandlerMapping and prevent tree-shaking Add fallback for undefined moduleToHandlerMapping in shared container entry Include additional plugins in filter list and prevent tree-shaking of shared modules by adding console logs when collectShared is true --- .../sharing/shared_container_entry_module.rs | 2 +- .../src/sharing/IndependentSharedPlugin.ts | 30 ++++++++++++++++--- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/crates/rspack_plugin_mf/src/sharing/shared_container_entry_module.rs b/crates/rspack_plugin_mf/src/sharing/shared_container_entry_module.rs index 81b308e9e96b..1bf65d782b26 100644 --- a/crates/rspack_plugin_mf/src/sharing/shared_container_entry_module.rs +++ b/crates/rspack_plugin_mf/src/sharing/shared_container_entry_module.rs @@ -187,7 +187,7 @@ impl Module for SharedContainerEntryModule { r#"localBundlerRuntime.installInitialConsumes({{ installedModules: localInstalledModules, initialConsumes: __webpack_require__.consumesLoadingData.initialConsumes, - moduleToHandlerMapping: __webpack_require__.federation.consumesLoadingModuleToHandlerMapping, + moduleToHandlerMapping: __webpack_require__.federation.consumesLoadingModuleToHandlerMapping || {{}}, webpackRequire: __webpack_require__, asyncLoad: true }})"# diff --git a/packages/rspack/src/sharing/IndependentSharedPlugin.ts b/packages/rspack/src/sharing/IndependentSharedPlugin.ts index 280ccb829706..3e5faf05acfd 100644 --- a/packages/rspack/src/sharing/IndependentSharedPlugin.ts +++ b/packages/rspack/src/sharing/IndependentSharedPlugin.ts @@ -40,6 +40,8 @@ const filterPlugin = (plugin: Plugins[0], excludedPlugins: string[] = []) => { "ModuleFederationPlugin", "SharedUsedExportsOptimizerPlugin", "HtmlWebpackPlugin", + "HtmlRspackPlugin", + "RsbuildHtmlPlugin", ...excludedPlugins ].includes(pluginName); }; @@ -61,13 +63,19 @@ export type ShareFallback = Record; class VirtualEntryPlugin { sharedOptions: [string, SharedConfig][]; - constructor(sharedOptions: [string, SharedConfig][]) { + collectShared = false; + constructor(sharedOptions: [string, SharedConfig][], collectShared: boolean) { this.sharedOptions = sharedOptions; + this.collectShared = collectShared; } createEntry() { - const { sharedOptions } = this; + const { sharedOptions, collectShared } = this; const entryContent = sharedOptions.reduce((acc, cur, index) => { - return `${acc}import shared_${index} from '${cur[0]}';\n`; + const importLine = `import shared_${index} from '${cur[0]}';\n`; + // Always mark the import as used to prevent tree-shaking removal + // Optional console for debugging: reference the variable, not a string + const logLine = collectShared ? `console.log(shared_${index});\n` : ""; + return acc + importLine + logLine; }, ""); return entryContent; } @@ -383,7 +391,7 @@ export class IndependentSharedPlugin { ); } finalPlugins.push( - new VirtualEntryPlugin(sharedOptions) + new VirtualEntryPlugin(sharedOptions, !extraOptions) // new rspack.experiments.VirtualModulesPlugin({ // [VIRTUAL_ENTRY]: this.createEntry() // }) @@ -394,6 +402,20 @@ export class IndependentSharedPlugin { ); const compilerConfig: RspackOptions = { ...parentConfig, + module: { + ...parentConfig.module, + rules: [ + { + test: /virtual-entry\.js$/, + type: "javascript/auto", + resolve: { fullySpecified: false }, + use: { + loader: "builtin:swc-loader" + } + }, + ...(parentConfig.module?.rules || []) + ] + }, mode: parentConfig.mode || "development", entry: VirtualEntryPlugin.entry, From c976e7be2869f3e5278fda2136e848e367ad92ec Mon Sep 17 00:00:00 2001 From: "zhanghang.heal" Date: Mon, 15 Dec 2025 17:07:58 +0800 Subject: [PATCH 06/87] test(container-1-5): add ui-lib package for treeshake shared infer strategy --- .../src/sharing/collect_shared_entry_plugin.rs | 9 +++++++-- .../treeshake-shared-infer-strategy/App.js | 7 +++++++ .../treeshake-shared-infer-strategy/index.js | 13 +++++++++++++ .../node_modules/@scope-sc/ui-lib/index.js | 9 +++++++++ .../node_modules/@scope-sc/ui-lib/package.json | 6 ++++++ .../rspack.config.js | 6 ++++++ 6 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/@scope-sc/ui-lib/index.js create mode 100644 tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/@scope-sc/ui-lib/package.json diff --git a/crates/rspack_plugin_mf/src/sharing/collect_shared_entry_plugin.rs b/crates/rspack_plugin_mf/src/sharing/collect_shared_entry_plugin.rs index 5dc8c3ba9624..150cda395ce8 100644 --- a/crates/rspack_plugin_mf/src/sharing/collect_shared_entry_plugin.rs +++ b/crates/rspack_plugin_mf/src/sharing/collect_shared_entry_plugin.rs @@ -130,8 +130,13 @@ async fn process_assets(&self, compilation: &mut Compilation) -> Result<()> { } if let Some(pos) = ident.find(") ") { let rest = &ident[pos + 2..]; - let at = rest.find('@').unwrap_or(rest.len()); - key = rest[..at].to_string(); + // Limit to the segment before any suffixes like " (strict)", " (fallback: ...)" or " (eager)" + let suffix_start = rest.find(" (").unwrap_or(rest.len()); + let head = &rest[..suffix_start]; + // Use the LAST '@' within the head to split "{share_key}@{version}", + // so scoped names like "@scope/pkg@1.0.0" are handled correctly. + let at = head.rfind('@').unwrap_or(head.len()); + key = head[..at].to_string(); } (scope, key) }; diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/App.js b/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/App.js index 89e10a92feb9..5ba9987fe9ef 100644 --- a/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/App.js +++ b/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/App.js @@ -1,5 +1,6 @@ import UiLib from 'ui-lib'; import { Button } from 'ui-lib-es'; +import UiLibScopeSc from '@scope-sc/ui-lib'; export default () => { return `default Uilib has ${Object.keys(UiLib).join( @@ -7,6 +8,12 @@ export default () => { )} exports not treeshake, and ui-lib-es Button value is ${Button} should treeshake`; }; +export const scopeScUILib = () => { + return `scope-sc Uilib has ${Object.keys(UiLibScopeSc).join( + ', ', + )}`; +}; + export const dynamicUISpecificExport = async () => { const { List } = await import('ui-lib-dynamic-specific-export'); return `dynamic Uilib has ${List} exports treeshake`; diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/index.js b/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/index.js index 05c24370341d..42cff89ef766 100644 --- a/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/index.js +++ b/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/index.js @@ -122,3 +122,16 @@ it('should inject usedExports into manifest and stats if enable manifest', async ), ).toEqual(JSON.stringify(['Button', 'default'])); }); + +it('should treeshake scope-sc ui-lib correctly', async () => { + const { scopeScUILib } = await import('./App.js'); + expect(scopeScUILib()).toEqual('scope-sc Uilib has Button, List, Badge'); + + const bundlePath = path.join( + __dirname, + 'node_modules_scope-sc_ui-lib_index_js.js', + ); + const bundleContent = fs.readFileSync(bundlePath, 'utf-8'); + expect(bundleContent).toContain('Button'); + expect(bundleContent).toContain('default'); +}); diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/@scope-sc/ui-lib/index.js b/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/@scope-sc/ui-lib/index.js new file mode 100644 index 000000000000..dffb614be886 --- /dev/null +++ b/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/@scope-sc/ui-lib/index.js @@ -0,0 +1,9 @@ +export const List = 'List' +export const Button = 'Button'; +export const Badge = 'Badge' + +export default { + Button, + List, + Badge +} diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/@scope-sc/ui-lib/package.json b/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/@scope-sc/ui-lib/package.json new file mode 100644 index 000000000000..485bb4d62618 --- /dev/null +++ b/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/@scope-sc/ui-lib/package.json @@ -0,0 +1,6 @@ +{ + "name": "@scope-sc/ui-lib", + "main": "./index.js", + "version": "1.0.0", + "sideEffects": false +} diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/rspack.config.js b/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/rspack.config.js index 34500eda0ce6..2f288c5d98d2 100644 --- a/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/rspack.config.js +++ b/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/rspack.config.js @@ -32,6 +32,12 @@ module.exports = { }, runtimePlugins: [require.resolve('./runtime-plugin.js')], shared: { + '@scope-sc/ui-lib': { + requiredVersion: '*', + treeshake: { + strategy: 'infer', + }, + }, 'ui-lib': { requiredVersion: '*', treeshake: { From c38ded8b1163a39bf8fc8c5046bbbb214229ec7e Mon Sep 17 00:00:00 2001 From: "zhanghang.heal" Date: Mon, 22 Dec 2025 15:54:27 +0800 Subject: [PATCH 07/87] fix(shared_used_exports): handle scoped package names in shared exports refactor(node_binding): remove redundant exports in wasi files --- crates/node_binding/rspack.wasi-browser.js | 61 +------------------ crates/node_binding/rspack.wasi.cjs | 61 +------------------ .../shared_used_exports_optimizer_plugin.rs | 18 +++++- 3 files changed, 18 insertions(+), 122 deletions(-) diff --git a/crates/node_binding/rspack.wasi-browser.js b/crates/node_binding/rspack.wasi-browser.js index e3e5c0a99d48..ee65959b37bc 100644 --- a/crates/node_binding/rspack.wasi-browser.js +++ b/crates/node_binding/rspack.wasi-browser.js @@ -63,63 +63,4 @@ const { }, }) export default __napiModule.exports -export const Assets = __napiModule.exports.Assets -export const AsyncDependenciesBlock = __napiModule.exports.AsyncDependenciesBlock -export const Chunk = __napiModule.exports.Chunk -export const ChunkGraph = __napiModule.exports.ChunkGraph -export const ChunkGroup = __napiModule.exports.ChunkGroup -export const Chunks = __napiModule.exports.Chunks -export const CodeGenerationResult = __napiModule.exports.CodeGenerationResult -export const CodeGenerationResults = __napiModule.exports.CodeGenerationResults -export const ConcatenatedModule = __napiModule.exports.ConcatenatedModule -export const ContextModule = __napiModule.exports.ContextModule -export const Dependency = __napiModule.exports.Dependency -export const Diagnostics = __napiModule.exports.Diagnostics -export const EntryDataDto = __napiModule.exports.EntryDataDto -export const EntryDataDTO = __napiModule.exports.EntryDataDTO -export const EntryDependency = __napiModule.exports.EntryDependency -export const EntryOptionsDto = __napiModule.exports.EntryOptionsDto -export const EntryOptionsDTO = __napiModule.exports.EntryOptionsDTO -export const ExternalModule = __napiModule.exports.ExternalModule -export const JsCompilation = __napiModule.exports.JsCompilation -export const JsCompiler = __napiModule.exports.JsCompiler -export const JsContextModuleFactoryAfterResolveData = __napiModule.exports.JsContextModuleFactoryAfterResolveData -export const JsContextModuleFactoryBeforeResolveData = __napiModule.exports.JsContextModuleFactoryBeforeResolveData -export const JsDependencies = __napiModule.exports.JsDependencies -export const JsEntries = __napiModule.exports.JsEntries -export const JsExportsInfo = __napiModule.exports.JsExportsInfo -export const JsModuleGraph = __napiModule.exports.JsModuleGraph -export const JsResolver = __napiModule.exports.JsResolver -export const JsResolverFactory = __napiModule.exports.JsResolverFactory -export const JsStats = __napiModule.exports.JsStats -export const KnownBuildInfo = __napiModule.exports.KnownBuildInfo -export const Module = __napiModule.exports.Module -export const ModuleGraphConnection = __napiModule.exports.ModuleGraphConnection -export const NativeWatcher = __napiModule.exports.NativeWatcher -export const NativeWatchResult = __napiModule.exports.NativeWatchResult -export const NormalModule = __napiModule.exports.NormalModule -export const RawExternalItemFnCtx = __napiModule.exports.RawExternalItemFnCtx -export const ReadonlyResourceData = __napiModule.exports.ReadonlyResourceData -export const ResolverFactory = __napiModule.exports.ResolverFactory -export const Sources = __napiModule.exports.Sources -export const VirtualFileStore = __napiModule.exports.VirtualFileStore -export const JsVirtualFileStore = __napiModule.exports.JsVirtualFileStore -export const async = __napiModule.exports.async -export const BuiltinPluginName = __napiModule.exports.BuiltinPluginName -export const cleanupGlobalTrace = __napiModule.exports.cleanupGlobalTrace -export const EnforceExtension = __napiModule.exports.EnforceExtension -export const EXPECTED_RSPACK_CORE_VERSION = __napiModule.exports.EXPECTED_RSPACK_CORE_VERSION -export const formatDiagnostic = __napiModule.exports.formatDiagnostic -export const JsLoaderState = __napiModule.exports.JsLoaderState -export const JsRspackSeverity = __napiModule.exports.JsRspackSeverity -export const loadBrowserslist = __napiModule.exports.loadBrowserslist -export const minify = __napiModule.exports.minify -export const minifySync = __napiModule.exports.minifySync -export const RawJavascriptParserCommonjsExports = __napiModule.exports.RawJavascriptParserCommonjsExports -export const RawRuleSetConditionType = __napiModule.exports.RawRuleSetConditionType -export const registerGlobalTrace = __napiModule.exports.registerGlobalTrace -export const RegisterJsTapKind = __napiModule.exports.RegisterJsTapKind -export const sync = __napiModule.exports.sync -export const syncTraceEvent = __napiModule.exports.syncTraceEvent -export const transform = __napiModule.exports.transform -export const transformSync = __napiModule.exports.transformSync + diff --git a/crates/node_binding/rspack.wasi.cjs b/crates/node_binding/rspack.wasi.cjs index a251ce4d0d7d..1ad96db4aac4 100644 --- a/crates/node_binding/rspack.wasi.cjs +++ b/crates/node_binding/rspack.wasi.cjs @@ -108,63 +108,4 @@ const { instance: __napiInstance, module: __wasiModule, napiModule: __napiModule }, }) module.exports = __napiModule.exports -module.exports.Assets = __napiModule.exports.Assets -module.exports.AsyncDependenciesBlock = __napiModule.exports.AsyncDependenciesBlock -module.exports.Chunk = __napiModule.exports.Chunk -module.exports.ChunkGraph = __napiModule.exports.ChunkGraph -module.exports.ChunkGroup = __napiModule.exports.ChunkGroup -module.exports.Chunks = __napiModule.exports.Chunks -module.exports.CodeGenerationResult = __napiModule.exports.CodeGenerationResult -module.exports.CodeGenerationResults = __napiModule.exports.CodeGenerationResults -module.exports.ConcatenatedModule = __napiModule.exports.ConcatenatedModule -module.exports.ContextModule = __napiModule.exports.ContextModule -module.exports.Dependency = __napiModule.exports.Dependency -module.exports.Diagnostics = __napiModule.exports.Diagnostics -module.exports.EntryDataDto = __napiModule.exports.EntryDataDto -module.exports.EntryDataDTO = __napiModule.exports.EntryDataDTO -module.exports.EntryDependency = __napiModule.exports.EntryDependency -module.exports.EntryOptionsDto = __napiModule.exports.EntryOptionsDto -module.exports.EntryOptionsDTO = __napiModule.exports.EntryOptionsDTO -module.exports.ExternalModule = __napiModule.exports.ExternalModule -module.exports.JsCompilation = __napiModule.exports.JsCompilation -module.exports.JsCompiler = __napiModule.exports.JsCompiler -module.exports.JsContextModuleFactoryAfterResolveData = __napiModule.exports.JsContextModuleFactoryAfterResolveData -module.exports.JsContextModuleFactoryBeforeResolveData = __napiModule.exports.JsContextModuleFactoryBeforeResolveData -module.exports.JsDependencies = __napiModule.exports.JsDependencies -module.exports.JsEntries = __napiModule.exports.JsEntries -module.exports.JsExportsInfo = __napiModule.exports.JsExportsInfo -module.exports.JsModuleGraph = __napiModule.exports.JsModuleGraph -module.exports.JsResolver = __napiModule.exports.JsResolver -module.exports.JsResolverFactory = __napiModule.exports.JsResolverFactory -module.exports.JsStats = __napiModule.exports.JsStats -module.exports.KnownBuildInfo = __napiModule.exports.KnownBuildInfo -module.exports.Module = __napiModule.exports.Module -module.exports.ModuleGraphConnection = __napiModule.exports.ModuleGraphConnection -module.exports.NativeWatcher = __napiModule.exports.NativeWatcher -module.exports.NativeWatchResult = __napiModule.exports.NativeWatchResult -module.exports.NormalModule = __napiModule.exports.NormalModule -module.exports.RawExternalItemFnCtx = __napiModule.exports.RawExternalItemFnCtx -module.exports.ReadonlyResourceData = __napiModule.exports.ReadonlyResourceData -module.exports.ResolverFactory = __napiModule.exports.ResolverFactory -module.exports.Sources = __napiModule.exports.Sources -module.exports.VirtualFileStore = __napiModule.exports.VirtualFileStore -module.exports.JsVirtualFileStore = __napiModule.exports.JsVirtualFileStore -module.exports.async = __napiModule.exports.async -module.exports.BuiltinPluginName = __napiModule.exports.BuiltinPluginName -module.exports.cleanupGlobalTrace = __napiModule.exports.cleanupGlobalTrace -module.exports.EnforceExtension = __napiModule.exports.EnforceExtension -module.exports.EXPECTED_RSPACK_CORE_VERSION = __napiModule.exports.EXPECTED_RSPACK_CORE_VERSION -module.exports.formatDiagnostic = __napiModule.exports.formatDiagnostic -module.exports.JsLoaderState = __napiModule.exports.JsLoaderState -module.exports.JsRspackSeverity = __napiModule.exports.JsRspackSeverity -module.exports.loadBrowserslist = __napiModule.exports.loadBrowserslist -module.exports.minify = __napiModule.exports.minify -module.exports.minifySync = __napiModule.exports.minifySync -module.exports.RawJavascriptParserCommonjsExports = __napiModule.exports.RawJavascriptParserCommonjsExports -module.exports.RawRuleSetConditionType = __napiModule.exports.RawRuleSetConditionType -module.exports.registerGlobalTrace = __napiModule.exports.registerGlobalTrace -module.exports.RegisterJsTapKind = __napiModule.exports.RegisterJsTapKind -module.exports.sync = __napiModule.exports.sync -module.exports.syncTraceEvent = __napiModule.exports.syncTraceEvent -module.exports.transform = __napiModule.exports.transform -module.exports.transformSync = __napiModule.exports.transformSync + diff --git a/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_plugin.rs b/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_plugin.rs index 047ca4337892..aeb9c45c7c59 100644 --- a/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_plugin.rs +++ b/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_plugin.rs @@ -169,7 +169,14 @@ async fn optimize_dependencies( return None; } let share_key_part = parts[1]; - let share_key_end = share_key_part.find('@').unwrap_or(share_key_part.len()); + let share_key_end = if share_key_part.starts_with('@') { + share_key_part[1..] + .find('@') + .map(|i| i + 1) + .unwrap_or(share_key_part.len()) + } else { + share_key_part.find('@').unwrap_or(share_key_part.len()) + }; let sk: String = share_key_part[..share_key_end].to_string(); collect_processed_modules( &module_graph, @@ -202,7 +209,14 @@ async fn optimize_dependencies( return None; } let name_part = parts[3]; - let name_end = name_part.find('@').unwrap_or(name_part.len()); + let name_end = if name_part.starts_with('@') { + name_part[1..] + .find('@') + .map(|i| i + 1) + .unwrap_or(name_part.len()) + } else { + name_part.find('@').unwrap_or(name_part.len()) + }; let sk = name_part[..name_end].to_string(); collect_processed_modules( &module_graph, From 22d591c52265b2a4b2c1b97979a41cc186152f25 Mon Sep 17 00:00:00 2001 From: "zhanghang.heal" Date: Mon, 22 Dec 2025 16:31:23 +0800 Subject: [PATCH 08/87] chore: update critical file --- crates/node_binding/rspack.wasi-browser.js | 61 +++++++++++++++++++++- crates/node_binding/rspack.wasi.cjs | 61 +++++++++++++++++++++- 2 files changed, 120 insertions(+), 2 deletions(-) diff --git a/crates/node_binding/rspack.wasi-browser.js b/crates/node_binding/rspack.wasi-browser.js index ee65959b37bc..e3e5c0a99d48 100644 --- a/crates/node_binding/rspack.wasi-browser.js +++ b/crates/node_binding/rspack.wasi-browser.js @@ -63,4 +63,63 @@ const { }, }) export default __napiModule.exports - +export const Assets = __napiModule.exports.Assets +export const AsyncDependenciesBlock = __napiModule.exports.AsyncDependenciesBlock +export const Chunk = __napiModule.exports.Chunk +export const ChunkGraph = __napiModule.exports.ChunkGraph +export const ChunkGroup = __napiModule.exports.ChunkGroup +export const Chunks = __napiModule.exports.Chunks +export const CodeGenerationResult = __napiModule.exports.CodeGenerationResult +export const CodeGenerationResults = __napiModule.exports.CodeGenerationResults +export const ConcatenatedModule = __napiModule.exports.ConcatenatedModule +export const ContextModule = __napiModule.exports.ContextModule +export const Dependency = __napiModule.exports.Dependency +export const Diagnostics = __napiModule.exports.Diagnostics +export const EntryDataDto = __napiModule.exports.EntryDataDto +export const EntryDataDTO = __napiModule.exports.EntryDataDTO +export const EntryDependency = __napiModule.exports.EntryDependency +export const EntryOptionsDto = __napiModule.exports.EntryOptionsDto +export const EntryOptionsDTO = __napiModule.exports.EntryOptionsDTO +export const ExternalModule = __napiModule.exports.ExternalModule +export const JsCompilation = __napiModule.exports.JsCompilation +export const JsCompiler = __napiModule.exports.JsCompiler +export const JsContextModuleFactoryAfterResolveData = __napiModule.exports.JsContextModuleFactoryAfterResolveData +export const JsContextModuleFactoryBeforeResolveData = __napiModule.exports.JsContextModuleFactoryBeforeResolveData +export const JsDependencies = __napiModule.exports.JsDependencies +export const JsEntries = __napiModule.exports.JsEntries +export const JsExportsInfo = __napiModule.exports.JsExportsInfo +export const JsModuleGraph = __napiModule.exports.JsModuleGraph +export const JsResolver = __napiModule.exports.JsResolver +export const JsResolverFactory = __napiModule.exports.JsResolverFactory +export const JsStats = __napiModule.exports.JsStats +export const KnownBuildInfo = __napiModule.exports.KnownBuildInfo +export const Module = __napiModule.exports.Module +export const ModuleGraphConnection = __napiModule.exports.ModuleGraphConnection +export const NativeWatcher = __napiModule.exports.NativeWatcher +export const NativeWatchResult = __napiModule.exports.NativeWatchResult +export const NormalModule = __napiModule.exports.NormalModule +export const RawExternalItemFnCtx = __napiModule.exports.RawExternalItemFnCtx +export const ReadonlyResourceData = __napiModule.exports.ReadonlyResourceData +export const ResolverFactory = __napiModule.exports.ResolverFactory +export const Sources = __napiModule.exports.Sources +export const VirtualFileStore = __napiModule.exports.VirtualFileStore +export const JsVirtualFileStore = __napiModule.exports.JsVirtualFileStore +export const async = __napiModule.exports.async +export const BuiltinPluginName = __napiModule.exports.BuiltinPluginName +export const cleanupGlobalTrace = __napiModule.exports.cleanupGlobalTrace +export const EnforceExtension = __napiModule.exports.EnforceExtension +export const EXPECTED_RSPACK_CORE_VERSION = __napiModule.exports.EXPECTED_RSPACK_CORE_VERSION +export const formatDiagnostic = __napiModule.exports.formatDiagnostic +export const JsLoaderState = __napiModule.exports.JsLoaderState +export const JsRspackSeverity = __napiModule.exports.JsRspackSeverity +export const loadBrowserslist = __napiModule.exports.loadBrowserslist +export const minify = __napiModule.exports.minify +export const minifySync = __napiModule.exports.minifySync +export const RawJavascriptParserCommonjsExports = __napiModule.exports.RawJavascriptParserCommonjsExports +export const RawRuleSetConditionType = __napiModule.exports.RawRuleSetConditionType +export const registerGlobalTrace = __napiModule.exports.registerGlobalTrace +export const RegisterJsTapKind = __napiModule.exports.RegisterJsTapKind +export const sync = __napiModule.exports.sync +export const syncTraceEvent = __napiModule.exports.syncTraceEvent +export const transform = __napiModule.exports.transform +export const transformSync = __napiModule.exports.transformSync diff --git a/crates/node_binding/rspack.wasi.cjs b/crates/node_binding/rspack.wasi.cjs index 1ad96db4aac4..a251ce4d0d7d 100644 --- a/crates/node_binding/rspack.wasi.cjs +++ b/crates/node_binding/rspack.wasi.cjs @@ -108,4 +108,63 @@ const { instance: __napiInstance, module: __wasiModule, napiModule: __napiModule }, }) module.exports = __napiModule.exports - +module.exports.Assets = __napiModule.exports.Assets +module.exports.AsyncDependenciesBlock = __napiModule.exports.AsyncDependenciesBlock +module.exports.Chunk = __napiModule.exports.Chunk +module.exports.ChunkGraph = __napiModule.exports.ChunkGraph +module.exports.ChunkGroup = __napiModule.exports.ChunkGroup +module.exports.Chunks = __napiModule.exports.Chunks +module.exports.CodeGenerationResult = __napiModule.exports.CodeGenerationResult +module.exports.CodeGenerationResults = __napiModule.exports.CodeGenerationResults +module.exports.ConcatenatedModule = __napiModule.exports.ConcatenatedModule +module.exports.ContextModule = __napiModule.exports.ContextModule +module.exports.Dependency = __napiModule.exports.Dependency +module.exports.Diagnostics = __napiModule.exports.Diagnostics +module.exports.EntryDataDto = __napiModule.exports.EntryDataDto +module.exports.EntryDataDTO = __napiModule.exports.EntryDataDTO +module.exports.EntryDependency = __napiModule.exports.EntryDependency +module.exports.EntryOptionsDto = __napiModule.exports.EntryOptionsDto +module.exports.EntryOptionsDTO = __napiModule.exports.EntryOptionsDTO +module.exports.ExternalModule = __napiModule.exports.ExternalModule +module.exports.JsCompilation = __napiModule.exports.JsCompilation +module.exports.JsCompiler = __napiModule.exports.JsCompiler +module.exports.JsContextModuleFactoryAfterResolveData = __napiModule.exports.JsContextModuleFactoryAfterResolveData +module.exports.JsContextModuleFactoryBeforeResolveData = __napiModule.exports.JsContextModuleFactoryBeforeResolveData +module.exports.JsDependencies = __napiModule.exports.JsDependencies +module.exports.JsEntries = __napiModule.exports.JsEntries +module.exports.JsExportsInfo = __napiModule.exports.JsExportsInfo +module.exports.JsModuleGraph = __napiModule.exports.JsModuleGraph +module.exports.JsResolver = __napiModule.exports.JsResolver +module.exports.JsResolverFactory = __napiModule.exports.JsResolverFactory +module.exports.JsStats = __napiModule.exports.JsStats +module.exports.KnownBuildInfo = __napiModule.exports.KnownBuildInfo +module.exports.Module = __napiModule.exports.Module +module.exports.ModuleGraphConnection = __napiModule.exports.ModuleGraphConnection +module.exports.NativeWatcher = __napiModule.exports.NativeWatcher +module.exports.NativeWatchResult = __napiModule.exports.NativeWatchResult +module.exports.NormalModule = __napiModule.exports.NormalModule +module.exports.RawExternalItemFnCtx = __napiModule.exports.RawExternalItemFnCtx +module.exports.ReadonlyResourceData = __napiModule.exports.ReadonlyResourceData +module.exports.ResolverFactory = __napiModule.exports.ResolverFactory +module.exports.Sources = __napiModule.exports.Sources +module.exports.VirtualFileStore = __napiModule.exports.VirtualFileStore +module.exports.JsVirtualFileStore = __napiModule.exports.JsVirtualFileStore +module.exports.async = __napiModule.exports.async +module.exports.BuiltinPluginName = __napiModule.exports.BuiltinPluginName +module.exports.cleanupGlobalTrace = __napiModule.exports.cleanupGlobalTrace +module.exports.EnforceExtension = __napiModule.exports.EnforceExtension +module.exports.EXPECTED_RSPACK_CORE_VERSION = __napiModule.exports.EXPECTED_RSPACK_CORE_VERSION +module.exports.formatDiagnostic = __napiModule.exports.formatDiagnostic +module.exports.JsLoaderState = __napiModule.exports.JsLoaderState +module.exports.JsRspackSeverity = __napiModule.exports.JsRspackSeverity +module.exports.loadBrowserslist = __napiModule.exports.loadBrowserslist +module.exports.minify = __napiModule.exports.minify +module.exports.minifySync = __napiModule.exports.minifySync +module.exports.RawJavascriptParserCommonjsExports = __napiModule.exports.RawJavascriptParserCommonjsExports +module.exports.RawRuleSetConditionType = __napiModule.exports.RawRuleSetConditionType +module.exports.registerGlobalTrace = __napiModule.exports.registerGlobalTrace +module.exports.RegisterJsTapKind = __napiModule.exports.RegisterJsTapKind +module.exports.sync = __napiModule.exports.sync +module.exports.syncTraceEvent = __napiModule.exports.syncTraceEvent +module.exports.transform = __napiModule.exports.transform +module.exports.transformSync = __napiModule.exports.transformSync From c8f933e3836e77fd9d4a6e7fb96740f377ba75e2 Mon Sep 17 00:00:00 2001 From: "zhanghang.heal" Date: Wed, 24 Dec 2025 20:08:08 +0800 Subject: [PATCH 09/87] feat(module-federation): add target and plugins to build info for treeshaking Add target and plugins fields to build info when treeshaking is enabled in module federation. Also rename 'reshake' to 'reShake' for consistency across the codebase. These changes support better treeshaking analysis and configuration. --- crates/node_binding/napi-binding.d.ts | 2 + .../src/raw_options/raw_builtins/raw_mf.rs | 5 ++ crates/rspack_plugin_mf/src/manifest/data.rs | 4 ++ crates/rspack_plugin_mf/src/manifest/mod.rs | 7 ++- packages/rspack/etc/core.api.md | 4 +- .../ModuleFederationManifestPlugin.ts | 47 ++++++++++++++----- .../src/container/ModuleFederationPlugin.ts | 2 +- .../src/sharing/TreeShakeSharedPlugin.ts | 14 +++--- 8 files changed, 63 insertions(+), 22 deletions(-) diff --git a/crates/node_binding/napi-binding.d.ts b/crates/node_binding/napi-binding.d.ts index c1aab0f3d9d3..12a9cc7a2ced 100644 --- a/crates/node_binding/napi-binding.d.ts +++ b/crates/node_binding/napi-binding.d.ts @@ -2884,6 +2884,8 @@ export interface RawSplitChunksOptions { export interface RawStatsBuildInfo { buildVersion: string buildName?: string + target?: Array + plugins?: Array } export interface RawStatsOptions { diff --git a/crates/rspack_binding_api/src/raw_options/raw_builtins/raw_mf.rs b/crates/rspack_binding_api/src/raw_options/raw_builtins/raw_mf.rs index 708ea7f8b95e..84e4d6fc774d 100644 --- a/crates/rspack_binding_api/src/raw_options/raw_builtins/raw_mf.rs +++ b/crates/rspack_binding_api/src/raw_options/raw_builtins/raw_mf.rs @@ -351,6 +351,9 @@ pub struct RawManifestSharedOption { pub struct RawStatsBuildInfo { pub build_version: String, pub build_name: Option, + // only appear when enable treeshake + pub target: Option>, + pub plugins: Option>, } #[derive(Debug)] @@ -414,6 +417,8 @@ impl From for ModuleFederationManifest build_info: value.build_info.map(|info| StatsBuildInfo { build_version: info.build_version, build_name: info.build_name, + target: info.target, + plugins: info.plugins, }), } } diff --git a/crates/rspack_plugin_mf/src/manifest/data.rs b/crates/rspack_plugin_mf/src/manifest/data.rs index d2ca71591bae..54d3dd932a2e 100644 --- a/crates/rspack_plugin_mf/src/manifest/data.rs +++ b/crates/rspack_plugin_mf/src/manifest/data.rs @@ -22,6 +22,10 @@ pub struct StatsBuildInfo { pub build_version: String, #[serde(rename = "buildName", skip_serializing_if = "Option::is_none")] pub build_name: Option, + #[serde(rename = "target", skip_serializing_if = "Option::is_none")] + pub target: Option>, + #[serde(rename = "plugins", skip_serializing_if = "Option::is_none")] + pub plugins: Option>, } #[derive(Debug, Serialize, Deserialize, Clone)] diff --git a/crates/rspack_plugin_mf/src/manifest/mod.rs b/crates/rspack_plugin_mf/src/manifest/mod.rs index 3214cc0606fd..edc5841de85c 100644 --- a/crates/rspack_plugin_mf/src/manifest/mod.rs +++ b/crates/rspack_plugin_mf/src/manifest/mod.rs @@ -528,10 +528,15 @@ async fn process_assets(&self, compilation: &mut Compilation) -> Result<()> { ), ); // Build manifest from stats + let mut manifest_meta = stats_root.metaData.clone(); + if let Some(build_info) = &mut manifest_meta.build_info { + build_info.target = None; + build_info.plugins = None; + } let manifest = ManifestRoot { id: stats_root.id.clone(), name: stats_root.name.clone(), - metaData: stats_root.metaData.clone(), + metaData: manifest_meta, exposes: exposes .into_iter() .map(|e| ManifestExpose { diff --git a/packages/rspack/etc/core.api.md b/packages/rspack/etc/core.api.md index abbad21e3914..df9d60c3bf74 100644 --- a/packages/rspack/etc/core.api.md +++ b/packages/rspack/etc/core.api.md @@ -8405,7 +8405,7 @@ class TreeShakeSharedPlugin { // (undocumented) plugins?: Plugins; // (undocumented) - reshake?: boolean; + reShake?: boolean; } // @public (undocumented) @@ -8415,7 +8415,7 @@ export interface TreeshakeSharedPluginOptions { // (undocumented) plugins?: Plugins; // (undocumented) - reshake?: boolean; + reShake?: boolean; } // @public (undocumented) diff --git a/packages/rspack/src/container/ModuleFederationManifestPlugin.ts b/packages/rspack/src/container/ModuleFederationManifestPlugin.ts index 601bf7f5eca2..1be0821107c3 100644 --- a/packages/rspack/src/container/ModuleFederationManifestPlugin.ts +++ b/packages/rspack/src/container/ModuleFederationManifestPlugin.ts @@ -10,7 +10,10 @@ import { RspackBuiltinPlugin } from "../builtin-plugin/base"; import type { Compiler } from "../Compiler"; -import type { SharedConfig } from "../sharing/SharePlugin"; +import { + normalizeSharedOptions, + type SharedConfig +} from "../sharing/SharePlugin"; import { isRequiredVersion } from "../sharing/utils"; import { getRemoteInfos, @@ -65,20 +68,40 @@ function readPKGJson(root?: string): Record { return {}; } -function getBuildInfo(isDev: boolean, root?: string): StatsBuildInfo { - const rootPath = root || process.cwd(); +function getBuildInfo( + isDev: boolean, + compiler: Compiler, + mfConfig: ModuleFederationPluginOptions +): StatsBuildInfo { + const rootPath = compiler.options.context || process.cwd(); const pkg = readPKGJson(rootPath); const buildVersion = isDev ? LOCAL_BUILD_VERSION : pkg?.version; - return { + const statsBuildInfo: StatsBuildInfo = { buildVersion: process.env.MF_BUILD_VERSION || buildVersion || "UNKNOWN", buildName: process.env.MF_BUILD_NAME || pkg?.name || "UNKNOWN" }; + + const normalizedShared = normalizeSharedOptions(mfConfig.shared || {}); + const enableTreeshake = Object.values(normalizedShared).some( + config => config[1].treeshake + ); + if (enableTreeshake) { + statsBuildInfo.target = Array.isArray(compiler.options.target) + ? compiler.options.target + : []; + statsBuildInfo.plugins = mfConfig.treeshakeSharedExcludedPlugins || []; + } + + return statsBuildInfo; } interface StatsBuildInfo { buildVersion: string; buildName?: string; + // only appear when enable treeshake + target?: string[]; + plugins?: string[]; } export type RemoteAliasMap = Record; @@ -288,13 +311,14 @@ function normalizeManifestOptions(mfConfig: ModuleFederationPluginOptions) { */ export class ModuleFederationManifestPlugin extends RspackBuiltinPlugin { name = BuiltinPluginName.ModuleFederationManifestPlugin; - private opts: InternalManifestPluginOptions; + private rawOpts: ModuleFederationPluginOptions; constructor(opts: ModuleFederationPluginOptions) { super(); - this.opts = normalizeManifestOptions(opts); + this.rawOpts = opts; } raw(compiler: Compiler): BuiltinPlugin { + const opts = normalizeManifestOptions(this.rawOpts); const { fileName, filePath, @@ -302,12 +326,12 @@ export class ModuleFederationManifestPlugin extends RspackBuiltinPlugin { remoteAliasMap, exposes, shared - } = this.opts; - const { statsFileName, manifestFileName } = getFileName(this.opts); + } = opts; + const { statsFileName, manifestFileName } = getFileName(opts); const rawOptions: RawModuleFederationManifestPluginOptions = { - name: this.opts.name, - globalName: this.opts.globalName, + name: opts.name, + globalName: opts.globalName, fileName, filePath, manifestFileName, @@ -318,7 +342,8 @@ export class ModuleFederationManifestPlugin extends RspackBuiltinPlugin { shared, buildInfo: getBuildInfo( compiler.options.mode === "development", - compiler.context + compiler, + this.rawOpts ) }; return createBuiltinPlugin(this.name, rawOptions); diff --git a/packages/rspack/src/container/ModuleFederationPlugin.ts b/packages/rspack/src/container/ModuleFederationPlugin.ts index 0ce2b5159be3..4fd6fc4cbff0 100644 --- a/packages/rspack/src/container/ModuleFederationPlugin.ts +++ b/packages/rspack/src/container/ModuleFederationPlugin.ts @@ -49,7 +49,7 @@ export class ModuleFederationPlugin { if (treeshakeEntries.length > 0) { this._treeShakeSharedPlugin = new TreeShakeSharedPlugin({ mfConfig: this._options, - reshake: false + reShake: false }); this._treeShakeSharedPlugin.apply(compiler); } diff --git a/packages/rspack/src/sharing/TreeShakeSharedPlugin.ts b/packages/rspack/src/sharing/TreeShakeSharedPlugin.ts index 84c8744450e8..858be86562de 100644 --- a/packages/rspack/src/sharing/TreeShakeSharedPlugin.ts +++ b/packages/rspack/src/sharing/TreeShakeSharedPlugin.ts @@ -8,27 +8,27 @@ import { normalizeSharedOptions } from "./SharePlugin"; export interface TreeshakeSharedPluginOptions { mfConfig: ModuleFederationPluginOptions; plugins?: Plugins; - reshake?: boolean; + reShake?: boolean; } export class TreeShakeSharedPlugin { mfConfig: ModuleFederationPluginOptions; outputDir: string; plugins?: Plugins; - reshake?: boolean; + reShake?: boolean; private _independentSharePlugin?: IndependentSharedPlugin; name = "TreeShakeSharedPlugin"; constructor(options: TreeshakeSharedPluginOptions) { - const { mfConfig, plugins, reshake } = options; + const { mfConfig, plugins, reShake } = options; this.mfConfig = mfConfig; this.outputDir = mfConfig.independentShareDir || "independent-packages"; this.plugins = plugins; - this.reshake = Boolean(reshake); + this.reShake = Boolean(reShake); } apply(compiler: Compiler) { - const { mfConfig, outputDir, plugins, reshake } = this; + const { mfConfig, outputDir, plugins, reShake } = this; const { name, shared, library } = mfConfig; if (!shared) { return; @@ -43,7 +43,7 @@ export class TreeShakeSharedPlugin { ([_, config]) => config.treeshake && config.import !== false ) ) { - if (!reshake) { + if (!reShake) { new SharedUsedExportsOptimizerPlugin( sharedOptions, mfConfig.injectUsedExports, @@ -55,7 +55,7 @@ export class TreeShakeSharedPlugin { shared: shared, outputDir, plugins, - treeshake: reshake, + treeshake: reShake, library, manifest: mfConfig.manifest, treeshakeSharedExcludedPlugins: mfConfig.treeshakeSharedExcludedPlugins From ae6c179bcd56eda3cd5cab359499cd4287909fdf Mon Sep 17 00:00:00 2001 From: "zhanghang.heal" Date: Tue, 30 Dec 2025 14:23:21 +0800 Subject: [PATCH 10/87] docs: update field --- .../configCases/sharing/reshake-share/rspack.config.js | 4 ++-- .../docs/en/plugins/webpack/tree-shake-shared-plugin.mdx | 6 +++--- .../docs/zh/plugins/webpack/tree-shake-shared-plugin.mdx | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/rspack-test/configCases/sharing/reshake-share/rspack.config.js b/tests/rspack-test/configCases/sharing/reshake-share/rspack.config.js index 47d774a07270..685193bb83ce 100644 --- a/tests/rspack-test/configCases/sharing/reshake-share/rspack.config.js +++ b/tests/rspack-test/configCases/sharing/reshake-share/rspack.config.js @@ -13,7 +13,7 @@ module.exports = { }, plugins: [ new TreeShakeSharedPlugin({ - reshake: true, + reShake: true, plugins: [ { apply(compiler) { @@ -24,7 +24,7 @@ module.exports = { }, async () => { compilation.emitAsset('apply-plugin.json', new compilation.compiler.rspack.sources.RawSource(JSON.stringify({ - reshake: true + reShake: true }))) }) }) diff --git a/website/docs/en/plugins/webpack/tree-shake-shared-plugin.mdx b/website/docs/en/plugins/webpack/tree-shake-shared-plugin.mdx index 1b16d5496b58..a2be9b12ba07 100644 --- a/website/docs/en/plugins/webpack/tree-shake-shared-plugin.mdx +++ b/website/docs/en/plugins/webpack/tree-shake-shared-plugin.mdx @@ -12,7 +12,7 @@ import { Stability, ApiMeta } from '@components/ApiMeta'; - `mfConfig`: `ModuleFederationPluginOptions`, configuration passed to the Module Federation plugin. - `plugins`: extra plugins reused during independent builds. -- `reshake`: whether to perform a second tree-shake during independent builds (typically used when the deployment platform has determined complete dependency info and triggers a fresh build to improve tree-shake accuracy for shared dependencies). +- `reShake`: whether to perform a second tree-shake during independent builds (typically used when the deployment platform has determined complete dependency info and triggers a fresh build to improve tree-shake accuracy for shared dependencies). **Usage** @@ -23,7 +23,7 @@ const { TreeShakeSharedPlugin } = require('@rspack/core'); module.exports = { plugins: [ new TreeShakeSharedPlugin({ - reshake: true, + reShake: true, mfConfig: { name: 'app', shared: { @@ -41,5 +41,5 @@ module.exports = { **Behavior** - Normalizes `shared` into `[shareName, SharedConfig][]`. -- Registers `SharedUsedExportsOptimizerPlugin` when `reshake` is `false` to inject used-exports from the stats manifest. +- Registers `SharedUsedExportsOptimizerPlugin` when `reShake` is `false` to inject used-exports from the stats manifest. - Triggers independent compilation for shared entries with `treeshake: true`, and writes the produced assets back to the `stats/manifest` (fallback fields). diff --git a/website/docs/zh/plugins/webpack/tree-shake-shared-plugin.mdx b/website/docs/zh/plugins/webpack/tree-shake-shared-plugin.mdx index eda8c1f393bc..ac06117fbfeb 100644 --- a/website/docs/zh/plugins/webpack/tree-shake-shared-plugin.mdx +++ b/website/docs/zh/plugins/webpack/tree-shake-shared-plugin.mdx @@ -12,7 +12,7 @@ import { Stability, ApiMeta } from '@components/ApiMeta'; - `mfConfig`:`ModuleFederationPluginOptions`,传入模块联邦插件所需要的配置项。 - `plugins`:额外插件列表,可在独立编译中复用。 -- `reshake`:是否在独立编译阶段执行二次摇树优化(二次摇树通常在部署平台确定了完整的依赖信息后重新触发的一次全新构建,提高共享依赖 treeshake 命中的准确率)。 +- `reShake`:是否在独立编译阶段执行二次摇树优化(二次摇树通常在部署平台确定了完整的依赖信息后重新触发的一次全新构建,提高共享依赖 treeshake 命中的准确率)。 **使用示例** @@ -23,7 +23,7 @@ const { TreeShakeSharedPlugin } = require('@rspack/core'); module.exports = { plugins: [ new TreeShakeSharedPlugin({ - reshake: true, + reShake: true, mfConfig: { name: 'app', shared: { @@ -41,5 +41,5 @@ module.exports = { **行为说明** - 读取 `shared` 配置后标准化为 `[shareName, SharedConfig][]`。 -- 当 `reshake` 为 `false` 时,注册 `SharedUsedExportsOptimizerPlugin`,基于 stats 清单注入已用导出集合。 +- 当 `reShake` 为 `false` 时,注册 `SharedUsedExportsOptimizerPlugin`,基于 stats 清单注入已用导出集合。 - 对 `treeshake` 的共享包触发独立编译,产出回写到 stats/manifest 中的 fallback 字段。 From 226445c42e448cbd3b3c1c7d5d1a85e34782290d Mon Sep 17 00:00:00 2001 From: "zhanghang.heal" Date: Tue, 30 Dec 2025 17:51:17 +0800 Subject: [PATCH 11/87] feat: add treeshakeSharedPlugins --- crates/node_binding/rspack.wasi-browser.js | 61 +------------------ crates/node_binding/rspack.wasi.cjs | 61 +------------------ packages/rspack/etc/core.api.md | 4 +- .../ModuleFederationManifestPlugin.ts | 5 +- .../src/container/ModuleFederationPlugin.ts | 3 +- .../src/sharing/IndependentSharedPlugin.ts | 12 ++-- .../src/sharing/TreeShakeSharedPlugin.ts | 2 +- 7 files changed, 18 insertions(+), 130 deletions(-) diff --git a/crates/node_binding/rspack.wasi-browser.js b/crates/node_binding/rspack.wasi-browser.js index e3e5c0a99d48..ee65959b37bc 100644 --- a/crates/node_binding/rspack.wasi-browser.js +++ b/crates/node_binding/rspack.wasi-browser.js @@ -63,63 +63,4 @@ const { }, }) export default __napiModule.exports -export const Assets = __napiModule.exports.Assets -export const AsyncDependenciesBlock = __napiModule.exports.AsyncDependenciesBlock -export const Chunk = __napiModule.exports.Chunk -export const ChunkGraph = __napiModule.exports.ChunkGraph -export const ChunkGroup = __napiModule.exports.ChunkGroup -export const Chunks = __napiModule.exports.Chunks -export const CodeGenerationResult = __napiModule.exports.CodeGenerationResult -export const CodeGenerationResults = __napiModule.exports.CodeGenerationResults -export const ConcatenatedModule = __napiModule.exports.ConcatenatedModule -export const ContextModule = __napiModule.exports.ContextModule -export const Dependency = __napiModule.exports.Dependency -export const Diagnostics = __napiModule.exports.Diagnostics -export const EntryDataDto = __napiModule.exports.EntryDataDto -export const EntryDataDTO = __napiModule.exports.EntryDataDTO -export const EntryDependency = __napiModule.exports.EntryDependency -export const EntryOptionsDto = __napiModule.exports.EntryOptionsDto -export const EntryOptionsDTO = __napiModule.exports.EntryOptionsDTO -export const ExternalModule = __napiModule.exports.ExternalModule -export const JsCompilation = __napiModule.exports.JsCompilation -export const JsCompiler = __napiModule.exports.JsCompiler -export const JsContextModuleFactoryAfterResolveData = __napiModule.exports.JsContextModuleFactoryAfterResolveData -export const JsContextModuleFactoryBeforeResolveData = __napiModule.exports.JsContextModuleFactoryBeforeResolveData -export const JsDependencies = __napiModule.exports.JsDependencies -export const JsEntries = __napiModule.exports.JsEntries -export const JsExportsInfo = __napiModule.exports.JsExportsInfo -export const JsModuleGraph = __napiModule.exports.JsModuleGraph -export const JsResolver = __napiModule.exports.JsResolver -export const JsResolverFactory = __napiModule.exports.JsResolverFactory -export const JsStats = __napiModule.exports.JsStats -export const KnownBuildInfo = __napiModule.exports.KnownBuildInfo -export const Module = __napiModule.exports.Module -export const ModuleGraphConnection = __napiModule.exports.ModuleGraphConnection -export const NativeWatcher = __napiModule.exports.NativeWatcher -export const NativeWatchResult = __napiModule.exports.NativeWatchResult -export const NormalModule = __napiModule.exports.NormalModule -export const RawExternalItemFnCtx = __napiModule.exports.RawExternalItemFnCtx -export const ReadonlyResourceData = __napiModule.exports.ReadonlyResourceData -export const ResolverFactory = __napiModule.exports.ResolverFactory -export const Sources = __napiModule.exports.Sources -export const VirtualFileStore = __napiModule.exports.VirtualFileStore -export const JsVirtualFileStore = __napiModule.exports.JsVirtualFileStore -export const async = __napiModule.exports.async -export const BuiltinPluginName = __napiModule.exports.BuiltinPluginName -export const cleanupGlobalTrace = __napiModule.exports.cleanupGlobalTrace -export const EnforceExtension = __napiModule.exports.EnforceExtension -export const EXPECTED_RSPACK_CORE_VERSION = __napiModule.exports.EXPECTED_RSPACK_CORE_VERSION -export const formatDiagnostic = __napiModule.exports.formatDiagnostic -export const JsLoaderState = __napiModule.exports.JsLoaderState -export const JsRspackSeverity = __napiModule.exports.JsRspackSeverity -export const loadBrowserslist = __napiModule.exports.loadBrowserslist -export const minify = __napiModule.exports.minify -export const minifySync = __napiModule.exports.minifySync -export const RawJavascriptParserCommonjsExports = __napiModule.exports.RawJavascriptParserCommonjsExports -export const RawRuleSetConditionType = __napiModule.exports.RawRuleSetConditionType -export const registerGlobalTrace = __napiModule.exports.registerGlobalTrace -export const RegisterJsTapKind = __napiModule.exports.RegisterJsTapKind -export const sync = __napiModule.exports.sync -export const syncTraceEvent = __napiModule.exports.syncTraceEvent -export const transform = __napiModule.exports.transform -export const transformSync = __napiModule.exports.transformSync + diff --git a/crates/node_binding/rspack.wasi.cjs b/crates/node_binding/rspack.wasi.cjs index a251ce4d0d7d..1ad96db4aac4 100644 --- a/crates/node_binding/rspack.wasi.cjs +++ b/crates/node_binding/rspack.wasi.cjs @@ -108,63 +108,4 @@ const { instance: __napiInstance, module: __wasiModule, napiModule: __napiModule }, }) module.exports = __napiModule.exports -module.exports.Assets = __napiModule.exports.Assets -module.exports.AsyncDependenciesBlock = __napiModule.exports.AsyncDependenciesBlock -module.exports.Chunk = __napiModule.exports.Chunk -module.exports.ChunkGraph = __napiModule.exports.ChunkGraph -module.exports.ChunkGroup = __napiModule.exports.ChunkGroup -module.exports.Chunks = __napiModule.exports.Chunks -module.exports.CodeGenerationResult = __napiModule.exports.CodeGenerationResult -module.exports.CodeGenerationResults = __napiModule.exports.CodeGenerationResults -module.exports.ConcatenatedModule = __napiModule.exports.ConcatenatedModule -module.exports.ContextModule = __napiModule.exports.ContextModule -module.exports.Dependency = __napiModule.exports.Dependency -module.exports.Diagnostics = __napiModule.exports.Diagnostics -module.exports.EntryDataDto = __napiModule.exports.EntryDataDto -module.exports.EntryDataDTO = __napiModule.exports.EntryDataDTO -module.exports.EntryDependency = __napiModule.exports.EntryDependency -module.exports.EntryOptionsDto = __napiModule.exports.EntryOptionsDto -module.exports.EntryOptionsDTO = __napiModule.exports.EntryOptionsDTO -module.exports.ExternalModule = __napiModule.exports.ExternalModule -module.exports.JsCompilation = __napiModule.exports.JsCompilation -module.exports.JsCompiler = __napiModule.exports.JsCompiler -module.exports.JsContextModuleFactoryAfterResolveData = __napiModule.exports.JsContextModuleFactoryAfterResolveData -module.exports.JsContextModuleFactoryBeforeResolveData = __napiModule.exports.JsContextModuleFactoryBeforeResolveData -module.exports.JsDependencies = __napiModule.exports.JsDependencies -module.exports.JsEntries = __napiModule.exports.JsEntries -module.exports.JsExportsInfo = __napiModule.exports.JsExportsInfo -module.exports.JsModuleGraph = __napiModule.exports.JsModuleGraph -module.exports.JsResolver = __napiModule.exports.JsResolver -module.exports.JsResolverFactory = __napiModule.exports.JsResolverFactory -module.exports.JsStats = __napiModule.exports.JsStats -module.exports.KnownBuildInfo = __napiModule.exports.KnownBuildInfo -module.exports.Module = __napiModule.exports.Module -module.exports.ModuleGraphConnection = __napiModule.exports.ModuleGraphConnection -module.exports.NativeWatcher = __napiModule.exports.NativeWatcher -module.exports.NativeWatchResult = __napiModule.exports.NativeWatchResult -module.exports.NormalModule = __napiModule.exports.NormalModule -module.exports.RawExternalItemFnCtx = __napiModule.exports.RawExternalItemFnCtx -module.exports.ReadonlyResourceData = __napiModule.exports.ReadonlyResourceData -module.exports.ResolverFactory = __napiModule.exports.ResolverFactory -module.exports.Sources = __napiModule.exports.Sources -module.exports.VirtualFileStore = __napiModule.exports.VirtualFileStore -module.exports.JsVirtualFileStore = __napiModule.exports.JsVirtualFileStore -module.exports.async = __napiModule.exports.async -module.exports.BuiltinPluginName = __napiModule.exports.BuiltinPluginName -module.exports.cleanupGlobalTrace = __napiModule.exports.cleanupGlobalTrace -module.exports.EnforceExtension = __napiModule.exports.EnforceExtension -module.exports.EXPECTED_RSPACK_CORE_VERSION = __napiModule.exports.EXPECTED_RSPACK_CORE_VERSION -module.exports.formatDiagnostic = __napiModule.exports.formatDiagnostic -module.exports.JsLoaderState = __napiModule.exports.JsLoaderState -module.exports.JsRspackSeverity = __napiModule.exports.JsRspackSeverity -module.exports.loadBrowserslist = __napiModule.exports.loadBrowserslist -module.exports.minify = __napiModule.exports.minify -module.exports.minifySync = __napiModule.exports.minifySync -module.exports.RawJavascriptParserCommonjsExports = __napiModule.exports.RawJavascriptParserCommonjsExports -module.exports.RawRuleSetConditionType = __napiModule.exports.RawRuleSetConditionType -module.exports.registerGlobalTrace = __napiModule.exports.registerGlobalTrace -module.exports.RegisterJsTapKind = __napiModule.exports.RegisterJsTapKind -module.exports.sync = __napiModule.exports.sync -module.exports.syncTraceEvent = __napiModule.exports.syncTraceEvent -module.exports.transform = __napiModule.exports.transform -module.exports.transformSync = __napiModule.exports.transformSync + diff --git a/packages/rspack/etc/core.api.md b/packages/rspack/etc/core.api.md index df9d60c3bf74..fc80e49b03b7 100644 --- a/packages/rspack/etc/core.api.md +++ b/packages/rspack/etc/core.api.md @@ -4879,7 +4879,9 @@ export interface ModuleFederationPluginOptions extends Omit][]; diff --git a/packages/rspack/src/sharing/IndependentSharedPlugin.ts b/packages/rspack/src/sharing/IndependentSharedPlugin.ts index 3e5faf05acfd..829d6cea31ea 100644 --- a/packages/rspack/src/sharing/IndependentSharedPlugin.ts +++ b/packages/rspack/src/sharing/IndependentSharedPlugin.ts @@ -55,7 +55,7 @@ export interface IndependentSharePluginOptions { treeshake?: boolean; manifest?: ModuleFederationManifestPluginOptions; injectUsedExports?: boolean; - treeshakeSharedExcludedPlugins?: string[]; + treeshakeSharedExcludePlugins?: string[]; } // { react: [ [ react/19.0.0/index.js , 19.0.0, react_global_name ] ] } @@ -131,7 +131,7 @@ export class IndependentSharedPlugin { manifest?: ModuleFederationManifestPluginOptions; buildAssets: ShareFallback = {}; injectUsedExports?: boolean; - treeshakeSharedExcludedPlugins?: string[]; + treeshakeSharedExcludePlugins?: string[]; name = "IndependentSharedPlugin"; constructor(options: IndependentSharePluginOptions) { @@ -144,7 +144,7 @@ export class IndependentSharedPlugin { manifest, injectUsedExports, library, - treeshakeSharedExcludedPlugins + treeshakeSharedExcludePlugins } = options; this.shared = shared; this.mfName = name; @@ -154,7 +154,7 @@ export class IndependentSharedPlugin { this.manifest = manifest; this.injectUsedExports = injectUsedExports ?? true; this.library = library; - this.treeshakeSharedExcludedPlugins = treeshakeSharedExcludedPlugins || []; + this.treeshakeSharedExcludePlugins = treeshakeSharedExcludePlugins || []; this.sharedOptions = parseOptions( shared, (item, key) => { @@ -321,7 +321,7 @@ export class IndependentSharedPlugin { sharedOptions, treeshake, library, - treeshakeSharedExcludedPlugins + treeshakeSharedExcludePlugins } = this; const outputDirWithShareName = resolveOutputDir( @@ -349,7 +349,7 @@ export class IndependentSharedPlugin { if ( plugin !== undefined && typeof plugin !== "string" && - filterPlugin(plugin, treeshakeSharedExcludedPlugins) + filterPlugin(plugin, treeshakeSharedExcludePlugins) ) { finalPlugins.push(plugin); } diff --git a/packages/rspack/src/sharing/TreeShakeSharedPlugin.ts b/packages/rspack/src/sharing/TreeShakeSharedPlugin.ts index 858be86562de..bd323f574e10 100644 --- a/packages/rspack/src/sharing/TreeShakeSharedPlugin.ts +++ b/packages/rspack/src/sharing/TreeShakeSharedPlugin.ts @@ -58,7 +58,7 @@ export class TreeShakeSharedPlugin { treeshake: reShake, library, manifest: mfConfig.manifest, - treeshakeSharedExcludedPlugins: mfConfig.treeshakeSharedExcludedPlugins + treeshakeSharedExcludePlugins: mfConfig.treeshakeSharedExcludePlugins }); this._independentSharePlugin.apply(compiler); } From 32c765e4f8437299359114144b05ee436214372b Mon Sep 17 00:00:00 2001 From: "zhanghang.heal" Date: Tue, 30 Dec 2025 22:26:01 +0800 Subject: [PATCH 12/87] fix: lint --- .../plugin/flag_dependency_usage_plugin.rs | 16 +- .../sharing/collect_shared_entry_plugin.rs | 50 +++--- .../shared_container_entry_dependency.rs | 2 +- .../sharing/shared_container_entry_module.rs | 24 ++- .../shared_used_exports_optimizer_plugin.rs | 144 ++++++++---------- packages/rspack/package.json | 2 +- 6 files changed, 107 insertions(+), 131 deletions(-) diff --git a/crates/rspack_plugin_javascript/src/plugin/flag_dependency_usage_plugin.rs b/crates/rspack_plugin_javascript/src/plugin/flag_dependency_usage_plugin.rs index 6e875cae5163..851a1e17e114 100644 --- a/crates/rspack_plugin_javascript/src/plugin/flag_dependency_usage_plugin.rs +++ b/crates/rspack_plugin_javascript/src/plugin/flag_dependency_usage_plugin.rs @@ -1,6 +1,5 @@ use std::collections::{VecDeque, hash_map::Entry}; -use futures::executor::block_on; use rayon::prelude::*; use rspack_collections::{IdentifierMap, UkeyMap}; use rspack_core::{ @@ -53,7 +52,7 @@ impl<'a> FlagDependencyUsagePluginProxy<'a> { } } - fn apply(&mut self) { + async fn apply(&mut self) { let mut module_graph = self.build_module_graph_artifact.get_module_graph_mut(); module_graph.active_all_exports_info(); module_graph.reset_all_exports_info_used(); @@ -105,12 +104,9 @@ impl<'a> FlagDependencyUsagePluginProxy<'a> { // and also added referenced modules to queue for further processing let mut batch_res = vec![]; for (block_id, runtime, force_side_effects) in batch { - let (referenced_exports, module_tasks) = block_on(self.process_module( - block_id, - runtime.as_ref(), - force_side_effects, - self.global, - )); + let (referenced_exports, module_tasks) = self + .process_module(block_id, runtime.as_ref(), force_side_effects, self.global) + .await; batch_res.push(( runtime, force_side_effects, @@ -282,7 +278,7 @@ impl<'a> FlagDependencyUsagePluginProxy<'a> { .compilation_hooks .dependency_referenced_exports .call( - &*self.compilation, + self.compilation, &dep_id, &referenced_exports_result, runtime, @@ -530,7 +526,7 @@ async fn optimize_dependencies( let mut proxy = FlagDependencyUsagePluginProxy::new(self.global, compilation, build_module_graph_artifact); - proxy.apply(); + proxy.apply().await; Ok(None) } diff --git a/crates/rspack_plugin_mf/src/sharing/collect_shared_entry_plugin.rs b/crates/rspack_plugin_mf/src/sharing/collect_shared_entry_plugin.rs index 150cda395ce8..25d0ad11ee6b 100644 --- a/crates/rspack_plugin_mf/src/sharing/collect_shared_entry_plugin.rs +++ b/crates/rspack_plugin_mf/src/sharing/collect_shared_entry_plugin.rs @@ -48,12 +48,11 @@ impl CollectSharedEntryPlugin { async fn infer_version(&self, request: &str) -> Option { // 1) Try pnpm store path pattern: .pnpm/@_ let pnpm_re = Regex::new(r"/\\.pnpm/[^/]*@([^/_]+)").ok(); - if let Some(re) = pnpm_re { - if let Some(caps) = re.captures(request) { - if let Some(m) = caps.get(1) { - return Some(m.as_str().to_string()); - } - } + if let Some(re) = pnpm_re + && let Some(caps) = re.captures(request) + && let Some(m) = caps.get(1) + { + return Some(m.as_str().to_string()); } // 2) Fallback: read version from the deepest node_modules//package.json @@ -83,14 +82,12 @@ impl CollectSharedEntryPlugin { package_json_path.push(p); } package_json_path.push("package.json"); - if package_json_path.exists() { - if let Ok(content) = std::fs::read_to_string(&package_json_path) { - if let Ok(json) = serde_json::from_str::(&content) { - if let Some(version) = json.get("version").and_then(|v| v.as_str()) { - return Some(version.to_string()); - } - } - } + if package_json_path.exists() + && let Ok(content) = std::fs::read_to_string(&package_json_path) + && let Ok(json) = serde_json::from_str::(&content) + && let Some(version) = json.get("version").and_then(|v| v.as_str()) + { + return Some(version.to_string()); } } } @@ -163,17 +160,17 @@ async fn process_assets(&self, compilation: &mut Compilation) -> Result<()> { // Add real module resource paths to the map and infer version let mut reqs = ordered_requests.remove(&key).unwrap_or_default(); for target_id in target_modules { - if let Some(target) = module_graph.module_by_identifier(&target_id) { - if let Some(name) = target.name_for_condition() { - let resource: String = name.into(); - let version = self - .infer_version(&resource) - .await - .unwrap_or_else(|| "".to_string()); - let pair = [resource, version]; - if !reqs.iter().any(|p| p[0] == pair[0] && p[1] == pair[1]) { - reqs.push(pair); - } + if let Some(target) = module_graph.module_by_identifier(&target_id) + && let Some(name) = target.name_for_condition() + { + let resource: String = name.into(); + let version = self + .infer_version(&resource) + .await + .unwrap_or_else(|| "".to_string()); + let pair = [resource, version]; + if !reqs.iter().any(|p| p[0] == pair[0] && p[1] == pair[1]) { + reqs.push(pair); } } } @@ -208,8 +205,7 @@ async fn process_assets(&self, compilation: &mut Compilation) -> Result<()> { let filename = self .options .filename - .as_ref() - .map(|f| f.clone()) + .clone() .unwrap_or_else(|| DEFAULT_FILENAME.to_string()); compilation.emit_asset( diff --git a/crates/rspack_plugin_mf/src/sharing/shared_container_entry_dependency.rs b/crates/rspack_plugin_mf/src/sharing/shared_container_entry_dependency.rs index e4774db0e147..73190d3d86e3 100644 --- a/crates/rspack_plugin_mf/src/sharing/shared_container_entry_dependency.rs +++ b/crates/rspack_plugin_mf/src/sharing/shared_container_entry_dependency.rs @@ -62,7 +62,7 @@ impl Dependency for SharedContainerEntryDependency { #[cacheable_dyn] impl ModuleDependency for SharedContainerEntryDependency { fn request(&self) -> &str { - &self.resource_identifier + &self.request } fn factorize_info(&self) -> &FactorizeInfo { diff --git a/crates/rspack_plugin_mf/src/sharing/shared_container_entry_module.rs b/crates/rspack_plugin_mf/src/sharing/shared_container_entry_module.rs index 1bf65d782b26..1e5595c27afa 100644 --- a/crates/rspack_plugin_mf/src/sharing/shared_container_entry_module.rs +++ b/crates/rspack_plugin_mf/src/sharing/shared_container_entry_module.rs @@ -123,13 +123,13 @@ impl Module for SharedContainerEntryModule { _build_context: BuildContext, _: Option<&Compilation>, ) -> Result { - let mut dependencies: Vec = Vec::new(); - - dependencies.push(Box::new(StaticExportsDependency::new( - StaticExportsSpec::Array(vec!["get".into(), "init".into()]), - false, - ))); - dependencies.push(Box::new(SharedContainerDependency::new(self.name.clone()))); + let dependencies: Vec = vec![ + Box::new(StaticExportsDependency::new( + StaticExportsSpec::Array(vec!["get".into(), "init".into()]), + false, + )), + Box::new(SharedContainerDependency::new(self.name.clone())), + ]; Ok(BuildResult { dependencies, @@ -183,18 +183,16 @@ impl Module for SharedContainerEntryModule { ); // Generate installInitialConsumes function using returning_function - let install_initial_consumes_call = format!( - r#"localBundlerRuntime.installInitialConsumes({{ + let install_initial_consumes_call = r#"localBundlerRuntime.installInitialConsumes({ installedModules: localInstalledModules, initialConsumes: __webpack_require__.consumesLoadingData.initialConsumes, - moduleToHandlerMapping: __webpack_require__.federation.consumesLoadingModuleToHandlerMapping || {{}}, + moduleToHandlerMapping: __webpack_require__.federation.consumesLoadingModuleToHandlerMapping || {}, webpackRequire: __webpack_require__, asyncLoad: true - }})"# - ); + })"#; let install_initial_consumes_fn = compilation .runtime_template - .returning_function(&install_initial_consumes_call, ""); + .returning_function(install_initial_consumes_call, ""); // Create initShareContainer function using basic_function, supporting multi-statement body let init_body = format!( diff --git a/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_plugin.rs b/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_plugin.rs index 35c2d9102f7d..a83528dfe66c 100644 --- a/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_plugin.rs +++ b/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_plugin.rs @@ -55,7 +55,7 @@ pub struct SharedUsedExportsOptimizerPlugin { impl SharedUsedExportsOptimizerPlugin { pub fn new(options: SharedUsedExportsOptimizerPluginOptions) -> Self { let mut shared_map = FxHashMap::default(); - let inject_used_exports = options.inject_used_exports.clone(); + let inject_used_exports = options.inject_used_exports; for config in options.shared.into_iter().filter(|c| c.treeshake) { let atoms = config .used_exports @@ -127,23 +127,19 @@ fn collect_processed_modules( )] async fn optimize_dependencies( &self, - compilation: &Compilation, + _compilation: &Compilation, _side_effects_optimize_artifact: &mut SideEffectsOptimizeArtifact, build_module_graph_artifact: &mut BuildModuleGraphArtifact, _diagnostics: &mut Vec, ) -> Result> { let module_ids: Vec<_> = { let module_graph = build_module_graph_artifact.get_module_graph(); - module_graph - .modules() - .into_iter() - .map(|(id, _)| id) - .collect() + module_graph.modules().keys().copied().collect() }; self.apply_custom_exports(); for module_id in module_ids { let module_graph = build_module_graph_artifact.get_module_graph(); - let (share_key, modules_to_process) = match { + let share_info = { let module = module_graph.module_by_identifier(&module_id); module.and_then(|module| { let module_type = module.module_type(); @@ -170,8 +166,8 @@ async fn optimize_dependencies( return None; } let share_key_part = parts[1]; - let share_key_end = if share_key_part.starts_with('@') { - share_key_part[1..] + let share_key_end = if let Some(stripped) = share_key_part.strip_prefix('@') { + stripped .find('@') .map(|i| i + 1) .unwrap_or(share_key_part.len()) @@ -180,7 +176,7 @@ async fn optimize_dependencies( }; let sk: String = share_key_part[..share_key_end].to_string(); collect_processed_modules( - &module_graph, + module_graph, consume_shared_module.get_blocks(), consume_shared_module.get_dependencies(), &mut modules_to_process, @@ -191,7 +187,7 @@ async fn optimize_dependencies( let provide_shared_module = module.as_any().downcast_ref::()?; let sk = provide_shared_module.share_key().to_string(); collect_processed_modules( - &module_graph, + module_graph, provide_shared_module.get_blocks(), provide_shared_module.get_dependencies(), &mut modules_to_process, @@ -210,17 +206,14 @@ async fn optimize_dependencies( return None; } let name_part = parts[3]; - let name_end = if name_part.starts_with('@') { - name_part[1..] - .find('@') - .map(|i| i + 1) - .unwrap_or(name_part.len()) + let name_end = if let Some(stripped) = name_part.strip_prefix('@') { + stripped.find('@').map(|i| i + 1).unwrap_or(name_part.len()) } else { name_part.find('@').unwrap_or(name_part.len()) }; let sk = name_part[..name_end].to_string(); collect_processed_modules( - &module_graph, + module_graph, share_container_entry_module.get_blocks(), share_container_entry_module.get_dependencies(), &mut modules_to_process, @@ -231,7 +224,9 @@ async fn optimize_dependencies( }; Some((share_key, modules_to_process)) }) - } { + }; + + let (share_key, modules_to_process) = match share_info { Some(result) => result, None => continue, }; @@ -279,20 +274,20 @@ async fn optimize_dependencies( if !is_side_effect_free { // Clear referenced exports for this share_key when module is not side-effect free - if let Ok(mut shared_referenced_exports) = self.shared_referenced_exports.write() { - if let Some(set) = shared_referenced_exports.get_mut(&share_key) { - set.clear(); - } + if let Ok(mut shared_referenced_exports) = self.shared_referenced_exports.write() + && let Some(set) = shared_referenced_exports.get_mut(&share_key) + { + set.clear(); } continue; } - let mut module_graph_mut = build_module_graph_artifact.get_module_graph_mut(); + let module_graph_mut = build_module_graph_artifact.get_module_graph_mut(); module_graph_mut.active_all_exports_info(); // mark used for collected modules for module_id in &modules_to_process { let exports_info = module_graph_mut.get_exports_info(module_id); - let exports_info_data = exports_info.as_data_mut(&mut module_graph_mut); + let exports_info_data = exports_info.as_data_mut(module_graph_mut); for export_name in runtime_reference_exports.iter() { let export_atom = Atom::from(export_name.as_str()); @@ -305,7 +300,7 @@ async fn optimize_dependencies( // find if can update real share module let exports_info = module_graph_mut.get_exports_info(&real_shared_identifier); - let exports_info_data = exports_info.as_data_mut(&mut module_graph_mut); + let exports_info_data = exports_info.as_data_mut(module_graph_mut); let can_update_module_used_stage = { let exports_view = exports_info_data.exports(); if exports_view.is_empty() { @@ -350,32 +345,29 @@ async fn process_assets(&self, compilation: &mut Compilation) -> Result<()> { self.manifest_file_name.clone(), ]; for file_name in file_names { - if let Some(file_name) = &file_name { - if let Some(file) = compilation.assets().get(file_name) { - if let Some(source) = file.get_source() { - if let SourceValue::String(content) = source.source() { - if let Ok(mut stats_root) = serde_json::from_str::(&content) { - let shared_referenced_exports = self - .shared_referenced_exports - .read() - .expect("lock poisoned"); - - for shared in &mut stats_root.shared { - if let Some(exports_set) = shared_referenced_exports.get(&shared.name) { - shared.usedExports = exports_set.iter().cloned().collect::>(); - } - } - - let updated_content = serde_json::to_string_pretty(&stats_root) - .map_err(|e| rspack_error::error!("Failed to serialize stats root: {}", e))?; + if let Some(file_name) = &file_name + && let Some(file) = compilation.assets().get(file_name) + && let Some(source) = file.get_source() + && let SourceValue::String(content) = source.source() + && let Ok(mut stats_root) = serde_json::from_str::(&content) + { + let shared_referenced_exports = self + .shared_referenced_exports + .read() + .expect("lock poisoned"); - compilation.update_asset(file_name, |_, info| { - Ok((RawStringSource::from(updated_content).boxed(), info)) - })?; - } - } + for shared in &mut stats_root.shared { + if let Some(exports_set) = shared_referenced_exports.get(&shared.name) { + shared.usedExports = exports_set.iter().cloned().collect::>(); } } + + let updated_content = serde_json::to_string_pretty(&stats_root) + .map_err(|e| rspack_error::error!("Failed to serialize stats root: {}", e))?; + + compilation.update_asset(file_name, |_, info| { + Ok((RawStringSource::from(updated_content).boxed(), info)) + })?; } } @@ -428,7 +420,7 @@ async fn dependency_referenced_exports( return Ok(()); }; - let Some(dependency) = module_graph.dependency_by_id(&dependency_id) else { + let Some(dependency) = module_graph.dependency_by_id(dependency_id) else { return Ok(()); }; @@ -462,27 +454,25 @@ async fn dependency_referenced_exports( shared_referenced_exports.remove(share_key); return Ok(()); } - if final_exports.is_empty() || is_exports_object { - if dependency.dependency_type() == &DependencyType::EsmImportSpecifier { - if let Some(esm_dep) = dependency - .as_any() - .downcast_ref::() - { - let ids = esm_dep.get_ids(&module_graph); - if ids.is_empty() { - return Ok(()); - } - if let Some(first) = ids.first() - && *first == "default" - { - final_exports = esm_dep.get_referenced_exports_in_destructuring(Some(ids)); - } else { - final_exports = esm_dep.get_esm_import_specifier_referenced_exports( - &module_graph, - Some(ExportsType::DefaultWithNamed), - ); - } - } + if (final_exports.is_empty() || is_exports_object) + && dependency.dependency_type() == &DependencyType::EsmImportSpecifier + && let Some(esm_dep) = dependency + .as_any() + .downcast_ref::() + { + let ids = esm_dep.get_ids(module_graph); + if ids.is_empty() { + return Ok(()); + } + if let Some(first) = ids.first() + && *first == "default" + { + final_exports = esm_dep.get_referenced_exports_in_destructuring(Some(ids)); + } else { + final_exports = esm_dep.get_esm_import_specifier_referenced_exports( + module_graph, + Some(ExportsType::DefaultWithNamed), + ); } } @@ -494,7 +484,7 @@ async fn dependency_referenced_exports( .expect("lock poisoned"); let export_set = shared_referenced_exports .entry(share_key.to_string()) - .or_insert_with(|| FxHashSet::default()); + .or_default(); for referenced_export in &final_exports { match referenced_export { @@ -507,13 +497,9 @@ async fn dependency_referenced_exports( if referenced.name.is_empty() { continue; } - let flattened = referenced - .name - .iter() - .map(|atom| atom.to_string()) - .collect::>() - .join("."); - export_set.insert(flattened); + for atom in &referenced.name { + export_set.insert(atom.to_string()); + } } } } diff --git a/packages/rspack/package.json b/packages/rspack/package.json index 54bad7733173..f9144085179e 100644 --- a/packages/rspack/package.json +++ b/packages/rspack/package.json @@ -65,7 +65,7 @@ "webpack-sources": "3.3.3" }, "dependencies": { - "@module-federation/runtime-tools": "0.0.0-feat-shared-treeshake-poc-20251208061713", + "@module-federation/runtime-tools": "0.0.0-feat-shared-treeshake-poc-20251230120553", "@rspack/binding": "workspace:*", "@rspack/lite-tapable": "1.1.0" }, From df148620be8e84779efe1e4435a8691672d7dcb5 Mon Sep 17 00:00:00 2001 From: "zhanghang.heal" Date: Sun, 4 Jan 2026 10:58:24 +0800 Subject: [PATCH 13/87] fix: lockfile --- pnpm-lock.yaml | 109 +++++++++++++------------------------------------ 1 file changed, 29 insertions(+), 80 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 38ea3472d2c8..1d6aa5b8ca1e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -345,8 +345,8 @@ importers: packages/rspack: dependencies: '@module-federation/runtime-tools': - specifier: 0.0.0-feat-shared-treeshake-poc-20251208061713 - version: 0.0.0-feat-shared-treeshake-poc-20251208061713 + specifier: 0.0.0-feat-shared-treeshake-poc-20251230120553 + version: 0.0.0-feat-shared-treeshake-poc-20251230120553 '@rspack/binding': specifier: workspace:* version: link:../../crates/node_binding @@ -2436,63 +2436,42 @@ packages: '@microsoft/tsdoc@0.16.0': resolution: {integrity: sha512-xgAyonlVVS+q7Vc7qLW0UrJU7rSFcETRWsqdXZtjzRU8dF+6CkozTK4V4y1LwOX7j8r/vHphjDeMeGI4tNGeGA==} - '@module-federation/error-codes@0.0.0-feat-shared-treeshake-poc-20251208061713': - resolution: {integrity: sha512-XHG824maYpsTW5AxnAyr/UdZk7Nzjn2eBg+cYhhS6Lkv6E2Zfr7B+kcJex2bjJFso3aHVQ7XXgWjDryI36Lzxw==} - - '@module-federation/error-codes@0.21.4': - resolution: {integrity: sha512-ClpL5MereWNXh+EgDjz7w4RrC1JlisQTvXDa1gLxpviHafzNDfdViVmuhi9xXVuj+EYo8KU70Y999KHhk9424Q==} + '@module-federation/error-codes@0.0.0-feat-shared-treeshake-poc-20251230120553': + resolution: {integrity: sha512-MR19b/ZGgVMDyFHoDr1Wp31/ZD8VohqxXzbVXGrkanHR6ojr4In9+wMa19/lWkkS5+CYze5LY9qZukmGqIzGGw==} '@module-federation/error-codes@0.21.6': resolution: {integrity: sha512-MLJUCQ05KnoVl8xd6xs9a5g2/8U+eWmVxg7xiBMeR0+7OjdWUbHwcwgVFatRIwSZvFgKHfWEiI7wsU1q1XbTRQ==} - '@module-federation/runtime-core@0.0.0-feat-shared-treeshake-poc-20251208061713': - resolution: {integrity: sha512-Cur3LcnigycBkpZt4JCGb1wGPzuvZoedjtKcbqtWLf9C7dQH4uPKkBmcvo+QW/vzzd9HX17ADQAPgQnsmC7z6g==} - - '@module-federation/runtime-core@0.21.4': - resolution: {integrity: sha512-SGpmoOLGNxZofpTOk6Lxb2ewaoz5wMi93AFYuuJB04HTVcngEK+baNeUZ2D/xewrqNIJoMY6f5maUjVfIIBPUA==} + '@module-federation/runtime-core@0.0.0-feat-shared-treeshake-poc-20251230120553': + resolution: {integrity: sha512-0s+q/Yiwg20VaheIj/wARc2uWXuIwS1ZTLeaUFUIKjDhgZRYn75m8lyP2YXWbjE50iADnD0PnCB/+/hHGTUZIw==} '@module-federation/runtime-core@0.21.6': resolution: {integrity: sha512-5Hd1Y5qp5lU/aTiK66lidMlM/4ji2gr3EXAtJdreJzkY+bKcI5+21GRcliZ4RAkICmvdxQU5PHPL71XmNc7Lsw==} - '@module-federation/runtime-tools@0.0.0-feat-shared-treeshake-poc-20251208061713': - resolution: {integrity: sha512-vyLbzv9vRnxTLpk1OhnHNsExgQsqy3DRnOUHeG0nOauFswetzfrNxPjqMKeaDORoiggIPjlMQkhEPnAalV9q9g==} - - '@module-federation/runtime-tools@0.21.4': - resolution: {integrity: sha512-RzFKaL0DIjSmkn76KZRfzfB6dD07cvID84950jlNQgdyoQFUGkqD80L6rIpVCJTY/R7LzR3aQjHnoqmq4JPo3w==} + '@module-federation/runtime-tools@0.0.0-feat-shared-treeshake-poc-20251230120553': + resolution: {integrity: sha512-CiabUJIymlGH/7w2/4lOA+Ga5vHefsI045mUB5Efe2lNPCwU7b/hpIoMGdvzPEaPNGP9zaEYvBTLrQQ1pBZBiw==} '@module-federation/runtime-tools@0.21.6': resolution: {integrity: sha512-fnP+ZOZTFeBGiTAnxve+axGmiYn2D60h86nUISXjXClK3LUY1krUfPgf6MaD4YDJ4i51OGXZWPekeMe16pkd8Q==} - '@module-federation/runtime@0.0.0-feat-shared-treeshake-poc-20251208061713': - resolution: {integrity: sha512-NnO7kaeGipZrOMxHrD8qDtcJwt7WBrr8mS4NrTS5Xxg98MuoRe4H4hD5XvL//o1td9tkbM8Lasr0Nz64k4mnSw==} - - '@module-federation/runtime@0.21.4': - resolution: {integrity: sha512-wgvGqryurVEvkicufJmTG0ZehynCeNLklv8kIk5BLIsWYSddZAE+xe4xov1kgH5fIJQAoQNkRauFFjVNlHoAkA==} + '@module-federation/runtime@0.0.0-feat-shared-treeshake-poc-20251230120553': + resolution: {integrity: sha512-KxX3OSZzrNw6MzjTn0Ur7K0mZ/8x+/TTiyaVtLD6iAVgCi3nmnj2hAmcNtGF733Na2vTtxCJCcFZBnW3DlQzmw==} '@module-federation/runtime@0.21.6': resolution: {integrity: sha512-+caXwaQqwTNh+CQqyb4mZmXq7iEemRDrTZQGD+zyeH454JAYnJ3s/3oDFizdH6245pk+NiqDyOOkHzzFQorKhQ==} - '@module-federation/sdk@0.0.0-feat-shared-treeshake-poc-20251208061713': - resolution: {integrity: sha512-89aKxad8ZNLobKRRQI7ipRzHYQx5dbKHcVtFW/nYkZN4HBqooWoaam+l3XcfKWWMRIOXWYg9Q424cR9BIorbSw==} - - '@module-federation/sdk@0.21.4': - resolution: {integrity: sha512-tzvhOh/oAfX++6zCDDxuvioHY4Jurf8vcfoCbKFxusjmyKr32GPbwFDazUP+OPhYCc3dvaa9oWU6X/qpUBLfJw==} + '@module-federation/sdk@0.0.0-feat-shared-treeshake-poc-20251230120553': + resolution: {integrity: sha512-3syc+/8Q8MNLoFPcpCRQ4uwCqv+7zsX/60WM4pqt058ZN1Y7AO4DDwxzuF+pt8vHxudcqALNa6VtDHvoPt8GPA==} '@module-federation/sdk@0.21.6': resolution: {integrity: sha512-x6hARETb8iqHVhEsQBysuWpznNZViUh84qV2yE7AD+g7uIzHKiYdoWqj10posbo5XKf/147qgWDzKZoKoEP2dw==} - '@module-federation/webpack-bundler-runtime@0.0.0-feat-shared-treeshake-poc-20251208061713': - resolution: {integrity: sha512-ED/yxAQbDDIJLg4PSpuL6eyg9kNJeSyU4/48u9yszSxlFG0AjGjJUAwVEL/HQ9vrS+bc0Y4E6tDSp752L1S3hQ==} - - '@module-federation/webpack-bundler-runtime@0.21.4': - resolution: {integrity: sha512-dusmR3uPnQh9u9ChQo3M+GLOuGFthfvnh7WitF/a1eoeTfRmXqnMFsXtZCUK+f/uXf+64874Zj/bhAgbBcVHZA==} + '@module-federation/webpack-bundler-runtime@0.0.0-feat-shared-treeshake-poc-20251230120553': + resolution: {integrity: sha512-KOi1+Tj9xz+9DYMfFp6exgKkYkzQ2X6zkof/yBq7HXdAnF9ID5Sc30JG/5pp+y9+bCv6uzKWV96n9Nrsk/igqA==} '@module-federation/webpack-bundler-runtime@0.21.6': resolution: {integrity: sha512-7zIp3LrcWbhGuFDTUMLJ2FJvcwjlddqhWGxi/MW3ur1a+HaO8v5tF2nl+vElKmbG1DFLU/52l3PElVcWf/YcsQ==} - '@module-federation/webpack-bundler-runtime@0.22.0': - resolution: {integrity: sha512-aM8gCqXu+/4wBmJtVeMeeMN5guw3chf+2i6HajKtQv7SJfxV/f4IyNQJUeUQu9HfiAZHjqtMV5Lvq/Lvh8LdyA==} - '@napi-rs/cli@3.0.4': resolution: {integrity: sha512-ilbCI69DVDQcIUSUB504LM1+Nhvo0jKycWAzzPJ22YwUoWrru/w0+V5sfjPINgkshQ4Ykv+oZOJXk9Kg1ZBUvg==} engines: {node: '>= 16'} @@ -10159,53 +10138,35 @@ snapshots: '@microsoft/tsdoc@0.16.0': {} - '@module-federation/error-codes@0.0.0-feat-shared-treeshake-poc-20251208061713': {} - - '@module-federation/error-codes@0.21.4': {} + '@module-federation/error-codes@0.0.0-feat-shared-treeshake-poc-20251230120553': {} '@module-federation/error-codes@0.21.6': {} - '@module-federation/runtime-core@0.0.0-feat-shared-treeshake-poc-20251208061713': - dependencies: - '@module-federation/error-codes': 0.0.0-feat-shared-treeshake-poc-20251208061713 - '@module-federation/sdk': 0.0.0-feat-shared-treeshake-poc-20251208061713 - - '@module-federation/runtime-core@0.21.4': + '@module-federation/runtime-core@0.0.0-feat-shared-treeshake-poc-20251230120553': dependencies: - '@module-federation/error-codes': 0.21.4 - '@module-federation/sdk': 0.21.4 + '@module-federation/error-codes': 0.0.0-feat-shared-treeshake-poc-20251230120553 + '@module-federation/sdk': 0.0.0-feat-shared-treeshake-poc-20251230120553 '@module-federation/runtime-core@0.21.6': dependencies: '@module-federation/error-codes': 0.21.6 '@module-federation/sdk': 0.21.6 - '@module-federation/runtime-tools@0.0.0-feat-shared-treeshake-poc-20251208061713': + '@module-federation/runtime-tools@0.0.0-feat-shared-treeshake-poc-20251230120553': dependencies: - '@module-federation/runtime': 0.0.0-feat-shared-treeshake-poc-20251208061713 - '@module-federation/webpack-bundler-runtime': 0.0.0-feat-shared-treeshake-poc-20251208061713 - - '@module-federation/runtime-tools@0.21.4': - dependencies: - '@module-federation/runtime': 0.21.4 - '@module-federation/webpack-bundler-runtime': 0.21.4 + '@module-federation/runtime': 0.0.0-feat-shared-treeshake-poc-20251230120553 + '@module-federation/webpack-bundler-runtime': 0.0.0-feat-shared-treeshake-poc-20251230120553 '@module-federation/runtime-tools@0.21.6': dependencies: '@module-federation/runtime': 0.21.6 '@module-federation/webpack-bundler-runtime': 0.21.6 - '@module-federation/runtime@0.0.0-feat-shared-treeshake-poc-20251208061713': + '@module-federation/runtime@0.0.0-feat-shared-treeshake-poc-20251230120553': dependencies: - '@module-federation/error-codes': 0.0.0-feat-shared-treeshake-poc-20251208061713 - '@module-federation/runtime-core': 0.0.0-feat-shared-treeshake-poc-20251208061713 - '@module-federation/sdk': 0.0.0-feat-shared-treeshake-poc-20251208061713 - - '@module-federation/runtime@0.21.4': - dependencies: - '@module-federation/error-codes': 0.21.4 - '@module-federation/runtime-core': 0.21.4 - '@module-federation/sdk': 0.21.4 + '@module-federation/error-codes': 0.0.0-feat-shared-treeshake-poc-20251230120553 + '@module-federation/runtime-core': 0.0.0-feat-shared-treeshake-poc-20251230120553 + '@module-federation/sdk': 0.0.0-feat-shared-treeshake-poc-20251230120553 '@module-federation/runtime@0.21.6': dependencies: @@ -10213,32 +10174,20 @@ snapshots: '@module-federation/runtime-core': 0.21.6 '@module-federation/sdk': 0.21.6 - '@module-federation/sdk@0.0.0-feat-shared-treeshake-poc-20251208061713': {} - - '@module-federation/sdk@0.21.4': {} + '@module-federation/sdk@0.0.0-feat-shared-treeshake-poc-20251230120553': {} '@module-federation/sdk@0.21.6': {} - '@module-federation/webpack-bundler-runtime@0.0.0-feat-shared-treeshake-poc-20251208061713': + '@module-federation/webpack-bundler-runtime@0.0.0-feat-shared-treeshake-poc-20251230120553': dependencies: - '@module-federation/runtime': 0.0.0-feat-shared-treeshake-poc-20251208061713 - '@module-federation/sdk': 0.0.0-feat-shared-treeshake-poc-20251208061713 - - '@module-federation/webpack-bundler-runtime@0.21.4': - dependencies: - '@module-federation/runtime': 0.21.4 - '@module-federation/sdk': 0.21.4 + '@module-federation/runtime': 0.0.0-feat-shared-treeshake-poc-20251230120553 + '@module-federation/sdk': 0.0.0-feat-shared-treeshake-poc-20251230120553 '@module-federation/webpack-bundler-runtime@0.21.6': dependencies: '@module-federation/runtime': 0.21.6 '@module-federation/sdk': 0.21.6 - '@module-federation/webpack-bundler-runtime@0.22.0': - dependencies: - '@module-federation/runtime': 0.22.0 - '@module-federation/sdk': 0.22.0 - '@napi-rs/cli@3.0.4(@emnapi/runtime@1.5.0)(@types/node@20.19.27)(emnapi@1.7.1(node-addon-api@7.1.1))': dependencies: '@inquirer/prompts': 7.8.6(@types/node@20.19.27) From cf4486a4e666f08d0910d51976dd2a0b71113da4 Mon Sep 17 00:00:00 2001 From: "zhanghang.heal" Date: Sun, 4 Jan 2026 17:49:20 +0800 Subject: [PATCH 14/87] fix: lint --- .../src/sharing/shared_container_entry_module.rs | 12 +++++++----- .../sharing/shared_used_exports_optimizer_plugin.rs | 8 +++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/crates/rspack_plugin_mf/src/sharing/shared_container_entry_module.rs b/crates/rspack_plugin_mf/src/sharing/shared_container_entry_module.rs index 1e5595c27afa..3bf9709215e4 100644 --- a/crates/rspack_plugin_mf/src/sharing/shared_container_entry_module.rs +++ b/crates/rspack_plugin_mf/src/sharing/shared_container_entry_module.rs @@ -158,15 +158,17 @@ impl Module for SharedContainerEntryModule { let module_graph = compilation.get_module_graph(); let mut factory = String::new(); for dependency_id in self.get_dependencies() { - let dependency = module_graph - .dependency_by_id(dependency_id) - .expect("share container dependency should exist"); - if let Some(dependency) = dependency.downcast_ref::() { + let dependency = module_graph.dependency_by_id(dependency_id); + if let Some(dependency) = dependency + .as_any() + .downcast_ref::() + { + let request: &str = dependency.user_request(); let module_expr = compilation.runtime_template.module_raw( compilation, &mut code_generation_result.runtime_requirements, dependency_id, - dependency.user_request(), + request, false, ); factory = compilation diff --git a/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_plugin.rs b/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_plugin.rs index a83528dfe66c..1c8992af3f89 100644 --- a/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_plugin.rs +++ b/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_plugin.rs @@ -420,15 +420,13 @@ async fn dependency_referenced_exports( return Ok(()); }; - let Some(dependency) = module_graph.dependency_by_id(dependency_id) else { - return Ok(()); - }; + let dependency = module_graph.dependency_by_id(dependency_id); let Some(module_dependency) = dependency.as_module_dependency() else { return Ok(()); }; - let share_key = module_dependency.request(); + let share_key: &str = module_dependency.request(); // Check if dependency type is EsmImportSpecifier and share_key is in shared_map if !self.shared_map.contains_key(share_key) { @@ -460,7 +458,7 @@ async fn dependency_referenced_exports( .as_any() .downcast_ref::() { - let ids = esm_dep.get_ids(module_graph); + let ids: &[Atom] = esm_dep.get_ids(module_graph); if ids.is_empty() { return Ok(()); } From 2f52780a00e63726650dced97befd999147d7556 Mon Sep 17 00:00:00 2001 From: "zhanghang.heal" Date: Tue, 6 Jan 2026 20:05:21 +0800 Subject: [PATCH 15/87] chore: rename config --- packages/rspack/etc/core.api.md | 4 ++-- packages/rspack/src/container/ModuleFederationPlugin.ts | 2 +- packages/rspack/src/sharing/TreeShakeSharedPlugin.ts | 2 +- .../configCases/sharing/reshake-share/index.js | 8 ++++---- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/rspack/etc/core.api.md b/packages/rspack/etc/core.api.md index 2e69d3362fc4..ebab0844849f 100644 --- a/packages/rspack/etc/core.api.md +++ b/packages/rspack/etc/core.api.md @@ -4890,8 +4890,6 @@ export interface ModuleFederationPluginOptions extends Omit Date: Wed, 7 Jan 2026 10:14:49 +0800 Subject: [PATCH 16/87] chore(deps): update patch npm dependencies (#12647) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 4 +- packages/create-rspack/package.json | 2 +- packages/rspack-cli/package.json | 2 +- packages/rspack/package.json | 4 +- pnpm-lock.yaml | 454 +++++++++++++++++----------- tests/rspack-test/package.json | 2 +- 6 files changed, 291 insertions(+), 177 deletions(-) diff --git a/package.json b/package.json index 12cee121c00a..7467cede552a 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "pnpm": "10.26.2" }, "devDependencies": { - "@biomejs/biome": "^2.3.10", + "@biomejs/biome": "^2.3.11", "@microsoft/api-extractor": "7.55.2", "@microsoft/api-extractor-model": "7.32.2", "@rslint/core": "0.1.13", @@ -74,7 +74,7 @@ "cross-env": "^10.1.0", "husky": "^9.1.7", "is-ci": "4.1.0", - "@rstest/core": "^0.7.7", + "@rstest/core": "^0.7.8", "lint-staged": "^16.2.7", "prettier": "3.7.4", "prettier-2": "npm:prettier@2.8.8", diff --git a/packages/create-rspack/package.json b/packages/create-rspack/package.json index 243022d447b6..e030e8a2e13d 100644 --- a/packages/create-rspack/package.json +++ b/packages/create-rspack/package.json @@ -27,7 +27,7 @@ "create-rstack": "1.7.20" }, "devDependencies": { - "@rslib/core": "0.19.0", + "@rslib/core": "0.19.1", "typescript": "^5.9.3" }, "publishConfig": { diff --git a/packages/rspack-cli/package.json b/packages/rspack-cli/package.json index 54e5b0b955de..2c66e0ac6f89 100644 --- a/packages/rspack-cli/package.json +++ b/packages/rspack-cli/package.json @@ -39,7 +39,7 @@ "webpack-bundle-analyzer": "4.10.2" }, "devDependencies": { - "@rslib/core": "0.19.0", + "@rslib/core": "0.19.1", "@rspack/core": "workspace:*", "@rspack/test-tools": "workspace:*", "@types/webpack-bundle-analyzer": "^4.7.0", diff --git a/packages/rspack/package.json b/packages/rspack/package.json index 2df9e39b04e4..2be157ff09cd 100644 --- a/packages/rspack/package.json +++ b/packages/rspack/package.json @@ -46,10 +46,10 @@ "directory": "packages/rspack" }, "devDependencies": { - "@ast-grep/napi": "^0.40.3", + "@ast-grep/napi": "^0.40.4", "@napi-rs/wasm-runtime": "1.0.7", "@rsbuild/plugin-node-polyfill": "^1.4.2", - "@rslib/core": "0.19.0", + "@rslib/core": "0.19.1", "@swc/types": "0.1.25", "@types/node": "^20.19.27", "@types/watchpack": "^2.4.5", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b1b40cbc2d1d..257445961ef0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,8 +14,8 @@ importers: .: devDependencies: '@biomejs/biome': - specifier: ^2.3.10 - version: 2.3.10 + specifier: ^2.3.11 + version: 2.3.11 '@microsoft/api-extractor': specifier: 7.55.2 version: 7.55.2(@types/node@20.19.27) @@ -29,8 +29,8 @@ importers: specifier: workspace:* version: link:packages/rspack-cli '@rstest/core': - specifier: ^0.7.7 - version: 0.7.7(jsdom@26.1.0) + specifier: ^0.7.8 + version: 0.7.8(jsdom@26.1.0) '@taplo/cli': specifier: ^0.7.0 version: 0.7.0 @@ -221,8 +221,8 @@ importers: version: 1.7.20 devDependencies: '@rslib/core': - specifier: 0.19.0 - version: 0.19.0(@microsoft/api-extractor@7.55.2(@types/node@20.19.27))(typescript@5.9.3) + specifier: 0.19.1 + version: 0.19.1(@microsoft/api-extractor@7.55.2(@types/node@20.19.27))(typescript@5.9.3) typescript: specifier: ^5.9.3 version: 5.9.3 @@ -358,17 +358,17 @@ importers: version: 0.5.17 devDependencies: '@ast-grep/napi': - specifier: ^0.40.3 - version: 0.40.3 + specifier: ^0.40.4 + version: 0.40.4 '@napi-rs/wasm-runtime': specifier: 1.0.7 version: 1.0.7 '@rsbuild/plugin-node-polyfill': specifier: ^1.4.2 - version: 1.4.2(@rsbuild/core@1.6.15) + version: 1.4.2(@rsbuild/core@1.7.2) '@rslib/core': - specifier: 0.19.0 - version: 0.19.0(@microsoft/api-extractor@7.55.2(@types/node@20.19.27))(typescript@5.9.3) + specifier: 0.19.1 + version: 0.19.1(@microsoft/api-extractor@7.55.2(@types/node@20.19.27))(typescript@5.9.3) '@swc/types': specifier: 0.1.25 version: 0.1.25 @@ -449,8 +449,8 @@ importers: version: 4.10.2 devDependencies: '@rslib/core': - specifier: 0.19.0 - version: 0.19.0(@microsoft/api-extractor@7.55.2(@types/node@20.19.27))(typescript@5.9.3) + specifier: 0.19.1 + version: 0.19.1(@microsoft/api-extractor@7.55.2(@types/node@20.19.27))(typescript@5.9.3) '@rspack/core': specifier: workspace:* version: link:../rspack @@ -733,8 +733,8 @@ importers: specifier: workspace:* version: link:../../packages/rspack-test-tools '@rstest/core': - specifier: ^0.7.7 - version: 0.7.7(jsdom@26.1.0) + specifier: ^0.7.8 + version: 0.7.8(jsdom@26.1.0) '@swc/helpers': specifier: 0.5.18 version: 0.5.18 @@ -957,7 +957,7 @@ importers: devDependencies: '@rsbuild/plugin-sass': specifier: ^1.4.0 - version: 1.4.0(@rsbuild/core@1.7.0-beta.2) + version: 1.4.0(@rsbuild/core@1.7.2) '@rspress/core': specifier: 2.0.0-rc.4 version: 2.0.0-rc.4(@types/react@19.2.7) @@ -1002,10 +1002,10 @@ importers: version: 1.0.4 rsbuild-plugin-google-analytics: specifier: 1.0.4 - version: 1.0.4(@rsbuild/core@1.7.0-beta.2) + version: 1.0.4(@rsbuild/core@1.7.2) rsbuild-plugin-open-graph: specifier: 1.1.0 - version: 1.1.0(@rsbuild/core@1.7.0-beta.2) + version: 1.1.0(@rsbuild/core@1.7.2) rspress-plugin-font-open-sans: specifier: 1.0.3 version: 1.0.3(@rspress/core@2.0.0-rc.4(@types/react@19.2.7)) @@ -1142,8 +1142,8 @@ packages: cpu: [arm64] os: [darwin] - '@ast-grep/napi-darwin-arm64@0.40.3': - resolution: {integrity: sha512-uIUecbLHjGE2HHSrCH2jzpjekPFaHOnBkqhUkMmfNUTG5c3H/4zSUDcWRLalFPOlNBgHtKGPe/RcIYGfC7Uk6Q==} + '@ast-grep/napi-darwin-arm64@0.40.4': + resolution: {integrity: sha512-UIkpoEExRghZe5wN6QXGkDzI65zKVoaBQowAzmEd3MCGP8VlAK3FoxDMdy0OLgQVTyRUdBUwG384WpxiWilYEw==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] @@ -1154,8 +1154,8 @@ packages: cpu: [x64] os: [darwin] - '@ast-grep/napi-darwin-x64@0.40.3': - resolution: {integrity: sha512-j6wNLb0LGNpKCkCYRd4zDWe5Q/+1CSKP62WtKgvACEvlLw4nMldxE6TnNYZpZddV7wG+Rb+tfuih33rB4h+dZA==} + '@ast-grep/napi-darwin-x64@0.40.4': + resolution: {integrity: sha512-derMkDWiMFjRlcN0SEHXNPeZ67OGR5So6b4r/+ETvZMZavLQv+ER0vevltFS4ci8m402g7l/wVOdSE1oHcN2Iw==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] @@ -1166,8 +1166,8 @@ packages: cpu: [arm64] os: [linux] - '@ast-grep/napi-linux-arm64-gnu@0.40.3': - resolution: {integrity: sha512-/KNX7byCcXrmPXLbtBExJSjajVxlgwl3rlFxtDZvgPAoIa+kpTZ4IGKgciNaUi0TXEpJsq9mPvVHLR2WpP52rA==} + '@ast-grep/napi-linux-arm64-gnu@0.40.4': + resolution: {integrity: sha512-1CeDsK6WRMz169mTXLfXdn2GkQAsMkYbqGd7mHDa2VqutJwDYrqe6t4QiFAlr+LRT2bQuExpPh3AiC8BNd6UQQ==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] @@ -1178,8 +1178,8 @@ packages: cpu: [arm64] os: [linux] - '@ast-grep/napi-linux-arm64-musl@0.40.3': - resolution: {integrity: sha512-w5ivvONb3zb6AigCvl0sr+O4WYgMziQg+I4n4JDdYu8rCGLUBc0WSb4++nmEY0KSNbHxKYVduLIPaEtXKUVhdg==} + '@ast-grep/napi-linux-arm64-musl@0.40.4': + resolution: {integrity: sha512-VqjL9Xbq5NNXexY4rluaFtpuHHGbcNIwFXInbm8hdaZS3Rsr9tz+QCEhDNO4IJgPtcRUOpa7AIztZotwxrb/iw==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] @@ -1190,8 +1190,8 @@ packages: cpu: [x64] os: [linux] - '@ast-grep/napi-linux-x64-gnu@0.40.3': - resolution: {integrity: sha512-3W1I9hKREFR/Wpu443C7RCR7s3kIP61eBDaevpJcO3Xi99+t2UNas6p765oqv08M7DOxJoTbC4OpI9GybD0aUA==} + '@ast-grep/napi-linux-x64-gnu@0.40.4': + resolution: {integrity: sha512-6BrPYjP+Gr+mkI3z3Xh/UHkOedJ25qKGdhRwbYteeK/QX3rWeuuo/tUjow4nh/8ewhk04wHGw/G96OiF47ICjA==} engines: {node: '>= 10'} cpu: [x64] os: [linux] @@ -1202,8 +1202,8 @@ packages: cpu: [x64] os: [linux] - '@ast-grep/napi-linux-x64-musl@0.40.3': - resolution: {integrity: sha512-A7W/iRlkuGQG7qR6ov4QZjk7/1QPSxTOLxQFHjvdUUEa5Eklv85YMpMCi38v9NI2PP9fBFNB/dQisf6cvQUoLA==} + '@ast-grep/napi-linux-x64-musl@0.40.4': + resolution: {integrity: sha512-4LGq6xYmOsgEycx4Cu9CdyNYa99O/C1bOsZi09T0C/NifKR+55v8og6nZrGCwsKEs4jWresdal4p7WXw3k8+0g==} engines: {node: '>= 10'} cpu: [x64] os: [linux] @@ -1214,8 +1214,8 @@ packages: cpu: [arm64] os: [win32] - '@ast-grep/napi-win32-arm64-msvc@0.40.3': - resolution: {integrity: sha512-nvBtz+g0d0eNIJo8+ryP2pETuGg1K5Up5AwDWQ+dbfQq3xvuL/kSseG+3MwNp6ASWjL3OZ/JinTDo6r3p/BocA==} + '@ast-grep/napi-win32-arm64-msvc@0.40.4': + resolution: {integrity: sha512-QrI9m9wmFYTRnyTsYOX+9/D/B+h0eyFqZf2qh/U3kbRU/ZZJnxI75YjYVjtoa2QI4oEJlzYb0QhKAN8NKIDYRA==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] @@ -1226,8 +1226,8 @@ packages: cpu: [ia32] os: [win32] - '@ast-grep/napi-win32-ia32-msvc@0.40.3': - resolution: {integrity: sha512-4oiHlAEuD8BcdtDPGhodN9vBzW7P2z0YU1Yeau5rEzLrfwi2SHptfTDsmngBAKLYXoRqHHs9T4E5ZENnDs6SQA==} + '@ast-grep/napi-win32-ia32-msvc@0.40.4': + resolution: {integrity: sha512-JLhcgCUD7e74rZ39XLEfUOU26TQboJltzHir2oSpvjZPtq4aBHEJOynq7dGABZdMrzRUOPdbBdM+nFzPiU38iQ==} engines: {node: '>= 10'} cpu: [ia32] os: [win32] @@ -1238,8 +1238,8 @@ packages: cpu: [x64] os: [win32] - '@ast-grep/napi-win32-x64-msvc@0.40.3': - resolution: {integrity: sha512-aZijW9FjFlUaC9NBv8f+yAR5Ql5tPtBPNBZkyy6GcOPiiHSjZKObvNJxIiw5KsQ26mTtZzq/l7z3t/z3lDqWWA==} + '@ast-grep/napi-win32-x64-msvc@0.40.4': + resolution: {integrity: sha512-DdsqVs/kg4Iun8GU8GoOw9L9WkT2pVLAZ+1hV9t+PsdI6SR3HGRIUIJSzKz2uejr8tY8evTZmdjBWyjUav8qbQ==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -1248,8 +1248,8 @@ packages: resolution: {integrity: sha512-Hb4o6h1Pf6yRUAX07DR4JVY7dmQw+RVQMW5/m55GoiAT/VRoKCWBtIUPPOnqDVhbx1Cjfil9b6EDrgJsUAujEQ==} engines: {node: '>= 10'} - '@ast-grep/napi@0.40.3': - resolution: {integrity: sha512-pRChD3a571FjQndLyabnrrZ5N3T0n68Q+6LyJz5SaZs/gc/TA0s4+UuoL12GEx/oqmaHHYOhnaFW0WB6dvI6fA==} + '@ast-grep/napi@0.40.4': + resolution: {integrity: sha512-unRhSrSn4X0tf7nCuj300rBrlrXqtGbKanFX75CNmn2NM+NyPrdvq1tdDk2F+XA8Z574MynpSeCESii3WBK+bw==} engines: {node: '>= 10'} '@babel/code-frame@7.27.1': @@ -1456,55 +1456,55 @@ packages: resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==} engines: {node: '>=6.9.0'} - '@biomejs/biome@2.3.10': - resolution: {integrity: sha512-/uWSUd1MHX2fjqNLHNL6zLYWBbrJeG412/8H7ESuK8ewoRoMPUgHDebqKrPTx/5n6f17Xzqc9hdg3MEqA5hXnQ==} + '@biomejs/biome@2.3.11': + resolution: {integrity: sha512-/zt+6qazBWguPG6+eWmiELqO+9jRsMZ/DBU3lfuU2ngtIQYzymocHhKiZRyrbra4aCOoyTg/BmY+6WH5mv9xmQ==} engines: {node: '>=14.21.3'} hasBin: true - '@biomejs/cli-darwin-arm64@2.3.10': - resolution: {integrity: sha512-M6xUjtCVnNGFfK7HMNKa593nb7fwNm43fq1Mt71kpLpb+4mE7odO8W/oWVDyBVO4ackhresy1ZYO7OJcVo/B7w==} + '@biomejs/cli-darwin-arm64@2.3.11': + resolution: {integrity: sha512-/uXXkBcPKVQY7rc9Ys2CrlirBJYbpESEDme7RKiBD6MmqR2w3j0+ZZXRIL2xiaNPsIMMNhP1YnA+jRRxoOAFrA==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [darwin] - '@biomejs/cli-darwin-x64@2.3.10': - resolution: {integrity: sha512-Vae7+V6t/Avr8tVbFNjnFSTKZogZHFYl7MMH62P/J1kZtr0tyRQ9Fe0onjqjS2Ek9lmNLmZc/VR5uSekh+p1fg==} + '@biomejs/cli-darwin-x64@2.3.11': + resolution: {integrity: sha512-fh7nnvbweDPm2xEmFjfmq7zSUiox88plgdHF9OIW4i99WnXrAC3o2P3ag9judoUMv8FCSUnlwJCM1B64nO5Fbg==} engines: {node: '>=14.21.3'} cpu: [x64] os: [darwin] - '@biomejs/cli-linux-arm64-musl@2.3.10': - resolution: {integrity: sha512-B9DszIHkuKtOH2IFeeVkQmSMVUjss9KtHaNXquYYWCjH8IstNgXgx5B0aSBQNr6mn4RcKKRQZXn9Zu1rM3O0/A==} + '@biomejs/cli-linux-arm64-musl@2.3.11': + resolution: {integrity: sha512-XPSQ+XIPZMLaZ6zveQdwNjbX+QdROEd1zPgMwD47zvHV+tCGB88VH+aynyGxAHdzL+Tm/+DtKST5SECs4iwCLg==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] - '@biomejs/cli-linux-arm64@2.3.10': - resolution: {integrity: sha512-hhPw2V3/EpHKsileVOFynuWiKRgFEV48cLe0eA+G2wO4SzlwEhLEB9LhlSrVeu2mtSn205W283LkX7Fh48CaxA==} + '@biomejs/cli-linux-arm64@2.3.11': + resolution: {integrity: sha512-l4xkGa9E7Uc0/05qU2lMYfN1H+fzzkHgaJoy98wO+b/7Gl78srbCRRgwYSW+BTLixTBrM6Ede5NSBwt7rd/i6g==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] - '@biomejs/cli-linux-x64-musl@2.3.10': - resolution: {integrity: sha512-QTfHZQh62SDFdYc2nfmZFuTm5yYb4eO1zwfB+90YxUumRCR171tS1GoTX5OD0wrv4UsziMPmrePMtkTnNyYG3g==} + '@biomejs/cli-linux-x64-musl@2.3.11': + resolution: {integrity: sha512-vU7a8wLs5C9yJ4CB8a44r12aXYb8yYgBn+WeyzbMjaCMklzCv1oXr8x+VEyWodgJt9bDmhiaW/I0RHbn7rsNmw==} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] - '@biomejs/cli-linux-x64@2.3.10': - resolution: {integrity: sha512-wwAkWD1MR95u+J4LkWP74/vGz+tRrIQvr8kfMMJY8KOQ8+HMVleREOcPYsQX82S7uueco60L58Wc6M1I9WA9Dw==} + '@biomejs/cli-linux-x64@2.3.11': + resolution: {integrity: sha512-/1s9V/H3cSe0r0Mv/Z8JryF5x9ywRxywomqZVLHAoa/uN0eY7F8gEngWKNS5vbbN/BsfpCG5yeBT5ENh50Frxg==} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] - '@biomejs/cli-win32-arm64@2.3.10': - resolution: {integrity: sha512-o7lYc9n+CfRbHvkjPhm8s9FgbKdYZu5HCcGVMItLjz93EhgJ8AM44W+QckDqLA9MKDNFrR8nPbO4b73VC5kGGQ==} + '@biomejs/cli-win32-arm64@2.3.11': + resolution: {integrity: sha512-PZQ6ElCOnkYapSsysiTy0+fYX+agXPlWugh6+eQ6uPKI3vKAqNp6TnMhoM3oY2NltSB89hz59o8xIfOdyhi9Iw==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [win32] - '@biomejs/cli-win32-x64@2.3.10': - resolution: {integrity: sha512-pHEFgq7dUEsKnqG9mx9bXihxGI49X+ar+UBrEIj3Wqj3UCZp1rNgV+OoyjFgcXsjCWpuEAF4VJdkZr3TrWdCbQ==} + '@biomejs/cli-win32-x64@2.3.11': + resolution: {integrity: sha512-43VrG813EW+b5+YbDbz31uUsheX+qFKCpXeY9kfdAx+ww3naKxeVkTD9zLIWxUPfJquANMHrmW3wbe/037G0Qg==} engines: {node: '>=14.21.3'} cpu: [x64] os: [win32] @@ -3203,13 +3203,13 @@ packages: engines: {node: '>=18.12.0'} hasBin: true - '@rsbuild/core@1.7.0-beta.1': - resolution: {integrity: sha512-qQ9jKF0GzUI2a53Ql18p252PBPBRVnLWQQXOWevolHNakSrTQ+ESD9pK0AvmJIF8TiQ7qaSccEzrisTg+EQfEA==} + '@rsbuild/core@1.7.1': + resolution: {integrity: sha512-ULIE/Qh+Ne80Pm/aUPbRHUvwvIzpap07jYNFB47azI8w5Q3sDEC4Gn574jsluT/42iNDsZTFADRBog9FEvtN9Q==} engines: {node: '>=18.12.0'} hasBin: true - '@rsbuild/core@1.7.0-beta.2': - resolution: {integrity: sha512-sPJ21GTJiX9dTj9xtB10ZFbWMdX2PML0MgF98msaLLVDpwYGa8kvS6jFGO+L2T+zbuWFxfMYdU7a8jX6G4JRsQ==} + '@rsbuild/core@1.7.2': + resolution: {integrity: sha512-VAFO6cM+cyg2ntxNW6g3tB2Jc5J5mpLjLluvm7VtW2uceNzyUlVv41o66Yp1t1ikxd3ljtqegViXem62JqzveA==} engines: {node: '>=18.12.0'} hasBin: true @@ -3231,8 +3231,8 @@ packages: peerDependencies: '@rsbuild/core': 1.x - '@rslib/core@0.19.0': - resolution: {integrity: sha512-t94QnZGU8YSn5xQ8vNqxIpee5Mo+S77SEVA/0Tjft0I0dLmU6GZHeYAmoztNfWLudSUl4KrvilnxGPlySMdPvw==} + '@rslib/core@0.19.1': + resolution: {integrity: sha512-Fz+uknjf9BRE6tNax7zcZOZ8FX3FLT5kKcR10vHdo6IgCaMZpJxQmM62NNfv21kdy5u1PdIRgKFVpqP2QTarfg==} engines: {node: '>=18.12.0'} hasBin: true peerDependencies: @@ -3283,8 +3283,13 @@ packages: cpu: [arm64] os: [darwin] - '@rspack/binding-darwin-arm64@1.7.0-beta.1': - resolution: {integrity: sha512-UR+WRtuRttu1dMY8lIP3qHcDVjRfz8RtS5KegUw7EArmOMDQBUpZtc+xporXnKr/bf6FTdwUpUh2KTJ9Ss3H2Q==} + '@rspack/binding-darwin-arm64@1.7.0': + resolution: {integrity: sha512-HMYrhvVh3sMRBXl6cSI2JqsvlHJKQ42qX+Sw4qbj7LeZBN6Gv4GjfL3cXRLUTdO37FOC0uLEUYgxVXetx/Y4sA==} + cpu: [arm64] + os: [darwin] + + '@rspack/binding-darwin-arm64@1.7.1': + resolution: {integrity: sha512-3C0w0kfCHfgOH+AP/Dx1bm/b3AR/or5CmU22Abevek0m95ndU3iT902eLcm9JNiMQnDQLBQbolfj5P591t0oPg==} cpu: [arm64] os: [darwin] @@ -3293,8 +3298,13 @@ packages: cpu: [x64] os: [darwin] - '@rspack/binding-darwin-x64@1.7.0-beta.1': - resolution: {integrity: sha512-wPR3uE0PXL+AUHI7rH2SKAYxinjjhiVOLgE+KxeHQwx5P3G1GjmMi9b+vif/NRTDNyFYS0VnxHFMb7Ja5rFhRw==} + '@rspack/binding-darwin-x64@1.7.0': + resolution: {integrity: sha512-R/SoR04ySmHPqoIBGC+SjP9zRGjL1fS908mdwBvQ1RfFinKu7a/o/5rxH/vxUUsVQrHCyX+o7YXpfWq9xpvyQA==} + cpu: [x64] + os: [darwin] + + '@rspack/binding-darwin-x64@1.7.1': + resolution: {integrity: sha512-HTrBpdw2gWwcpJ3c8h4JF8B1YRNvrFT+K620ycttrlu/HvI4/U770BBJ/ej36R/hdh59JvMCGe+w49FyXv6rzg==} cpu: [x64] os: [darwin] @@ -3303,8 +3313,13 @@ packages: cpu: [arm64] os: [linux] - '@rspack/binding-linux-arm64-gnu@1.7.0-beta.1': - resolution: {integrity: sha512-iI+84/jOgLCTfORniIsQFoqwSsT9ppJXCCZS0Hzx9nn5vjZ+i/dmh6C7EwD9pJQgLhuqMLRv9Pd7Cz8zD9pv/A==} + '@rspack/binding-linux-arm64-gnu@1.7.0': + resolution: {integrity: sha512-jDCcso++qshu58+Iuo6oiL0XKuX04lDugL0qwrWHW8SS/EjZ2rc1J3yQx+XDW0PCQsfI2c9ji0IOW56PzW1hXQ==} + cpu: [arm64] + os: [linux] + + '@rspack/binding-linux-arm64-gnu@1.7.1': + resolution: {integrity: sha512-BX9yAPCO0WBFyOzKl9bSXT/cH27nnOJp02smIQMxfv7RNfwGkJg5GgakYcuYG+9U1HEFitBSzmwS2+dxDcAxlg==} cpu: [arm64] os: [linux] @@ -3313,8 +3328,13 @@ packages: cpu: [arm64] os: [linux] - '@rspack/binding-linux-arm64-musl@1.7.0-beta.1': - resolution: {integrity: sha512-EdYWcjXOMTYB+qdR84u2wBwhNlqdwDmiMrL3TnFYh2NH6dQJqEUvzSe7bx2UKOobIkNnVU0wCeT5jZOPnEwXBg==} + '@rspack/binding-linux-arm64-musl@1.7.0': + resolution: {integrity: sha512-0W49s0SQQhr3hZ8Zd7Auyf2pv4OTBr6wQhgWUQ6XeeMEjB16KpAVypSK5Jpn1ON0v9jAPLdod+a255rz8/f3kg==} + cpu: [arm64] + os: [linux] + + '@rspack/binding-linux-arm64-musl@1.7.1': + resolution: {integrity: sha512-maBX19XyiVkxzh/NA79ALetCobc4zUyoWkWLeCGyW5xKzhPVFatJp+qCiHqHkqUZcgRo+1i5ihoZ2bXmelIeZg==} cpu: [arm64] os: [linux] @@ -3323,8 +3343,13 @@ packages: cpu: [x64] os: [linux] - '@rspack/binding-linux-x64-gnu@1.7.0-beta.1': - resolution: {integrity: sha512-3G3bkWnxkGnCn/t4KtU9KHG4lLdmIWF3ApEkXZL0YNHSEg+eFkMm3oVL/YtJUdRNU4QlbL4lwPcuMIDK6FOefw==} + '@rspack/binding-linux-x64-gnu@1.7.0': + resolution: {integrity: sha512-oFjzjTD1MmG0ucAaP0Wyg9eobrsnFwZjEHa7LwyzWDRBeC3GWAF9T04Bqd6Ba6DgASGzU0BjEJcUpjvtXxO95Q==} + cpu: [x64] + os: [linux] + + '@rspack/binding-linux-x64-gnu@1.7.1': + resolution: {integrity: sha512-8KJAeBLiWcN7zEc9aaS7LRJPZVtZuQU8mCsn+fRhdQDSc+a9FcTN8b6Lw29z8cejwbU6Gxr/8wk5XGexMWFaZA==} cpu: [x64] os: [linux] @@ -3333,8 +3358,13 @@ packages: cpu: [x64] os: [linux] - '@rspack/binding-linux-x64-musl@1.7.0-beta.1': - resolution: {integrity: sha512-q5LnITueKNPFFDmOjGU7e17cczr65MXQKC72VvNEpD2lDSqe9GbQ9tmlbG1seWmGKtsRSwi+j1qeZhoC3AQW4w==} + '@rspack/binding-linux-x64-musl@1.7.0': + resolution: {integrity: sha512-MNGslPLOsurdwOcoo6r0u8mLpw1ADar3hkx67WzwwMqYnem/Ky0aANJC2JvQHPC22mu01gCOukHYyEaUFTxcuw==} + cpu: [x64] + os: [linux] + + '@rspack/binding-linux-x64-musl@1.7.1': + resolution: {integrity: sha512-Gn9x5vhKRELvSoZ3ZjquY8eWtCXur0OsYnZ2/ump8mofM6IDaL7Qqu3Hf4Kud31PDH0tfz0jWf9piX32HHPmgg==} cpu: [x64] os: [linux] @@ -3342,8 +3372,12 @@ packages: resolution: {integrity: sha512-VUwdhl/lI4m6o1OGCZ9JwtMjTV/yLY5VZTQdEPKb40JMTlmZ5MBlr5xk7ByaXXYHr6I+qnqEm73iMKQvg6iknw==} cpu: [wasm32] - '@rspack/binding-wasm32-wasi@1.7.0-beta.1': - resolution: {integrity: sha512-cJ41fUloY6RMMMsa5JQ0z13BDDlmMR5NX5LYWB0aY+rppF77EfxaPeNzb9NTL3QKh8zy1OPcZzZ+n27JEWlAXg==} + '@rspack/binding-wasm32-wasi@1.7.0': + resolution: {integrity: sha512-eaZzkGpxzVESmaX/UALMiQO+eNppe/i1VWQksGRfdoUu0rILqr/YDjsWFTcpbI9Dt3fg2kshHawBHxfwtxHcZQ==} + cpu: [wasm32] + + '@rspack/binding-wasm32-wasi@1.7.1': + resolution: {integrity: sha512-2r9M5iVchmsFkp3sz7A5YnMm2TfpkB71LK3AoaRWKMfvf5oFky0GSGISYd2TCBASO+X2Qskaq+B24Szo8zH5FA==} cpu: [wasm32] '@rspack/binding-win32-arm64-msvc@1.6.8': @@ -3351,8 +3385,13 @@ packages: cpu: [arm64] os: [win32] - '@rspack/binding-win32-arm64-msvc@1.7.0-beta.1': - resolution: {integrity: sha512-+Jbx0le019Xc692pD6bqN7pZQDZg1fZuKLpBaI+FINIkJ7JzkCn64UhbxFpcskc1Z8/tBojEvu9FIozVnWq7Kg==} + '@rspack/binding-win32-arm64-msvc@1.7.0': + resolution: {integrity: sha512-XFg4l7sOhupnpG0soOfzYLeF2cgpSJMenmjmdzd9y06CotTyVId0hNoS7y+A7hEP8XGf3YPbdiUL5UDp6+DRBA==} + cpu: [arm64] + os: [win32] + + '@rspack/binding-win32-arm64-msvc@1.7.1': + resolution: {integrity: sha512-/WIHp982yqqqAuiz2WLtf1ofo9d1lHDGZJ7flxFllb1iMgnUeSRyX6stxEi11K3Rg6pQa7FdCZGKX/engyj2bw==} cpu: [arm64] os: [win32] @@ -3361,8 +3400,13 @@ packages: cpu: [ia32] os: [win32] - '@rspack/binding-win32-ia32-msvc@1.7.0-beta.1': - resolution: {integrity: sha512-UOqEsWL8Udp1Fb2YwoY3Na2fo5gwzGW9EXVJ7l0AJEVSKGSwuM/Wk0dD5jmwKYilVzwZ23Dx8hVZreM6/Y33aQ==} + '@rspack/binding-win32-ia32-msvc@1.7.0': + resolution: {integrity: sha512-eWt2XV6la/c0IlU/18RlhQsqwHGShSypwA3kt4s/dpfOK0YB1h4f0fYeUZuvj2X0MIoJQGhMofMrgA35/IcAcw==} + cpu: [ia32] + os: [win32] + + '@rspack/binding-win32-ia32-msvc@1.7.1': + resolution: {integrity: sha512-Kpela29n+kDGGsss6q/3qTd6n9VW7TOQaiA7t1YLdCCl8qqcdKlz/vWjFMd2MqgcSGC/16PvChE4sgpUvryfCQ==} cpu: [ia32] os: [win32] @@ -3371,16 +3415,24 @@ packages: cpu: [x64] os: [win32] - '@rspack/binding-win32-x64-msvc@1.7.0-beta.1': - resolution: {integrity: sha512-YtziYe5sSLcJRItkp4Vq/dKGUV9dBZHwhXGjf44K4AlwEtAblf2GnlzrYfDeZP6uqqCjH0f9A//3+zytO2so0w==} + '@rspack/binding-win32-x64-msvc@1.7.0': + resolution: {integrity: sha512-LOL5G8rfbAwlmusx+t98r9QzuGRz+L9Bg+8s5s6K/Qe64iemcNIuxGr5QLVq1jLa0SGNTeog4N21pAzlkWh4jw==} + cpu: [x64] + os: [win32] + + '@rspack/binding-win32-x64-msvc@1.7.1': + resolution: {integrity: sha512-B/y4MWqP2Xeto1/HV0qtZNOMPSLrEVOqi2b7JSIXG/bhlf+3IAkDzEEoHs+ZikLR4C8hMaS0pVJsDGKFmGzC9A==} cpu: [x64] os: [win32] '@rspack/binding@1.6.8': resolution: {integrity: sha512-lUeL4mbwGo+nqRKqFDCm9vH2jv9FNMVt1X8jqayWRcOCPlj/2UVMEFgqjR7Pp2vlvnTKq//31KbDBJmDZq31RQ==} - '@rspack/binding@1.7.0-beta.1': - resolution: {integrity: sha512-BZXEMduPOyGkqJNRaf90uI2QMSH241S1YwXyK9DKH406sZfUTvIwhE9LFVaEgNucChwJ7DXTriwuBJSHVf0R1Q==} + '@rspack/binding@1.7.0': + resolution: {integrity: sha512-xO+pZKG2dvU9CuRTTi+DcCc4p+CZhBJlvuYikBja/0a62cTntQV2PWV+/xU1a6Vbo89yNz158LR05nvjtKVwTw==} + + '@rspack/binding@1.7.1': + resolution: {integrity: sha512-qVTV1/UWpMSZktvK5A8+HolgR1Qf0nYR3Gg4Vax5x3/BcHDpwGZ0fbdFRUirGVWH/XwxZ81zoI6F2SZq7xbX+w==} '@rspack/core@1.6.8': resolution: {integrity: sha512-FolcIAH5FW4J2FET+qwjd1kNeFbCkd0VLuIHO0thyolEjaPSxw5qxG67DA7BZGm6PVcoiSgPLks1DL6eZ8c+fA==} @@ -3391,8 +3443,17 @@ packages: '@swc/helpers': optional: true - '@rspack/core@1.7.0-beta.1': - resolution: {integrity: sha512-dqLODRPWFCWs4YR34kPT4Gr7ruLBihn4lxM+nf87FiaXKIeb7Ga5K0cnh52t+Wzly6GsdAWZQWmq0pDiqPhy0w==} + '@rspack/core@1.7.0': + resolution: {integrity: sha512-uDxPQsPh/+2DnOISuKnUiXZ9M0y2G1BOsI0IesxPJGp42ME2QW7axbJfUqD3bwp4bi3RN2zqh56NgxU/XETQvA==} + engines: {node: '>=18.12.0'} + peerDependencies: + '@swc/helpers': '>=0.5.1' + peerDependenciesMeta: + '@swc/helpers': + optional: true + + '@rspack/core@1.7.1': + resolution: {integrity: sha512-kRxfY8RRa6nU3/viDvAIP6CRpx+0rfXFRonPL0pHBx8u6HhV7m9rLEyaN6MWsLgNIAWkleFGb7tdo4ux2ljRJQ==} engines: {node: '>=18.12.0'} peerDependencies: '@swc/helpers': '>=0.5.1' @@ -3521,8 +3582,8 @@ packages: '@rstack-dev/doc-ui@1.12.2': resolution: {integrity: sha512-4C+tfhODxCp81ohCik9baOdbhYGNFqdwcwQMAESncF0YX3EawdNCORI1E26DqkY/F3ggfKG4qOlEAu+oOxrPxg==} - '@rstest/core@0.7.7': - resolution: {integrity: sha512-WZSTMcgdrg6BVEZSP6XP0Bl4Ng+riaTmIuJrW4QPGOOefFXxVpPjQ4p1NpMZQAGOVf9qK2jxH+fus0X3/SpNDA==} + '@rstest/core@0.7.8': + resolution: {integrity: sha512-A7oN5GLMYuVkTGjXTH+69nz3wR0lxHUkWax+hVq+jNQmcf81ZqJosTLqN6jwFZdmCfHbj3iTd9ku6boo8tJlnA==} engines: {node: '>=18.12.0'} hasBin: true peerDependencies: @@ -7489,8 +7550,8 @@ packages: rrweb-cssom@0.8.0: resolution: {integrity: sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==} - rsbuild-plugin-dts@0.19.0: - resolution: {integrity: sha512-5NkHONFDMBXv0qr1voHQigVhPmqai2icbJtckXJSCrpSTAJO0eXkGsHNVR8QvnsZEZWXL+KsIgNEJ7C8tYginQ==} + rsbuild-plugin-dts@0.19.1: + resolution: {integrity: sha512-LaK1RAvHPrb/ulfwvZckeui5qkQSKxf1RD7rzBTgK2UY8fMTQgsxsvun/XzfzAOKqdagzIohhnmNd5+j2Niqww==} engines: {node: '>=18.12.0'} peerDependencies: '@microsoft/api-extractor': ^7 @@ -8929,55 +8990,55 @@ snapshots: '@ast-grep/napi-darwin-arm64@0.37.0': optional: true - '@ast-grep/napi-darwin-arm64@0.40.3': + '@ast-grep/napi-darwin-arm64@0.40.4': optional: true '@ast-grep/napi-darwin-x64@0.37.0': optional: true - '@ast-grep/napi-darwin-x64@0.40.3': + '@ast-grep/napi-darwin-x64@0.40.4': optional: true '@ast-grep/napi-linux-arm64-gnu@0.37.0': optional: true - '@ast-grep/napi-linux-arm64-gnu@0.40.3': + '@ast-grep/napi-linux-arm64-gnu@0.40.4': optional: true '@ast-grep/napi-linux-arm64-musl@0.37.0': optional: true - '@ast-grep/napi-linux-arm64-musl@0.40.3': + '@ast-grep/napi-linux-arm64-musl@0.40.4': optional: true '@ast-grep/napi-linux-x64-gnu@0.37.0': optional: true - '@ast-grep/napi-linux-x64-gnu@0.40.3': + '@ast-grep/napi-linux-x64-gnu@0.40.4': optional: true '@ast-grep/napi-linux-x64-musl@0.37.0': optional: true - '@ast-grep/napi-linux-x64-musl@0.40.3': + '@ast-grep/napi-linux-x64-musl@0.40.4': optional: true '@ast-grep/napi-win32-arm64-msvc@0.37.0': optional: true - '@ast-grep/napi-win32-arm64-msvc@0.40.3': + '@ast-grep/napi-win32-arm64-msvc@0.40.4': optional: true '@ast-grep/napi-win32-ia32-msvc@0.37.0': optional: true - '@ast-grep/napi-win32-ia32-msvc@0.40.3': + '@ast-grep/napi-win32-ia32-msvc@0.40.4': optional: true '@ast-grep/napi-win32-x64-msvc@0.37.0': optional: true - '@ast-grep/napi-win32-x64-msvc@0.40.3': + '@ast-grep/napi-win32-x64-msvc@0.40.4': optional: true '@ast-grep/napi@0.37.0': @@ -8992,17 +9053,17 @@ snapshots: '@ast-grep/napi-win32-ia32-msvc': 0.37.0 '@ast-grep/napi-win32-x64-msvc': 0.37.0 - '@ast-grep/napi@0.40.3': + '@ast-grep/napi@0.40.4': optionalDependencies: - '@ast-grep/napi-darwin-arm64': 0.40.3 - '@ast-grep/napi-darwin-x64': 0.40.3 - '@ast-grep/napi-linux-arm64-gnu': 0.40.3 - '@ast-grep/napi-linux-arm64-musl': 0.40.3 - '@ast-grep/napi-linux-x64-gnu': 0.40.3 - '@ast-grep/napi-linux-x64-musl': 0.40.3 - '@ast-grep/napi-win32-arm64-msvc': 0.40.3 - '@ast-grep/napi-win32-ia32-msvc': 0.40.3 - '@ast-grep/napi-win32-x64-msvc': 0.40.3 + '@ast-grep/napi-darwin-arm64': 0.40.4 + '@ast-grep/napi-darwin-x64': 0.40.4 + '@ast-grep/napi-linux-arm64-gnu': 0.40.4 + '@ast-grep/napi-linux-arm64-musl': 0.40.4 + '@ast-grep/napi-linux-x64-gnu': 0.40.4 + '@ast-grep/napi-linux-x64-musl': 0.40.4 + '@ast-grep/napi-win32-arm64-msvc': 0.40.4 + '@ast-grep/napi-win32-ia32-msvc': 0.40.4 + '@ast-grep/napi-win32-x64-msvc': 0.40.4 '@babel/code-frame@7.27.1': dependencies: @@ -9272,39 +9333,39 @@ snapshots: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.28.5 - '@biomejs/biome@2.3.10': + '@biomejs/biome@2.3.11': optionalDependencies: - '@biomejs/cli-darwin-arm64': 2.3.10 - '@biomejs/cli-darwin-x64': 2.3.10 - '@biomejs/cli-linux-arm64': 2.3.10 - '@biomejs/cli-linux-arm64-musl': 2.3.10 - '@biomejs/cli-linux-x64': 2.3.10 - '@biomejs/cli-linux-x64-musl': 2.3.10 - '@biomejs/cli-win32-arm64': 2.3.10 - '@biomejs/cli-win32-x64': 2.3.10 - - '@biomejs/cli-darwin-arm64@2.3.10': + '@biomejs/cli-darwin-arm64': 2.3.11 + '@biomejs/cli-darwin-x64': 2.3.11 + '@biomejs/cli-linux-arm64': 2.3.11 + '@biomejs/cli-linux-arm64-musl': 2.3.11 + '@biomejs/cli-linux-x64': 2.3.11 + '@biomejs/cli-linux-x64-musl': 2.3.11 + '@biomejs/cli-win32-arm64': 2.3.11 + '@biomejs/cli-win32-x64': 2.3.11 + + '@biomejs/cli-darwin-arm64@2.3.11': optional: true - '@biomejs/cli-darwin-x64@2.3.10': + '@biomejs/cli-darwin-x64@2.3.11': optional: true - '@biomejs/cli-linux-arm64-musl@2.3.10': + '@biomejs/cli-linux-arm64-musl@2.3.11': optional: true - '@biomejs/cli-linux-arm64@2.3.10': + '@biomejs/cli-linux-arm64@2.3.11': optional: true - '@biomejs/cli-linux-x64-musl@2.3.10': + '@biomejs/cli-linux-x64-musl@2.3.11': optional: true - '@biomejs/cli-linux-x64@2.3.10': + '@biomejs/cli-linux-x64@2.3.11': optional: true - '@biomejs/cli-win32-arm64@2.3.10': + '@biomejs/cli-win32-arm64@2.3.11': optional: true - '@biomejs/cli-win32-x64@2.3.10': + '@biomejs/cli-win32-x64@2.3.11': optional: true '@braintree/sanitize-url@7.1.1': {} @@ -10724,23 +10785,23 @@ snapshots: core-js: 3.47.0 jiti: 2.6.1 - '@rsbuild/core@1.7.0-beta.1': + '@rsbuild/core@1.7.1': dependencies: - '@rspack/core': 1.7.0-beta.1(@swc/helpers@0.5.18) + '@rspack/core': 1.7.0(@swc/helpers@0.5.18) '@rspack/lite-tapable': 1.1.0 '@swc/helpers': 0.5.18 core-js: 3.47.0 jiti: 2.6.1 - '@rsbuild/core@1.7.0-beta.2': + '@rsbuild/core@1.7.2': dependencies: - '@rspack/core': 1.7.0-beta.1(@swc/helpers@0.5.18) + '@rspack/core': 1.7.1(@swc/helpers@0.5.18) '@rspack/lite-tapable': 1.1.0 '@swc/helpers': 0.5.18 core-js: 3.47.0 jiti: 2.6.1 - '@rsbuild/plugin-node-polyfill@1.4.2(@rsbuild/core@1.6.15)': + '@rsbuild/plugin-node-polyfill@1.4.2(@rsbuild/core@1.7.2)': dependencies: assert: 2.1.0 browserify-zlib: 0.2.0 @@ -10766,7 +10827,7 @@ snapshots: util: 0.12.5 vm-browserify: 1.1.2 optionalDependencies: - '@rsbuild/core': 1.6.15 + '@rsbuild/core': 1.7.2 '@rsbuild/plugin-react@1.4.2(@rsbuild/core@1.6.15)': dependencies: @@ -10776,19 +10837,19 @@ snapshots: transitivePeerDependencies: - webpack-hot-middleware - '@rsbuild/plugin-sass@1.4.0(@rsbuild/core@1.7.0-beta.2)': + '@rsbuild/plugin-sass@1.4.0(@rsbuild/core@1.7.2)': dependencies: - '@rsbuild/core': 1.7.0-beta.2 + '@rsbuild/core': 1.7.2 deepmerge: 4.3.1 loader-utils: 2.0.4 postcss: 8.5.6 reduce-configs: 1.1.1 sass-embedded: 1.93.2 - '@rslib/core@0.19.0(@microsoft/api-extractor@7.55.2(@types/node@20.19.27))(typescript@5.9.3)': + '@rslib/core@0.19.1(@microsoft/api-extractor@7.55.2(@types/node@20.19.27))(typescript@5.9.3)': dependencies: - '@rsbuild/core': 1.7.0-beta.2 - rsbuild-plugin-dts: 0.19.0(@microsoft/api-extractor@7.55.2(@types/node@20.19.27))(@rsbuild/core@1.7.0-beta.2)(typescript@5.9.3) + '@rsbuild/core': 1.7.2 + rsbuild-plugin-dts: 0.19.1(@microsoft/api-extractor@7.55.2(@types/node@20.19.27))(@rsbuild/core@1.7.2)(typescript@5.9.3) optionalDependencies: '@microsoft/api-extractor': 7.55.2(@types/node@20.19.27) typescript: 5.9.3 @@ -10825,37 +10886,55 @@ snapshots: '@rspack/binding-darwin-arm64@1.6.8': optional: true - '@rspack/binding-darwin-arm64@1.7.0-beta.1': + '@rspack/binding-darwin-arm64@1.7.0': + optional: true + + '@rspack/binding-darwin-arm64@1.7.1': optional: true '@rspack/binding-darwin-x64@1.6.8': optional: true - '@rspack/binding-darwin-x64@1.7.0-beta.1': + '@rspack/binding-darwin-x64@1.7.0': + optional: true + + '@rspack/binding-darwin-x64@1.7.1': optional: true '@rspack/binding-linux-arm64-gnu@1.6.8': optional: true - '@rspack/binding-linux-arm64-gnu@1.7.0-beta.1': + '@rspack/binding-linux-arm64-gnu@1.7.0': + optional: true + + '@rspack/binding-linux-arm64-gnu@1.7.1': optional: true '@rspack/binding-linux-arm64-musl@1.6.8': optional: true - '@rspack/binding-linux-arm64-musl@1.7.0-beta.1': + '@rspack/binding-linux-arm64-musl@1.7.0': + optional: true + + '@rspack/binding-linux-arm64-musl@1.7.1': optional: true '@rspack/binding-linux-x64-gnu@1.6.8': optional: true - '@rspack/binding-linux-x64-gnu@1.7.0-beta.1': + '@rspack/binding-linux-x64-gnu@1.7.0': + optional: true + + '@rspack/binding-linux-x64-gnu@1.7.1': optional: true '@rspack/binding-linux-x64-musl@1.6.8': optional: true - '@rspack/binding-linux-x64-musl@1.7.0-beta.1': + '@rspack/binding-linux-x64-musl@1.7.0': + optional: true + + '@rspack/binding-linux-x64-musl@1.7.1': optional: true '@rspack/binding-wasm32-wasi@1.6.8': @@ -10863,7 +10942,12 @@ snapshots: '@napi-rs/wasm-runtime': 1.0.7 optional: true - '@rspack/binding-wasm32-wasi@1.7.0-beta.1': + '@rspack/binding-wasm32-wasi@1.7.0': + dependencies: + '@napi-rs/wasm-runtime': 1.0.7 + optional: true + + '@rspack/binding-wasm32-wasi@1.7.1': dependencies: '@napi-rs/wasm-runtime': 1.0.7 optional: true @@ -10871,19 +10955,28 @@ snapshots: '@rspack/binding-win32-arm64-msvc@1.6.8': optional: true - '@rspack/binding-win32-arm64-msvc@1.7.0-beta.1': + '@rspack/binding-win32-arm64-msvc@1.7.0': + optional: true + + '@rspack/binding-win32-arm64-msvc@1.7.1': optional: true '@rspack/binding-win32-ia32-msvc@1.6.8': optional: true - '@rspack/binding-win32-ia32-msvc@1.7.0-beta.1': + '@rspack/binding-win32-ia32-msvc@1.7.0': + optional: true + + '@rspack/binding-win32-ia32-msvc@1.7.1': optional: true '@rspack/binding-win32-x64-msvc@1.6.8': optional: true - '@rspack/binding-win32-x64-msvc@1.7.0-beta.1': + '@rspack/binding-win32-x64-msvc@1.7.0': + optional: true + + '@rspack/binding-win32-x64-msvc@1.7.1': optional: true '@rspack/binding@1.6.8': @@ -10899,18 +10992,31 @@ snapshots: '@rspack/binding-win32-ia32-msvc': 1.6.8 '@rspack/binding-win32-x64-msvc': 1.6.8 - '@rspack/binding@1.7.0-beta.1': + '@rspack/binding@1.7.0': + optionalDependencies: + '@rspack/binding-darwin-arm64': 1.7.0 + '@rspack/binding-darwin-x64': 1.7.0 + '@rspack/binding-linux-arm64-gnu': 1.7.0 + '@rspack/binding-linux-arm64-musl': 1.7.0 + '@rspack/binding-linux-x64-gnu': 1.7.0 + '@rspack/binding-linux-x64-musl': 1.7.0 + '@rspack/binding-wasm32-wasi': 1.7.0 + '@rspack/binding-win32-arm64-msvc': 1.7.0 + '@rspack/binding-win32-ia32-msvc': 1.7.0 + '@rspack/binding-win32-x64-msvc': 1.7.0 + + '@rspack/binding@1.7.1': optionalDependencies: - '@rspack/binding-darwin-arm64': 1.7.0-beta.1 - '@rspack/binding-darwin-x64': 1.7.0-beta.1 - '@rspack/binding-linux-arm64-gnu': 1.7.0-beta.1 - '@rspack/binding-linux-arm64-musl': 1.7.0-beta.1 - '@rspack/binding-linux-x64-gnu': 1.7.0-beta.1 - '@rspack/binding-linux-x64-musl': 1.7.0-beta.1 - '@rspack/binding-wasm32-wasi': 1.7.0-beta.1 - '@rspack/binding-win32-arm64-msvc': 1.7.0-beta.1 - '@rspack/binding-win32-ia32-msvc': 1.7.0-beta.1 - '@rspack/binding-win32-x64-msvc': 1.7.0-beta.1 + '@rspack/binding-darwin-arm64': 1.7.1 + '@rspack/binding-darwin-x64': 1.7.1 + '@rspack/binding-linux-arm64-gnu': 1.7.1 + '@rspack/binding-linux-arm64-musl': 1.7.1 + '@rspack/binding-linux-x64-gnu': 1.7.1 + '@rspack/binding-linux-x64-musl': 1.7.1 + '@rspack/binding-wasm32-wasi': 1.7.1 + '@rspack/binding-win32-arm64-msvc': 1.7.1 + '@rspack/binding-win32-ia32-msvc': 1.7.1 + '@rspack/binding-win32-x64-msvc': 1.7.1 '@rspack/core@1.6.8(@swc/helpers@0.5.18)': dependencies: @@ -10920,10 +11026,18 @@ snapshots: optionalDependencies: '@swc/helpers': 0.5.18 - '@rspack/core@1.7.0-beta.1(@swc/helpers@0.5.18)': + '@rspack/core@1.7.0(@swc/helpers@0.5.18)': dependencies: - '@module-federation/runtime-tools': 0.21.6 - '@rspack/binding': 1.7.0-beta.1 + '@module-federation/runtime-tools': 0.22.0 + '@rspack/binding': 1.7.0 + '@rspack/lite-tapable': 1.1.0 + optionalDependencies: + '@swc/helpers': 0.5.18 + + '@rspack/core@1.7.1(@swc/helpers@0.5.18)': + dependencies: + '@module-federation/runtime-tools': 0.22.0 + '@rspack/binding': 1.7.1 '@rspack/lite-tapable': 1.1.0 optionalDependencies: '@swc/helpers': 0.5.18 @@ -11120,9 +11234,9 @@ snapshots: - react - react-dom - '@rstest/core@0.7.7(jsdom@26.1.0)': + '@rstest/core@0.7.8(jsdom@26.1.0)': dependencies: - '@rsbuild/core': 1.7.0-beta.1 + '@rsbuild/core': 1.7.1 '@types/chai': 5.2.3 tinypool: 1.1.1 optionalDependencies: @@ -15966,21 +16080,21 @@ snapshots: rrweb-cssom@0.8.0: {} - rsbuild-plugin-dts@0.19.0(@microsoft/api-extractor@7.55.2(@types/node@20.19.27))(@rsbuild/core@1.7.0-beta.2)(typescript@5.9.3): + rsbuild-plugin-dts@0.19.1(@microsoft/api-extractor@7.55.2(@types/node@20.19.27))(@rsbuild/core@1.7.2)(typescript@5.9.3): dependencies: '@ast-grep/napi': 0.37.0 - '@rsbuild/core': 1.7.0-beta.2 + '@rsbuild/core': 1.7.2 optionalDependencies: '@microsoft/api-extractor': 7.55.2(@types/node@20.19.27) typescript: 5.9.3 - rsbuild-plugin-google-analytics@1.0.4(@rsbuild/core@1.7.0-beta.2): + rsbuild-plugin-google-analytics@1.0.4(@rsbuild/core@1.7.2): optionalDependencies: - '@rsbuild/core': 1.7.0-beta.2 + '@rsbuild/core': 1.7.2 - rsbuild-plugin-open-graph@1.1.0(@rsbuild/core@1.7.0-beta.2): + rsbuild-plugin-open-graph@1.1.0(@rsbuild/core@1.7.2): optionalDependencies: - '@rsbuild/core': 1.7.0-beta.2 + '@rsbuild/core': 1.7.2 rspress-plugin-font-open-sans@1.0.3(@rspress/core@2.0.0-rc.4(@types/react@19.2.7)): dependencies: diff --git a/tests/rspack-test/package.json b/tests/rspack-test/package.json index 0eb43a100395..7b0238c94597 100644 --- a/tests/rspack-test/package.json +++ b/tests/rspack-test/package.json @@ -19,7 +19,7 @@ "@rspack/plugin-preact-refresh": "1.1.4", "@rspack/plugin-react-refresh": "^1.5.3", "@rspack/test-tools": "workspace:*", - "@rstest/core": "^0.7.7", + "@rstest/core": "^0.7.8", "@swc/helpers": "0.5.18", "@swc/plugin-remove-console": "^12.1.0", "@types/babel__generator": "7.27.0", From ece0fee674b2f2b88f4da9b3920b4b49de9ea5d8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 7 Jan 2026 02:22:12 +0000 Subject: [PATCH 17/87] chore(deps): update patch crates (#12646) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 162 ++++++++++++++++++++++++++--------------------------- Cargo.toml | 14 ++--- 2 files changed, 88 insertions(+), 88 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a57ba5c3bb5a..17bad5f159aa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -191,7 +191,7 @@ checksum = "2eb025ef00a6da925cf40870b9c8d008526b6004ece399cb0974209720f0b194" dependencies = [ "quote", "swc_macros_common", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -202,7 +202,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -213,7 +213,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -230,7 +230,7 @@ checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -455,7 +455,7 @@ checksum = "523363cbe1df49b68215efdf500b103ac3b0fb4836aed6d15689a076eadb8fff" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -667,9 +667,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.53" +version = "4.5.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e340e012a1bf4935f5282ed1436d1489548e8f72308207ea5df0e23d2d03f8" +checksum = "c6e6ff9dcd79cff5cd969a17a545d79e84ab086e444102a591e288a8aa3ce394" dependencies = [ "clap_builder", "clap_derive", @@ -677,9 +677,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.53" +version = "4.5.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d76b5d13eaa18c901fd2f7fca939fefe3a0727a953561fefdf3b2922b8569d00" +checksum = "fa42cf4d2b7a41bc8f663a7cab4031ebafa1bf3875705bfaf8466dc60ab52c00" dependencies = [ "anstream", "anstyle", @@ -696,7 +696,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -1103,7 +1103,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -1153,7 +1153,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -1164,7 +1164,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -1247,7 +1247,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -1257,7 +1257,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ "derive_builder_core", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -1277,7 +1277,7 @@ checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", "unicode-xid", ] @@ -1305,7 +1305,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -1403,7 +1403,7 @@ checksum = "1ccd72f8e71e242f71705868f5478fe7592a6e194c06330d8732421ffdbc554c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -1531,7 +1531,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5ff35a391aef949120a0340d690269b3d9f63460a6106e99bd07b961f345ea9" dependencies = [ "swc_macros_common", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -1616,7 +1616,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -1979,7 +1979,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -2122,7 +2122,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -2133,7 +2133,7 @@ checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" dependencies = [ "hermit-abi 0.5.2", "libc", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -2476,7 +2476,7 @@ checksum = "db5b29714e950dbb20d5e6f74f9dcec4edbcc1067bb7f8ed198c097b8c1a818b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -2549,7 +2549,7 @@ checksum = "1bb5c1d8184f13f7d0ccbeeca0def2f9a181bce2624302793005f5ca8aa62e5e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -2587,7 +2587,7 @@ dependencies = [ "napi-derive-backend", "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -2600,7 +2600,7 @@ dependencies = [ "proc-macro2", "quote", "semver", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -2688,7 +2688,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -2973,7 +2973,7 @@ dependencies = [ "phf_shared", "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -3091,9 +3091,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.104" +version = "1.0.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9695f8df41bb4f3d222c95a67532365f569318332d03d5f3f67f37b20e6ebdf0" +checksum = "535d180e0ecab6268a3e718bb9fd44db66bbbc256257165fc699dadf70d16fe7" dependencies = [ "unicode-ident", ] @@ -3118,7 +3118,7 @@ dependencies = [ "itertools 0.14.0", "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -3167,7 +3167,7 @@ checksum = "ca414edb151b4c8d125c12566ab0d74dc9cdba36fb80eb7b848c15f495fd32d1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -3190,14 +3190,14 @@ checksum = "938543690519c20c3a480d20a8efcc8e69abeb44093ab1df4e7c1f81f26c677a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] name = "quote" -version = "1.0.42" +version = "1.0.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" +checksum = "dc74d9a594b72ae6656596548f56f667211f8a97b3d4c3d467150794690dc40a" dependencies = [ "proc-macro2", ] @@ -3315,7 +3315,7 @@ checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -3445,7 +3445,7 @@ checksum = "09cb82b74b4810f07e460852c32f522e979787691b0b7b7439fe473e49d49b2f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -3531,7 +3531,7 @@ checksum = "125d6c4fea52a20e2baaa381c122e111a825ac4c3cccdbb50605805f025d7197" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -3696,7 +3696,7 @@ dependencies = [ "proc-macro2", "quote", "rspack_binding_builder", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -3755,7 +3755,7 @@ name = "rspack_cacheable_macros" version = "0.7.1" dependencies = [ "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -4094,7 +4094,7 @@ version = "0.7.1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -4133,7 +4133,7 @@ version = "0.7.1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -5332,14 +5332,14 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] name = "serde_json" -version = "1.0.148" +version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3084b546a1dd6289475996f182a22aba973866ea8e8b02c51d9f46b1336a22da" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ "indexmap", "itoa", @@ -5547,7 +5547,7 @@ checksum = "710e9696ef338691287aeb937ee6ffe60022f579d3c8d2fd9d58973a9a10a466" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -5592,7 +5592,7 @@ checksum = "ae36a4951ca7bd1cfd991c241584a9824a70f6aff1e7d4f693fb3f2465e4030e" dependencies = [ "quote", "swc_macros_common", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -5806,7 +5806,7 @@ dependencies = [ "proc-macro2", "quote", "swc_macros_common", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -5891,7 +5891,7 @@ checksum = "e276dc62c0a2625a560397827989c82a93fd545fcf6f7faec0935a82cc4ddbb8" dependencies = [ "proc-macro2", "swc_macros_common", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -6214,7 +6214,7 @@ dependencies = [ "swc_ecma_ast", "swc_ecma_parser", "swc_macros_common", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -6327,7 +6327,7 @@ dependencies = [ "proc-macro2", "quote", "swc_macros_common", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -6502,7 +6502,7 @@ checksum = "c16ce73424a6316e95e09065ba6a207eba7765496fed113702278b7711d4b632" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -6526,7 +6526,7 @@ checksum = "b45db26cc495a8695f8034277ceb6a44e52eb702d6c64ea5c7156dd673ea8c98" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -6629,7 +6629,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f98ef1f87379c816ba7d22351c9fc993af38b034bce4da3286cfe4b17e7ec9e2" dependencies = [ "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -6705,7 +6705,7 @@ checksum = "aae1efbaa74943dc5ad2a2fb16cbd78b77d7e4d63188f3c5b4df2b4dcd2faaae" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -6791,7 +6791,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfd2b4b0adb82e36f2ac688d00a6a67132c7f4170c772617516793a701be89e8" dependencies = [ "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -6829,9 +6829,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.112" +version = "2.0.113" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21f182278bf2d2bcb3c88b1b08a37df029d71ce3d3ae26168e3c653b213b99d4" +checksum = "678faa00651c9eb72dd2020cbdf275d92eccb2400d568e419efdd64838145cb4" dependencies = [ "proc-macro2", "quote", @@ -6846,7 +6846,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -6893,7 +6893,7 @@ dependencies = [ "getrandom 0.3.2", "once_cell", "rustix 1.0.8", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -6951,7 +6951,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -6962,7 +6962,7 @@ checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -7052,7 +7052,7 @@ checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -7154,7 +7154,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -7211,9 +7211,9 @@ dependencies = [ [[package]] name = "tracy-client" -version = "0.18.3" +version = "0.18.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91d722a05fe49b31fef971c4732a7d4aa6a18283d9ba46abddab35f484872947" +checksum = "a4f6fc3baeac5d86ab90c772e9e30620fc653bf1864295029921a15ef478e6a5" dependencies = [ "loom", "once_cell", @@ -7319,9 +7319,9 @@ checksum = "81e544489bf3d8ef66c953931f56617f423cd4b5494be343d9b9d3dda037b9a3" [[package]] name = "url" -version = "2.5.7" +version = "2.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" dependencies = [ "form_urlencoded", "idna", @@ -7512,7 +7512,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", "wasm-bindgen-shared", ] @@ -7534,7 +7534,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -7755,7 +7755,7 @@ checksum = "342b0466f92b7217a4de9e114175fedee1907028567d2548bcd42f71a8b5b016" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -7819,7 +7819,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", "witx", ] @@ -7831,7 +7831,7 @@ checksum = "f5872fbe512b73acd514e7ef5bd5aee0ff951a12c1fed0293e1f7992de30df9f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", "wiggle-generate", ] @@ -7949,7 +7949,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -7960,7 +7960,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -8280,7 +8280,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", "synstructure", ] @@ -8311,7 +8311,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -8322,7 +8322,7 @@ checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -8342,7 +8342,7 @@ checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", "synstructure", ] @@ -8365,7 +8365,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index a653b3347c6b..20988b93f7a6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,7 +30,7 @@ bytes = { version = "1.10.0", default-features = false } camino = { version = "1.2.2", default-features = false } cargo_toml = { version = "0.21.0", default-features = false } cfg-if = { version = "1.0.4", default-features = false } -clap = { version = "4.5.53", default-features = false } +clap = { version = "4.5.54", default-features = false } color-backtrace = { version = "0.7.2", default-features = false, features = ["use-backtrace-crate"] } concat-string = { version = "1.0.1", default-features = false } cow-utils = { version = "0.1.3", default-features = false } @@ -73,9 +73,9 @@ paste = { version = "1.0.15", default-features = false } path-clean = { version = "1.0.1", default-features = false } pathdiff = { version = "0.2.3", default-features = false } pretty_assertions = { version = "1.4.1", default-features = false, features = ["std"] } -proc-macro2 = { version = "1.0.104", default-features = false } +proc-macro2 = { version = "1.0.105", default-features = false } prost = { version = "0.13", default-features = false } -quote = { version = "1.0.42", default-features = false } +quote = { version = "1.0.43", default-features = false } rayon = { version = "1.11.0", default-features = false } regex = { version = "1.12.2", default-features = false } regex-syntax = { version = "0.8.8", default-features = false, features = ["std"] } @@ -87,7 +87,7 @@ rustc-hash = { version = "2.1.1", default-features = false } ryu-js = { version = "1.0.2", default-features = false } scopeguard = { version = "1.2.0", default-features = false } serde = { version = "1.0.228", default-features = false, features = ["derive"] } -serde_json = { version = "1.0.148", default-features = false, features = ["std"] } +serde_json = { version = "1.0.149", default-features = false, features = ["std"] } sftrace-setup = { version = "0.1.2", default-features = false } sha2 = { version = "0.10.9", default-features = false } signal-hook = { version = "0.3.18", default-features = false, features = ["iterator"] } @@ -95,7 +95,7 @@ simd-json = { version = "0.17.0", default-features = false } smol_str = { version = "0.3.4", default-features = false } stacker = { version = "0.1.22", default-features = false } sugar_path = { version = "1.2.1", default-features = false, features = ["cached_current_dir"] } -syn = { version = "2.0.112", default-features = false } +syn = { version = "2.0.113", default-features = false } termcolor = { version = "1.4.1", default-features = false } textwrap = { version = "0.16.1", default-features = false } thread_local = { version = "1.1.9", default-features = false } @@ -106,7 +106,7 @@ tracing-subscriber = { version = "0.3.22", default-features = false, features = trybuild = { version = "1.0.114", default-features = false, features = ["diff"] } unicase = { version = "2.8.1", default-features = false } unicode-width = { version = "0.2.2", default-features = false } -url = { version = "2.5.7", default-features = false } +url = { version = "2.5.8", default-features = false } urlencoding = { version = "2.1.3", default-features = false } ustr = { package = "ustr-fxhash", version = "1.0.1", default-features = false } wasmparser = { version = "0.222.0", default-features = false } @@ -150,7 +150,7 @@ swc_experimental_ecma_parser = { version = "0.4.0", default-features = false } swc_experimental_ecma_semantic = { version = "0.4.0", default-features = false } rspack_dojang = { version = "0.1.11", default-features = false } -tracy-client = { version = "=0.18.3", default-features = false, features = [ +tracy-client = { version = "=0.18.4", default-features = false, features = [ "enable", "sampling", "demangle", From edce5bd297cd1a902d2f9261acdd8385ffdb286b Mon Sep 17 00:00:00 2001 From: harpsealjs Date: Wed, 7 Jan 2026 11:33:46 +0800 Subject: [PATCH 18/87] chore: run ci/eco-ci/eco-benchmark on v2 branch (#12650) --- .github/workflows/ci-diff.yml | 1 + .github/workflows/ci-lint.yaml | 1 + .github/workflows/ci-rust.yaml | 1 + .github/workflows/ci.yml | 3 ++- .github/workflows/ecosystem-benchmark.yml | 1 + .github/workflows/ecosystem-ci.yml | 1 + 6 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci-diff.yml b/.github/workflows/ci-diff.yml index d74691858933..2d51d7912bec 100644 --- a/.github/workflows/ci-diff.yml +++ b/.github/workflows/ci-diff.yml @@ -11,6 +11,7 @@ on: push: branches: - main + - v2 # Ignore md files in push to skip workflow when only documentation changes paths-ignore: - '**/*.md' diff --git a/.github/workflows/ci-lint.yaml b/.github/workflows/ci-lint.yaml index 405aba004889..007d58933524 100644 --- a/.github/workflows/ci-lint.yaml +++ b/.github/workflows/ci-lint.yaml @@ -9,6 +9,7 @@ on: push: branches: - main + - v2 paths-ignore: - '**/*.md' - 'website/**' diff --git a/.github/workflows/ci-rust.yaml b/.github/workflows/ci-rust.yaml index 632e5d93fcb4..a49675372106 100644 --- a/.github/workflows/ci-rust.yaml +++ b/.github/workflows/ci-rust.yaml @@ -9,6 +9,7 @@ on: push: branches: - main + - v2 paths: - '.github/workflows/**' - 'crates/**' diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 054afe635464..d9a5c9043cfb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,6 +15,7 @@ on: push: branches: - main + - v2 paths-ignore: - '**/*.md' - 'website/**' @@ -23,7 +24,7 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }} - cancel-in-progress: ${{ github.ref_name != 'main' }} + cancel-in-progress: ${{ github.ref_name != 'main' && github.ref_name != 'v2' }} permissions: # Allow commenting on issues for `reusable-build.yml` diff --git a/.github/workflows/ecosystem-benchmark.yml b/.github/workflows/ecosystem-benchmark.yml index 0080fbd9434e..4f58fd9da3dd 100644 --- a/.github/workflows/ecosystem-benchmark.yml +++ b/.github/workflows/ecosystem-benchmark.yml @@ -10,6 +10,7 @@ on: push: branches: - main + - v2 paths-ignore: - '**/*.md' - 'website/**' diff --git a/.github/workflows/ecosystem-ci.yml b/.github/workflows/ecosystem-ci.yml index bc1fcbe0d67b..9923c9968947 100644 --- a/.github/workflows/ecosystem-ci.yml +++ b/.github/workflows/ecosystem-ci.yml @@ -33,6 +33,7 @@ on: push: branches: - main + - v2 paths-ignore: - '**/*.md' - 'website/**' From 44a7564f58f308099830525db95c35c4f0145c7a Mon Sep 17 00:00:00 2001 From: hardfist Date: Wed, 7 Jan 2026 11:35:08 +0800 Subject: [PATCH 19/87] fix: report error when access module_graph in loader (#12639) * fix: report error when access module_graph in loader * Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- crates/rspack_binding_api/src/module_graph.rs | 5 +++++ .../access-module-graph/access-mg-loader.js | 7 +++++++ .../loader/access-module-graph/errors.js | 1 + .../loader/access-module-graph/index.js | 0 .../loader/access-module-graph/rspack.config.js | 16 ++++++++++++++++ 5 files changed, 29 insertions(+) create mode 100644 tests/rspack-test/configCases/loader/access-module-graph/access-mg-loader.js create mode 100644 tests/rspack-test/configCases/loader/access-module-graph/errors.js create mode 100644 tests/rspack-test/configCases/loader/access-module-graph/index.js create mode 100644 tests/rspack-test/configCases/loader/access-module-graph/rspack.config.js diff --git a/crates/rspack_binding_api/src/module_graph.rs b/crates/rspack_binding_api/src/module_graph.rs index f39fa8cb4755..ab1d1cf853b3 100644 --- a/crates/rspack_binding_api/src/module_graph.rs +++ b/crates/rspack_binding_api/src/module_graph.rs @@ -28,6 +28,11 @@ impl JsModuleGraph { fn as_ref(&self) -> napi::Result<(&'static Compilation, &'static ModuleGraph)> { let compilation = unsafe { self.compilation.as_ref() }; + if compilation.build_module_graph_artifact.is_none() { + return Err(napi::Error::from_reason( + "ModuleGraph is not available during module graph building phase".to_string(), + )); + } let module_graph = compilation.get_module_graph(); Ok((compilation, module_graph)) diff --git a/tests/rspack-test/configCases/loader/access-module-graph/access-mg-loader.js b/tests/rspack-test/configCases/loader/access-module-graph/access-mg-loader.js new file mode 100644 index 000000000000..85c54827a861 --- /dev/null +++ b/tests/rspack-test/configCases/loader/access-module-graph/access-mg-loader.js @@ -0,0 +1,7 @@ +module.exports = function loader(content) { + + const moduleGraph = this._compilation.moduleGraph; + let issuer = moduleGraph.getIssuer(this._module); + console.log(issuer); + return content; +} \ No newline at end of file diff --git a/tests/rspack-test/configCases/loader/access-module-graph/errors.js b/tests/rspack-test/configCases/loader/access-module-graph/errors.js new file mode 100644 index 000000000000..3233ccca0e74 --- /dev/null +++ b/tests/rspack-test/configCases/loader/access-module-graph/errors.js @@ -0,0 +1 @@ +module.exports = [/ModuleGraph is not available during module graph building phase/] \ No newline at end of file diff --git a/tests/rspack-test/configCases/loader/access-module-graph/index.js b/tests/rspack-test/configCases/loader/access-module-graph/index.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/tests/rspack-test/configCases/loader/access-module-graph/rspack.config.js b/tests/rspack-test/configCases/loader/access-module-graph/rspack.config.js new file mode 100644 index 000000000000..3208e94d7e20 --- /dev/null +++ b/tests/rspack-test/configCases/loader/access-module-graph/rspack.config.js @@ -0,0 +1,16 @@ + +/** + * @type {import('@rspack/core').RspackOptions} + */ +module.exports = { + context: __dirname, + entry: './index.js', + module: { + rules: [ + { + test: /index.js/, + use: [{ loader: "./access-mg-loader.js" }] + } + ] + } +}; From 25a4021b5ffaa3acf2430f71ffe5f30a9fa20892 Mon Sep 17 00:00:00 2001 From: Max Date: Wed, 7 Jan 2026 11:44:24 +0800 Subject: [PATCH 20/87] feat(rstest): add preserveNewUrl option to keep new URL untouched (#12632) * feat(rstest): add preserveNewUrl option to keep new URL untouched * fix: format Rust code with rustfmt --- crates/node_binding/napi-binding.d.ts | 1 + crates/rspack_binding_api/src/rstest.rs | 6 ++ crates/rspack_plugin_rstest/src/lib.rs | 1 + crates/rspack_plugin_rstest/src/plugin.rs | 11 ++++ .../src/url_dependency.rs | 57 ++++++++++++++++++ .../configCases/rstest/new-url-wasm/index.js | 4 ++ .../rstest/new-url-wasm/rspack.config.js | 38 ++++++++++++ .../rstest/new-url-wasm/test.config.js | 7 +++ .../configCases/rstest/new-url-wasm/test.js | 12 ++++ .../configCases/rstest/new-url-wasm/test.png | 1 + .../configCases/rstest/new-url-wasm/test.wasm | Bin 0 -> 8 bytes 11 files changed, 138 insertions(+) create mode 100644 crates/rspack_plugin_rstest/src/url_dependency.rs create mode 100644 tests/rspack-test/configCases/rstest/new-url-wasm/index.js create mode 100644 tests/rspack-test/configCases/rstest/new-url-wasm/rspack.config.js create mode 100644 tests/rspack-test/configCases/rstest/new-url-wasm/test.config.js create mode 100644 tests/rspack-test/configCases/rstest/new-url-wasm/test.js create mode 100644 tests/rspack-test/configCases/rstest/new-url-wasm/test.png create mode 100644 tests/rspack-test/configCases/rstest/new-url-wasm/test.wasm diff --git a/crates/node_binding/napi-binding.d.ts b/crates/node_binding/napi-binding.d.ts index 5a42f71f69d1..7125ee39f0fb 100644 --- a/crates/node_binding/napi-binding.d.ts +++ b/crates/node_binding/napi-binding.d.ts @@ -2790,6 +2790,7 @@ export interface RawRstestPluginOptions { importMetaPathName: boolean hoistMockModule: boolean manualMockRoot: string + preserveNewUrl?: Array } export interface RawRuleSetCondition { diff --git a/crates/rspack_binding_api/src/rstest.rs b/crates/rspack_binding_api/src/rstest.rs index 09f29968373b..c4c2411880a1 100644 --- a/crates/rspack_binding_api/src/rstest.rs +++ b/crates/rspack_binding_api/src/rstest.rs @@ -12,6 +12,11 @@ pub struct RawRstestPluginOptions { pub hoist_mock_module: bool, // Root of the manual mock directory. pub manual_mock_root: String, + // Preserve `new URL("*.", import.meta.url)` expressions for specified extensions + // instead of transforming them to asset imports. + // This allows rstest to dynamically load modules (e.g., wasm) at runtime. + // Example: [".wasm"] to preserve wasm URL expressions. + pub preserve_new_url: Option>, } impl From for RstestPluginOptions { @@ -21,6 +26,7 @@ impl From for RstestPluginOptions { hoist_mock_module: value.hoist_mock_module, import_meta_path_name: value.import_meta_path_name, manual_mock_root: value.manual_mock_root, + preserve_new_url: value.preserve_new_url.unwrap_or_default(), } } } diff --git a/crates/rspack_plugin_rstest/src/lib.rs b/crates/rspack_plugin_rstest/src/lib.rs index 3486ac76e143..3d19deb29baa 100644 --- a/crates/rspack_plugin_rstest/src/lib.rs +++ b/crates/rspack_plugin_rstest/src/lib.rs @@ -4,5 +4,6 @@ mod mock_module_id_dependency; mod module_path_name_dependency; mod parser_plugin; mod plugin; +mod url_dependency; pub use plugin::*; diff --git a/crates/rspack_plugin_rstest/src/plugin.rs b/crates/rspack_plugin_rstest/src/plugin.rs index e371cf39c85b..9733dcfba2b4 100644 --- a/crates/rspack_plugin_rstest/src/plugin.rs +++ b/crates/rspack_plugin_rstest/src/plugin.rs @@ -19,6 +19,7 @@ use crate::{ mock_method_dependency::MockMethodDependencyTemplate, mock_module_id_dependency::MockModuleIdDependencyTemplate, module_path_name_dependency::ModulePathNameDependencyTemplate, parser_plugin::RstestParserPlugin, + url_dependency::RstestUrlDependencyTemplate, }; #[derive(Debug)] @@ -27,6 +28,7 @@ pub struct RstestPluginOptions { pub hoist_mock_module: bool, pub import_meta_path_name: bool, pub manual_mock_root: String, + pub preserve_new_url: Vec, } #[derive(Debug)] @@ -148,6 +150,15 @@ async fn compilation_stage_9999( Arc::new(ImportDependencyTemplate::default()), ); + if !self.options.preserve_new_url.is_empty() { + compilation.set_dependency_template( + RstestUrlDependencyTemplate::template_type(), + Arc::new(RstestUrlDependencyTemplate::new( + self.options.preserve_new_url.clone(), + )), + ); + } + Ok(()) } diff --git a/crates/rspack_plugin_rstest/src/url_dependency.rs b/crates/rspack_plugin_rstest/src/url_dependency.rs new file mode 100644 index 000000000000..ebaad46ed832 --- /dev/null +++ b/crates/rspack_plugin_rstest/src/url_dependency.rs @@ -0,0 +1,57 @@ +use rspack_cacheable::cacheable; +use rspack_core::{ + DependencyCodeGeneration, DependencyTemplate, DependencyTemplateType, DependencyType, + ModuleDependency, TemplateContext, TemplateReplaceSource, +}; +use rspack_plugin_javascript::dependency::{URLDependency, URLDependencyTemplate}; + +#[cacheable] +#[derive(Debug, Default)] +pub struct RstestUrlDependencyTemplate { + /// List of extensions to preserve (e.g., [".wasm", ".node"]) + preserve_extensions: Vec, +} + +impl RstestUrlDependencyTemplate { + pub fn new(preserve_extensions: Vec) -> Self { + Self { + preserve_extensions, + } + } + + pub fn template_type() -> DependencyTemplateType { + DependencyTemplateType::Dependency(DependencyType::NewUrl) + } +} + +impl DependencyTemplate for RstestUrlDependencyTemplate { + fn render( + &self, + dep: &dyn DependencyCodeGeneration, + source: &mut TemplateReplaceSource, + code_generatable_context: &mut TemplateContext, + ) { + let dep = dep + .as_any() + .downcast_ref::() + .expect("RstestUrlDependencyTemplate should be used for URLDependency"); + + // Strip query string and fragment from request path before checking extension + let request = dep.request(); + let request_path = request.split(&['?', '#'][..]).next().unwrap_or(request); + + let should_preserve = request_path.rsplit('.').next().is_some_and(|ext| { + self.preserve_extensions.iter().any(|preserve_ext| { + // Support both ".ext" and "ext" formats + let preserve_ext = preserve_ext.trim_start_matches('.'); + ext.eq_ignore_ascii_case(preserve_ext) + }) + }); + + if should_preserve { + return; + } + + URLDependencyTemplate::default().render(dep, source, code_generatable_context); + } +} diff --git a/tests/rspack-test/configCases/rstest/new-url-wasm/index.js b/tests/rspack-test/configCases/rstest/new-url-wasm/index.js new file mode 100644 index 000000000000..55d37cbff3c4 --- /dev/null +++ b/tests/rspack-test/configCases/rstest/new-url-wasm/index.js @@ -0,0 +1,4 @@ +const wasmUrl = new URL("./test.wasm", import.meta.url); +const pngUrl = new URL("./test.png", import.meta.url); + +console.log(wasmUrl, pngUrl); diff --git a/tests/rspack-test/configCases/rstest/new-url-wasm/rspack.config.js b/tests/rspack-test/configCases/rstest/new-url-wasm/rspack.config.js new file mode 100644 index 000000000000..96bdaf9c3eed --- /dev/null +++ b/tests/rspack-test/configCases/rstest/new-url-wasm/rspack.config.js @@ -0,0 +1,38 @@ +const { + experiments: { RstestPlugin } +} = require("@rspack/core"); + +/** @type {import("@rspack/core").Configuration} */ +module.exports = [ + { + entry: "./index.js", + target: "node", + node: { + __filename: false, + __dirname: false + }, + output: { + filename: "bundle.js" + }, + plugins: [ + new RstestPlugin({ + injectModulePathName: true, + hoistMockModule: true, + importMetaPathName: true, + manualMockRoot: __dirname, + preserveNewUrl: [".wasm"] + }) + ] + }, + { + entry: { + main: "./test.js" + }, + output: { + filename: "[name].js" + }, + externalsPresets: { + node: true + } + } +]; diff --git a/tests/rspack-test/configCases/rstest/new-url-wasm/test.config.js b/tests/rspack-test/configCases/rstest/new-url-wasm/test.config.js new file mode 100644 index 000000000000..964d44756a72 --- /dev/null +++ b/tests/rspack-test/configCases/rstest/new-url-wasm/test.config.js @@ -0,0 +1,7 @@ +/** @type {import("../../../..").TConfigCaseConfig} */ +module.exports = { + findBundle: function (i) { + if (i === 0) return ["main.js"]; + return ["main.js"]; + } +}; diff --git a/tests/rspack-test/configCases/rstest/new-url-wasm/test.js b/tests/rspack-test/configCases/rstest/new-url-wasm/test.js new file mode 100644 index 000000000000..054d0862dadc --- /dev/null +++ b/tests/rspack-test/configCases/rstest/new-url-wasm/test.js @@ -0,0 +1,12 @@ +const fs = require("fs"); +const path = require("path"); + +const content = fs.readFileSync(path.resolve(__dirname, "bundle.js"), "utf-8"); + +it("should keep wasm new URL untouched in rstest", () => { + expect(content).toContain('new URL("./test.wasm", import.meta.url)'); +}); + +it("should keep non-wasm new URL behavior", () => { + expect(content).toContain("/* asset import */"); +}); diff --git a/tests/rspack-test/configCases/rstest/new-url-wasm/test.png b/tests/rspack-test/configCases/rstest/new-url-wasm/test.png new file mode 100644 index 000000000000..19b11ce57205 --- /dev/null +++ b/tests/rspack-test/configCases/rstest/new-url-wasm/test.png @@ -0,0 +1 @@ +png \ No newline at end of file diff --git a/tests/rspack-test/configCases/rstest/new-url-wasm/test.wasm b/tests/rspack-test/configCases/rstest/new-url-wasm/test.wasm new file mode 100644 index 0000000000000000000000000000000000000000..d8fc92d022fbf4d1072da17bc8e0840054b51ddc GIT binary patch literal 8 PcmZQbEY4+QU|;|M2ZjMd literal 0 HcmV?d00001 From d424733ba9e21577785311f770d97d5b4e9b2cdf Mon Sep 17 00:00:00 2001 From: Tu Shaokun <53142663+tt-a1i@users.noreply.github.com> Date: Wed, 7 Jan 2026 11:52:39 +0800 Subject: [PATCH 21/87] fix(lint): enable @typescript-eslint/await-thenable rule (#12644) * fix(lint): enable await-thenable rule and fix violation - Enable @typescript-eslint/await-thenable rule (off -> error) - Remove unnecessary await on syncTraceEvent() which returns void * Update rslint.json --------- Co-authored-by: neverland --- packages/rspack/src/exports.ts | 2 +- rslint.json | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/rspack/src/exports.ts b/packages/rspack/src/exports.ts index e1cab5eea45a..b864e0511dac 100644 --- a/packages/rspack/src/exports.ts +++ b/packages/rspack/src/exports.ts @@ -416,7 +416,7 @@ export const experiments: Experiments = { }, async cleanup() { await JavaScriptTracer.cleanupJavaScriptTrace(); - await syncTraceEvent(JavaScriptTracer.events); + syncTraceEvent(JavaScriptTracer.events); cleanupGlobalTrace(); }, }, diff --git a/rslint.json b/rslint.json index 6b2ff6dabad6..47ab6c814156 100644 --- a/rslint.json +++ b/rslint.json @@ -27,7 +27,6 @@ "@typescript-eslint/use-unknown-in-catch-callback-variable": "off", "@typescript-eslint/require-await": "off", "@typescript-eslint/switch-exhaustiveness-check": "off", - "@typescript-eslint/await-thenable": "off", "@typescript-eslint/return-await": "off", "@typescript-eslint/non-nullable-type-assertion-style": "off", "@typescript-eslint/no-misused-spread": "off", From 86634a079855003c3e837ab7be59b0c53b56c26d Mon Sep 17 00:00:00 2001 From: pshu Date: Wed, 7 Jan 2026 16:09:03 +0800 Subject: [PATCH 22/87] refactor: afterCodeGeneration hook use read only compilation ref (#12655) --- crates/rspack_core/src/compilation/mod.rs | 7 +++++-- crates/rspack_plugin_esm_library/src/link.rs | 8 ++++++-- crates/rspack_plugin_esm_library/src/plugin.rs | 10 +++++++--- crates/rspack_plugin_rsdoctor/src/plugin.rs | 6 +++++- 4 files changed, 23 insertions(+), 8 deletions(-) diff --git a/crates/rspack_core/src/compilation/mod.rs b/crates/rspack_core/src/compilation/mod.rs index 6313b6e995c9..ef032103b238 100644 --- a/crates/rspack_core/src/compilation/mod.rs +++ b/crates/rspack_core/src/compilation/mod.rs @@ -94,7 +94,7 @@ define_hook!(CompilationRuntimeRequirementInChunk: SeriesBail(compilation: &mut define_hook!(CompilationAdditionalTreeRuntimeRequirements: Series(compilation: &mut Compilation, chunk_ukey: &ChunkUkey, runtime_requirements: &mut RuntimeGlobals)); define_hook!(CompilationRuntimeRequirementInTree: SeriesBail(compilation: &mut Compilation, chunk_ukey: &ChunkUkey, all_runtime_requirements: &RuntimeGlobals, runtime_requirements: &RuntimeGlobals, runtime_requirements_mut: &mut RuntimeGlobals)); define_hook!(CompilationOptimizeCodeGeneration: Series(compilation: &mut Compilation)); -define_hook!(CompilationAfterCodeGeneration: Series(compilation: &mut Compilation)); +define_hook!(CompilationAfterCodeGeneration: Series(compilation: &Compilation, diagnostics: &mut Vec)); define_hook!(CompilationChunkHash: Series(compilation: &Compilation, chunk_ukey: &ChunkUkey, hasher: &mut RspackHash),tracing=false); define_hook!(CompilationContentHash: Series(compilation: &Compilation, chunk_ukey: &ChunkUkey, hashes: &mut HashMap)); define_hook!(CompilationDependentFullHash: SeriesBail(compilation: &Compilation, chunk_ukey: &ChunkUkey) -> bool); @@ -1893,12 +1893,15 @@ impl Compilation { }; self.code_generation(code_generation_modules).await?; + let mut diagnostics = vec![]; plugin_driver .compilation_hooks .after_code_generation - .call(self) + .call(self, &mut diagnostics) .await .map_err(|e| e.wrap_err("caused by plugins in Compilation.hooks.afterCodeGeneration"))?; + self.extend_diagnostics(diagnostics); + logger.time_end(start); let start = logger.time("runtime requirements"); diff --git a/crates/rspack_plugin_esm_library/src/link.rs b/crates/rspack_plugin_esm_library/src/link.rs index 617a4135be37..ea7e2667076a 100644 --- a/crates/rspack_plugin_esm_library/src/link.rs +++ b/crates/rspack_plugin_esm_library/src/link.rs @@ -139,7 +139,11 @@ impl EsmLibraryPlugin { } } - pub(crate) async fn link(&self, compilation: &mut Compilation) -> Result<()> { + pub(crate) async fn link( + &self, + compilation: &Compilation, + diagnostics: &mut Vec, + ) -> Result<()> { let module_graph = compilation.get_module_graph(); // codegen uses self.concatenated_modules_map_for_codegen which has hold another Arc, so @@ -247,7 +251,7 @@ impl EsmLibraryPlugin { // link imported specifier with exported symbol let mut needed_namespace_objects_by_ukey = UkeyMap::default(); - compilation.extend_diagnostics(self.link_imports_and_exports( + diagnostics.extend(self.link_imports_and_exports( compilation, &mut link, &mut concate_modules_map, diff --git a/crates/rspack_plugin_esm_library/src/plugin.rs b/crates/rspack_plugin_esm_library/src/plugin.rs index 1e51362f0679..f5b67db72a37 100644 --- a/crates/rspack_plugin_esm_library/src/plugin.rs +++ b/crates/rspack_plugin_esm_library/src/plugin.rs @@ -18,7 +18,7 @@ use rspack_core::{ ParserOptions, Plugin, PrefetchExportsInfoMode, RuntimeGlobals, get_target, is_esm_dep_like, rspack_sources::{ReplaceSource, Source}, }; -use rspack_error::Result; +use rspack_error::{Diagnostic, Result}; use rspack_hook::{plugin, plugin_hook}; use rspack_plugin_javascript::{ JavascriptModulesRenderChunkContent, JsPlugin, RenderSource, @@ -303,7 +303,11 @@ async fn concatenation_scope( } #[plugin_hook(CompilationAfterCodeGeneration for EsmLibraryPlugin)] -async fn after_code_generation(&self, compilation: &mut Compilation) -> Result<()> { +async fn after_code_generation( + &self, + compilation: &Compilation, + diagnostics: &mut Vec, +) -> Result<()> { let mut chunk_ids_to_ukey = FxHashMap::default(); for chunk_ukey in compilation.chunk_by_ukey.keys() { @@ -316,7 +320,7 @@ async fn after_code_generation(&self, compilation: &mut Compilation) -> Result<( *self.chunk_ids_to_ukey.borrow_mut() = chunk_ids_to_ukey; - self.link(compilation).await?; + self.link(compilation, diagnostics).await?; Ok(()) } diff --git a/crates/rspack_plugin_rsdoctor/src/plugin.rs b/crates/rspack_plugin_rsdoctor/src/plugin.rs index 165982245414..30274f25f2a7 100644 --- a/crates/rspack_plugin_rsdoctor/src/plugin.rs +++ b/crates/rspack_plugin_rsdoctor/src/plugin.rs @@ -418,7 +418,11 @@ async fn module_ids( } #[plugin_hook(CompilationAfterCodeGeneration for RsdoctorPlugin, stage = 9999)] -async fn after_code_generation(&self, compilation: &mut Compilation) -> Result<()> { +async fn after_code_generation( + &self, + compilation: &Compilation, + _diagnostics: &mut Vec, +) -> Result<()> { if !self.has_module_graph_feature(RsdoctorPluginModuleGraphFeature::ModuleSources) { return Ok(()); } From f4c77913ab9fb1c0ee04243e50af1eb228080823 Mon Sep 17 00:00:00 2001 From: Tu Shaokun <53142663+tt-a1i@users.noreply.github.com> Date: Wed, 7 Jan 2026 22:41:37 +0800 Subject: [PATCH 23/87] fix(lint): enable @typescript-eslint/require-await rule (#12664) fix(lint): enable require-await rule and fix violations - Enable @typescript-eslint/require-await rule (off -> error) - FileSystem.ts: Add missing return for Promise, remove async - SubresourceIntegrityPlugin.ts: Use Promise.resolve() instead of async - browser/service.ts: Remove async from function that only throws - loader-runner/worker.ts: Remove async from .then/.catch callbacks --- packages/rspack/src/FileSystem.ts | 6 +++--- packages/rspack/src/browser/service.ts | 4 ++-- .../src/builtin-plugin/SubresourceIntegrityPlugin.ts | 8 ++++---- packages/rspack/src/loader-runner/worker.ts | 4 ++-- rslint.json | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/rspack/src/FileSystem.ts b/packages/rspack/src/FileSystem.ts index 491b32c1fa29..de1f8cd6cf17 100644 --- a/packages/rspack/src/FileSystem.ts +++ b/packages/rspack/src/FileSystem.ts @@ -255,8 +255,8 @@ class ThreadsafeIntermediateNodeFS extends ThreadsafeOutputNodeFS { }); this.read = memoizeFn(() => { const readFn = fs.read.bind(fs); - return async (fd: number, length: number, position: number) => { - new Promise((resolve) => { + return (fd: number, length: number, position: number) => { + return new Promise((resolve, reject) => { readFn( fd, { @@ -265,7 +265,7 @@ class ThreadsafeIntermediateNodeFS extends ThreadsafeOutputNodeFS { }, (err, _bytesRead, buffer) => { if (err) { - resolve(err); + reject(err); } else { resolve(buffer); } diff --git a/packages/rspack/src/browser/service.ts b/packages/rspack/src/browser/service.ts index 9184cde3def9..c40997ea5a1f 100644 --- a/packages/rspack/src/browser/service.ts +++ b/packages/rspack/src/browser/service.ts @@ -23,6 +23,6 @@ export enum RequestType { CompilationGetAssetPathWithInfo = 'CompilationGetAssetPathWithInfo', } -export async function run() { - throw new Error('Not support browser'); +export function run(): Promise { + return Promise.reject(new Error('Not support browser')); } diff --git a/packages/rspack/src/builtin-plugin/SubresourceIntegrityPlugin.ts b/packages/rspack/src/builtin-plugin/SubresourceIntegrityPlugin.ts index 0eb3a6442720..1e9799285690 100644 --- a/packages/rspack/src/builtin-plugin/SubresourceIntegrityPlugin.ts +++ b/packages/rspack/src/builtin-plugin/SubresourceIntegrityPlugin.ts @@ -286,9 +286,9 @@ export class SubresourceIntegrityPlugin extends NativeSubresourceIntegrityPlugin const hwpHooks = getHooks(compilation); hwpHooks.beforeAssetTagGeneration.tapPromise( PLUGIN_NAME, - async (data) => { + (data) => { self.handleHwpPluginArgs(data); - return data; + return Promise.resolve(data); }, ); @@ -297,13 +297,13 @@ export class SubresourceIntegrityPlugin extends NativeSubresourceIntegrityPlugin name: PLUGIN_NAME, stage: 10000, }, - async (data) => { + (data) => { self.handleHwpBodyTags( data, compiler.outputPath, compiler.options.output.crossOriginLoading, ); - return data; + return Promise.resolve(data); }, ); }); diff --git a/packages/rspack/src/loader-runner/worker.ts b/packages/rspack/src/loader-runner/worker.ts index 3111f59e3f92..d3d91eb28db2 100644 --- a/packages/rspack/src/loader-runner/worker.ts +++ b/packages/rspack/src/loader-runner/worker.ts @@ -648,10 +648,10 @@ function worker(workerOptions: WorkerOptions) { const waitFor = createWaitForPendingRequest(sendRequest); loaderImpl(workerOptions, sendRequest, waitFor) - .then(async (data) => { + .then((data) => { workerData.workerPort.postMessage({ type: 'done', data }); }) - .catch(async (err) => { + .catch((err) => { workerData.workerPort.postMessage({ type: 'done-error', error: serializeError(err), diff --git a/rslint.json b/rslint.json index 47ab6c814156..27ec607043a6 100644 --- a/rslint.json +++ b/rslint.json @@ -25,7 +25,7 @@ "@typescript-eslint/no-confusing-void-expression": "off", "@typescript-eslint/promise-function-async": "off", "@typescript-eslint/use-unknown-in-catch-callback-variable": "off", - "@typescript-eslint/require-await": "off", + "@typescript-eslint/require-await": "error", "@typescript-eslint/switch-exhaustiveness-check": "off", "@typescript-eslint/return-await": "off", "@typescript-eslint/non-nullable-type-assertion-style": "off", From 9400b6514e3727f9a570036687047a5552dd8e95 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 8 Jan 2026 10:26:57 +0800 Subject: [PATCH 24/87] chore(deps): update github-actions (#12645) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/actions/binary-limit/action.yml | 2 +- .github/workflows/ci-lint.yaml | 2 +- .github/workflows/reusable-build-bench.yml | 2 +- .github/workflows/reusable-build-codspeed.yml | 2 +- .github/workflows/reusable-rust-test.yml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/actions/binary-limit/action.yml b/.github/actions/binary-limit/action.yml index f7ac45ce62cd..62d157d96360 100644 --- a/.github/actions/binary-limit/action.yml +++ b/.github/actions/binary-limit/action.yml @@ -13,7 +13,7 @@ runs: steps: - name: GitHub Script - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd + uses: actions/github-script@450193c5abd4cdb17ba9f3ffcfe8f635c4bb6c2a with: script: | const limit = parseInt("${{ inputs.size-threshold }}") || 51200; diff --git a/.github/workflows/ci-lint.yaml b/.github/workflows/ci-lint.yaml index 007d58933524..aeb85f61280b 100644 --- a/.github/workflows/ci-lint.yaml +++ b/.github/workflows/ci-lint.yaml @@ -109,7 +109,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5 - - uses: crate-ci/typos@5c19779cb52ea50e151f5a10333ccd269227b5ae # v1.41.0 + - uses: crate-ci/typos@bb4666ad77b539a6b4ce4eda7ebb6de553704021 # v1.42.0 with: files: . diff --git a/.github/workflows/reusable-build-bench.yml b/.github/workflows/reusable-build-bench.yml index 430e85a09942..0fc566686e80 100644 --- a/.github/workflows/reusable-build-bench.yml +++ b/.github/workflows/reusable-build-bench.yml @@ -42,7 +42,7 @@ jobs: key: build-bench-${{ inputs.target }} - name: Install cargo-codspeed binary - uses: taiki-e/install-action@0e76c5c569f13f7eb21e8e5b26fe710062b57b62 # v2 + uses: taiki-e/install-action@dfcb1ee29051d97c8d0f2d437199570008fd5612 # v2 with: tool: cargo-codspeed@2.10.1 diff --git a/.github/workflows/reusable-build-codspeed.yml b/.github/workflows/reusable-build-codspeed.yml index e8798ffa7773..763fe288d07f 100644 --- a/.github/workflows/reusable-build-codspeed.yml +++ b/.github/workflows/reusable-build-codspeed.yml @@ -30,7 +30,7 @@ jobs: key: build-bench-${{ inputs.target }} - name: Install cargo-codspeed binary - uses: taiki-e/install-action@0e76c5c569f13f7eb21e8e5b26fe710062b57b62 # v2 + uses: taiki-e/install-action@dfcb1ee29051d97c8d0f2d437199570008fd5612 # v2 with: tool: cargo-codspeed@2.10.1 diff --git a/.github/workflows/reusable-rust-test.yml b/.github/workflows/reusable-rust-test.yml index e6cc480a481c..8dbe0ea44161 100644 --- a/.github/workflows/reusable-rust-test.yml +++ b/.github/workflows/reusable-rust-test.yml @@ -95,7 +95,7 @@ jobs: run: cargo codegen - name: Install cargo-deny - uses: taiki-e/install-action@0e76c5c569f13f7eb21e8e5b26fe710062b57b62 # v2 + uses: taiki-e/install-action@dfcb1ee29051d97c8d0f2d437199570008fd5612 # v2 with: tool: cargo-deny@0.18.3 - name: Check licenses From 4ecc5cb27e2613119ff57eb3d0a657aed76583e4 Mon Sep 17 00:00:00 2001 From: Tu Shaokun <53142663+tt-a1i@users.noreply.github.com> Date: Thu, 8 Jan 2026 11:23:28 +0800 Subject: [PATCH 25/87] fix(lint): enable @typescript-eslint/return-await rule (#12665) --- packages/rspack/src/FileSystem.ts | 4 ++-- .../rspack/src/builtin-plugin/ExternalsPlugin.ts | 2 +- .../rspack/src/builtin-plugin/RsdoctorPlugin.ts | 10 +++++----- packages/rspack/src/taps/compilation.ts | 10 +++++----- packages/rspack/src/taps/compiler.ts | 16 ++++------------ rslint.json | 2 +- 6 files changed, 18 insertions(+), 26 deletions(-) diff --git a/packages/rspack/src/FileSystem.ts b/packages/rspack/src/FileSystem.ts index de1f8cd6cf17..6c7de612256b 100644 --- a/packages/rspack/src/FileSystem.ts +++ b/packages/rspack/src/FileSystem.ts @@ -242,7 +242,7 @@ class ThreadsafeIntermediateNodeFS extends ThreadsafeOutputNodeFS { this.write = memoizeFn(() => { const writeFn = util.promisify(fs.write.bind(fs)); return async (fd: number, content: Buffer, position: number) => { - return await writeFn(fd, content, { + return writeFn(fd, content, { position, }); }; @@ -250,7 +250,7 @@ class ThreadsafeIntermediateNodeFS extends ThreadsafeOutputNodeFS { this.writeAll = memoizeFn(() => { const writeFn = util.promisify(fs.writeFile.bind(fs)); return async (fd: number, content: Buffer) => { - return await writeFn(fd, content); + return writeFn(fd, content); }; }); this.read = memoizeFn(() => { diff --git a/packages/rspack/src/builtin-plugin/ExternalsPlugin.ts b/packages/rspack/src/builtin-plugin/ExternalsPlugin.ts index cbd7f4efa186..fd2af1f44dcc 100644 --- a/packages/rspack/src/builtin-plugin/ExternalsPlugin.ts +++ b/packages/rspack/src/builtin-plugin/ExternalsPlugin.ts @@ -70,7 +70,7 @@ export class ExternalsPlugin extends RspackBuiltinPlugin { const processResolveResult = this.#processResolveResult; return async (ctx: RawExternalItemFnCtx) => { - return await new Promise((resolve, reject) => { + return new Promise((resolve, reject) => { const data = ctx.data(); const promise = item( { diff --git a/packages/rspack/src/builtin-plugin/RsdoctorPlugin.ts b/packages/rspack/src/builtin-plugin/RsdoctorPlugin.ts index 6893a5f64850..c3571cfed869 100644 --- a/packages/rspack/src/builtin-plugin/RsdoctorPlugin.ts +++ b/packages/rspack/src/builtin-plugin/RsdoctorPlugin.ts @@ -161,7 +161,7 @@ export const createRsdoctorPluginHooksRegisters: CreatePartialRegisters< }, function (queried) { return async function (data: JsRsdoctorModuleGraph) { - return await queried.promise(data); + return queried.promise(data); }; }, ), @@ -174,7 +174,7 @@ export const createRsdoctorPluginHooksRegisters: CreatePartialRegisters< }, function (queried) { return async function (data: JsRsdoctorChunkGraph) { - return await queried.promise(data); + return queried.promise(data); }; }, ), @@ -187,7 +187,7 @@ export const createRsdoctorPluginHooksRegisters: CreatePartialRegisters< }, function (queried) { return async function (data: JsRsdoctorModuleIdsPatch) { - return await queried.promise(data); + return queried.promise(data); }; }, ), @@ -200,7 +200,7 @@ export const createRsdoctorPluginHooksRegisters: CreatePartialRegisters< }, function (queried) { return async function (data: JsRsdoctorModuleSourcesPatch) { - return await queried.promise(data); + return queried.promise(data); }; }, ), @@ -213,7 +213,7 @@ export const createRsdoctorPluginHooksRegisters: CreatePartialRegisters< }, function (queried) { return async function (data: JsRsdoctorAssetPatch) { - return await queried.promise(data); + return queried.promise(data); }; }, ), diff --git a/packages/rspack/src/taps/compilation.ts b/packages/rspack/src/taps/compilation.ts index 00af3f009b8e..1a404d478595 100644 --- a/packages/rspack/src/taps/compilation.ts +++ b/packages/rspack/src/taps/compilation.ts @@ -282,7 +282,7 @@ export const createCompilationHooksRegisters: CreatePartialRegisters< function (queried) { return async function () { - return await queried.promise( + return queried.promise( getCompiler().__internal__get_compilation()!.modules, ); }; @@ -329,7 +329,7 @@ export const createCompilationHooksRegisters: CreatePartialRegisters< function (queried) { return async function () { - return await queried.promise( + return queried.promise( getCompiler().__internal__get_compilation()!.chunks, getCompiler().__internal__get_compilation()!.modules, ); @@ -346,7 +346,7 @@ export const createCompilationHooksRegisters: CreatePartialRegisters< function (queried) { return async function () { - return await queried.promise( + return queried.promise( getCompiler().__internal__get_compilation()!.chunks, getCompiler().__internal__get_compilation()!.modules, ); @@ -403,7 +403,7 @@ export const createCompilationHooksRegisters: CreatePartialRegisters< function (queried) { return async function () { - return await queried.promise( + return queried.promise( getCompiler().__internal__get_compilation()!.assets, ); }; @@ -447,7 +447,7 @@ export const createCompilationHooksRegisters: CreatePartialRegisters< function (queried) { return async function () { - return await queried.promise(); + return queried.promise(); }; }, ), diff --git a/packages/rspack/src/taps/compiler.ts b/packages/rspack/src/taps/compiler.ts index 6a88440ab187..73c8408cd988 100644 --- a/packages/rspack/src/taps/compiler.ts +++ b/packages/rspack/src/taps/compiler.ts @@ -47,9 +47,7 @@ export const createCompilerHooksRegisters: CreatePartialRegisters< function (queried) { return async function () { - return await queried.promise( - getCompiler().__internal__get_compilation()!, - ); + return queried.promise(getCompiler().__internal__get_compilation()!); }; }, ), @@ -62,9 +60,7 @@ export const createCompilerHooksRegisters: CreatePartialRegisters< function (queried) { return async function () { - return await queried.promise( - getCompiler().__internal__get_compilation()!, - ); + return queried.promise(getCompiler().__internal__get_compilation()!); }; }, ), @@ -90,9 +86,7 @@ export const createCompilerHooksRegisters: CreatePartialRegisters< function (queried) { return async function () { - return await queried.promise( - getCompiler().__internal__get_compilation()!, - ); + return queried.promise(getCompiler().__internal__get_compilation()!); }; }, ), @@ -105,9 +99,7 @@ export const createCompilerHooksRegisters: CreatePartialRegisters< function (queried) { return async function () { - return await queried.promise( - getCompiler().__internal__get_compilation()!, - ); + return queried.promise(getCompiler().__internal__get_compilation()!); }; }, ), diff --git a/rslint.json b/rslint.json index 27ec607043a6..937303190a4c 100644 --- a/rslint.json +++ b/rslint.json @@ -27,7 +27,7 @@ "@typescript-eslint/use-unknown-in-catch-callback-variable": "off", "@typescript-eslint/require-await": "error", "@typescript-eslint/switch-exhaustiveness-check": "off", - "@typescript-eslint/return-await": "off", + "@typescript-eslint/return-await": "error", "@typescript-eslint/non-nullable-type-assertion-style": "off", "@typescript-eslint/no-misused-spread": "off", "@typescript-eslint/unbound-method": "off", From ed4b6ed83377214f6cf717c3abafd2e9b50b59b4 Mon Sep 17 00:00:00 2001 From: hardfist Date: Thu, 8 Jan 2026 16:49:17 +0800 Subject: [PATCH 26/87] refactor: make compilation readonly for runtimeModule hook (#12670) --- .../src/plugins/interceptor.rs | 14 ++++++-------- crates/rspack_core/src/compilation/mod.rs | 6 ++++-- ...ource_map_dev_tool_module_options_plugin.rs | 18 ++++++++++-------- 3 files changed, 20 insertions(+), 18 deletions(-) diff --git a/crates/rspack_binding_api/src/plugins/interceptor.rs b/crates/rspack_binding_api/src/plugins/interceptor.rs index e8e2c55ce5f6..91ace52eff4d 100644 --- a/crates/rspack_binding_api/src/plugins/interceptor.rs +++ b/crates/rspack_binding_api/src/plugins/interceptor.rs @@ -10,7 +10,7 @@ use napi::{ Env, JsValue, bindgen_prelude::{Buffer, FromNapiValue, Function, JsValuesTupleIntoVec, Promise, ToNapiValue}, }; -use rspack_collections::IdentifierSet; +use rspack_collections::{IdentifierMap, IdentifierSet}; use rspack_core::{ AfterResolveResult, AssetEmittedInfo, AsyncModulesArtifact, BeforeResolveResult, BindingCell, BoxModule, ChunkUkey, Compilation, CompilationAdditionalTreeRuntimeRequirements, @@ -41,7 +41,7 @@ use rspack_core::{ NormalModuleFactoryFactorizeHook, NormalModuleFactoryResolve, NormalModuleFactoryResolveForScheme, NormalModuleFactoryResolveForSchemeHook, NormalModuleFactoryResolveHook, NormalModuleFactoryResolveResult, ResourceData, RuntimeGlobals, - Scheme, build_module_graph::BuildModuleGraphArtifact, parse_resource, + RuntimeModule, Scheme, build_module_graph::BuildModuleGraphArtifact, parse_resource, rspack_sources::RawStringSource, }; use rspack_error::Diagnostic; @@ -1340,11 +1340,12 @@ impl CompilationRuntimeRequirementInTree for CompilationRuntimeRequirementInTree impl CompilationRuntimeModule for CompilationRuntimeModuleTap { async fn run( &self, - compilation: &mut Compilation, + compilation: &Compilation, m: &ModuleIdentifier, chunk_ukey: &ChunkUkey, + runtime_modules: &mut IdentifierMap>, ) -> rspack_error::Result<()> { - let Some(module) = compilation.runtime_modules.get(m) else { + let Some(module) = runtime_modules.get(m) else { return Ok(()); }; let source_string = module.generate(compilation).await?; @@ -1364,10 +1365,7 @@ impl CompilationRuntimeModule for CompilationRuntimeModuleTap { if let Some(module) = self.function.call_with_sync(arg).await? && let Some(source) = module.source { - let module = compilation - .runtime_modules - .get_mut(m) - .expect("should have module"); + let module = runtime_modules.get_mut(m).expect("should have module"); match source.source { napi::Either::A(string) => { module.set_custom_source(string); diff --git a/crates/rspack_core/src/compilation/mod.rs b/crates/rspack_core/src/compilation/mod.rs index ef032103b238..c1bc0c865172 100644 --- a/crates/rspack_core/src/compilation/mod.rs +++ b/crates/rspack_core/src/compilation/mod.rs @@ -86,7 +86,7 @@ define_hook!(CompilationOptimizeTree: Series(compilation: &Compilation)); define_hook!(CompilationOptimizeChunkModules: SeriesBail(compilation: &mut Compilation) -> bool); define_hook!(CompilationModuleIds: Series(compilation: &Compilation, module_ids: &mut ModuleIdsArtifact, diagnostics: &mut Vec)); define_hook!(CompilationChunkIds: Series(compilation: &Compilation, chunk_by_ukey: &mut ChunkByUkey, named_chunk_ids_artifact: &mut ChunkNamedIdArtifact, diagnostics: &mut Vec)); -define_hook!(CompilationRuntimeModule: Series(compilation: &mut Compilation, module: &ModuleIdentifier, chunk: &ChunkUkey)); +define_hook!(CompilationRuntimeModule: Series(compilation: &Compilation, module: &ModuleIdentifier, chunk: &ChunkUkey, runtime_modules: &mut IdentifierMap>)); define_hook!(CompilationAdditionalModuleRuntimeRequirements: Series(compilation: &Compilation, module_identifier: &ModuleIdentifier, runtime_requirements: &mut RuntimeGlobals),tracing=false); define_hook!(CompilationRuntimeRequirementInModule: SeriesBail(compilation: &Compilation, module_identifier: &ModuleIdentifier, all_runtime_requirements: &RuntimeGlobals, runtime_requirements: &RuntimeGlobals, runtime_requirements_mut: &mut RuntimeGlobals),tracing=false); define_hook!(CompilationAdditionalChunkRuntimeRequirements: Series(compilation: &mut Compilation, chunk_ukey: &ChunkUkey, runtime_requirements: &mut RuntimeGlobals)); @@ -2286,6 +2286,7 @@ impl Compilation { // NOTE: webpack runs hooks.runtime_module in compilation.add_runtime_module // and overwrite the runtime_module.generate() to get new source in create_chunk_assets // this needs full runtime requirements, so run hooks.runtime_module after runtime_requirements_in_tree + let mut runtime_modules = mem::take(&mut self.runtime_modules); for entry_ukey in &entries { let runtime_module_ids: Vec<_> = self .chunk_graph @@ -2296,11 +2297,12 @@ impl Compilation { plugin_driver .compilation_hooks .runtime_module - .call(self, &runtime_module_id, entry_ukey) + .call(self, &runtime_module_id, entry_ukey, &mut runtime_modules) .await .map_err(|e| e.wrap_err("caused by plugins in Compilation.hooks.runtimeModule"))?; } } + self.runtime_modules = runtime_modules; logger.time_end(start); Ok(()) diff --git a/crates/rspack_plugin_devtool/src/source_map_dev_tool_module_options_plugin.rs b/crates/rspack_plugin_devtool/src/source_map_dev_tool_module_options_plugin.rs index a40915cc277d..b549449ff7b4 100644 --- a/crates/rspack_plugin_devtool/src/source_map_dev_tool_module_options_plugin.rs +++ b/crates/rspack_plugin_devtool/src/source_map_dev_tool_module_options_plugin.rs @@ -1,6 +1,7 @@ +use rspack_collections::IdentifierMap; use rspack_core::{ BoxModule, ChunkUkey, Compilation, CompilationBuildModule, CompilationId, - CompilationRuntimeModule, CompilerId, ModuleIdentifier, Plugin, + CompilationRuntimeModule, CompilerId, ModuleIdentifier, Plugin, RuntimeModule, }; use rspack_error::Result; use rspack_hook::{plugin, plugin_hook}; @@ -46,21 +47,22 @@ async fn build_module( #[plugin_hook(CompilationRuntimeModule for SourceMapDevToolModuleOptionsPlugin)] async fn runtime_module( &self, - compilation: &mut Compilation, - module: &ModuleIdentifier, + _compilation: &Compilation, + module_identifier: &ModuleIdentifier, _chunk: &ChunkUkey, + runtime_modules: &mut IdentifierMap>, ) -> Result<()> { - let Some(module) = compilation.runtime_modules.get_mut(module) else { + let Some(runtime_module) = runtime_modules.get_mut(module_identifier) else { return Ok(()); }; if self.module { - module.set_source_map_kind(SourceMapKind::SourceMap); + runtime_module.set_source_map_kind(SourceMapKind::SourceMap); } else { - module.set_source_map_kind(SourceMapKind::SimpleSourceMap); + runtime_module.set_source_map_kind(SourceMapKind::SimpleSourceMap); } if self.cheap { - let current_kind = *module.get_source_map_kind(); - module.set_source_map_kind(current_kind | SourceMapKind::Cheap) + let current_kind = *runtime_module.get_source_map_kind(); + runtime_module.set_source_map_kind(current_kind | SourceMapKind::Cheap) } Ok(()) } From 3b1926fb9829269bf0ea3b74c4a7647f5c9e7421 Mon Sep 17 00:00:00 2001 From: harpsealjs Date: Thu, 8 Jan 2026 17:23:09 +0800 Subject: [PATCH 27/87] feat: add constructor name for JS runtime modules (#12673) feat: add constructor name for JS runtime module --- crates/node_binding/napi-binding.d.ts | 2 + crates/rspack_binding_api/src/module.rs | 2 + .../src/plugins/interceptor.rs | 2 + crates/rspack_core/src/runtime_module.rs | 11 ++++ .../src/helper/hot-update/plugin.ts | 4 +- packages/rspack/etc/core.api.md | 3 +- packages/rspack/src/Compilation.ts | 3 +- packages/rspack/src/RuntimeModule.ts | 55 ++++++++++++++++++- packages/rspack/src/taps/compilation.ts | 6 +- .../rspack.config.js | 6 +- website/docs/en/types/runtime-module.mdx | 9 +-- website/docs/zh/types/runtime-module.mdx | 9 +-- 12 files changed, 96 insertions(+), 16 deletions(-) diff --git a/crates/node_binding/napi-binding.d.ts b/crates/node_binding/napi-binding.d.ts index 7125ee39f0fb..b072c61cd319 100644 --- a/crates/node_binding/napi-binding.d.ts +++ b/crates/node_binding/napi-binding.d.ts @@ -1205,6 +1205,8 @@ export interface JsRuntimeModule { moduleIdentifier: string constructorName: string name: string + stage: number + isolate: boolean } export interface JsRuntimeModuleArg { diff --git a/crates/rspack_binding_api/src/module.rs b/crates/rspack_binding_api/src/module.rs index 6d90c053ad8e..0448865d1b0e 100644 --- a/crates/rspack_binding_api/src/module.rs +++ b/crates/rspack_binding_api/src/module.rs @@ -745,6 +745,8 @@ pub struct JsRuntimeModule { pub module_identifier: String, pub constructor_name: String, pub name: String, + pub stage: u32, + pub isolate: bool, } #[napi(object, object_from_js = false)] diff --git a/crates/rspack_binding_api/src/plugins/interceptor.rs b/crates/rspack_binding_api/src/plugins/interceptor.rs index 91ace52eff4d..9f022a6697c6 100644 --- a/crates/rspack_binding_api/src/plugins/interceptor.rs +++ b/crates/rspack_binding_api/src/plugins/interceptor.rs @@ -1359,6 +1359,8 @@ impl CompilationRuntimeModule for CompilationRuntimeModuleTap { .as_str() .cow_replace(compilation.runtime_template.runtime_module_prefix(), "") .into_owned(), + stage: module.stage().into(), + isolate: module.should_isolate(), }, chunk: ChunkWrapper::new(*chunk_ukey, compilation), }; diff --git a/crates/rspack_core/src/runtime_module.rs b/crates/rspack_core/src/runtime_module.rs index 64088d66b37d..43f0d27d5de3 100644 --- a/crates/rspack_core/src/runtime_module.rs +++ b/crates/rspack_core/src/runtime_module.rs @@ -67,6 +67,17 @@ impl From for RuntimeModuleStage { } } +impl From for u32 { + fn from(value: RuntimeModuleStage) -> Self { + match value { + RuntimeModuleStage::Normal => 0, + RuntimeModuleStage::Basic => 5, + RuntimeModuleStage::Attach => 10, + RuntimeModuleStage::Trigger => 20, + } + } +} + pub trait RuntimeModuleExt { fn boxed(self) -> Box; } diff --git a/packages/rspack-test-tools/src/helper/hot-update/plugin.ts b/packages/rspack-test-tools/src/helper/hot-update/plugin.ts index f8d19f439eeb..3f7a8065246b 100644 --- a/packages/rspack-test-tools/src/helper/hot-update/plugin.ts +++ b/packages/rspack-test-tools/src/helper/hot-update/plugin.ts @@ -167,7 +167,9 @@ export class HotUpdatePlugin { compilation.hooks.runtimeModule.tap( PLUGIN_NAME, (module: any, _set: any) => { - if (module.constructorName === 'DefinePropertyGettersRuntimeModule') { + if ( + module.constructor.name === 'DefinePropertyGettersRuntimeModule' + ) { module.source.source = Buffer.from( ` ${RuntimeGlobals.definePropertyGetters} = function (exports, definition) { diff --git a/packages/rspack/etc/core.api.md b/packages/rspack/etc/core.api.md index 6f256d593af6..1238e9baa238 100644 --- a/packages/rspack/etc/core.api.md +++ b/packages/rspack/etc/core.api.md @@ -53,7 +53,6 @@ import { JsRsdoctorChunkGraph } from '@rspack/binding'; import { JsRsdoctorModuleGraph } from '@rspack/binding'; import { JsRsdoctorModuleIdsPatch } from '@rspack/binding'; import { JsRsdoctorModuleSourcesPatch } from '@rspack/binding'; -import type { JsRuntimeModule } from '@rspack/binding'; import type { JsStats } from '@rspack/binding'; import type { JsStatsCompilation } from '@rspack/binding'; import type { JsStatsError } from '@rspack/binding'; @@ -1026,7 +1025,7 @@ export class Compilation { Set ]>; runtimeRequirementInTree: liteTapable.HookMap], void>>; - runtimeModule: liteTapable.SyncHook<[JsRuntimeModule, Chunk]>; + runtimeModule: liteTapable.SyncHook<[RuntimeModule, Chunk]>; seal: liteTapable.SyncHook<[]>; afterSeal: liteTapable.AsyncSeriesHook<[], void>; needAdditionalPass: liteTapable.SyncBailHook<[], boolean>; diff --git a/packages/rspack/src/Compilation.ts b/packages/rspack/src/Compilation.ts index 3d4140158bc6..7ee225efa277 100644 --- a/packages/rspack/src/Compilation.ts +++ b/packages/rspack/src/Compilation.ts @@ -15,7 +15,6 @@ import type { ExternalObject, JsCompilation, JsPathData, - JsRuntimeModule, JsSource, } from '@rspack/binding'; import binding from '@rspack/binding'; @@ -252,7 +251,7 @@ export class Compilation { runtimeRequirementInTree: liteTapable.HookMap< liteTapable.SyncBailHook<[Chunk, Set], void> >; - runtimeModule: liteTapable.SyncHook<[JsRuntimeModule, Chunk]>; + runtimeModule: liteTapable.SyncHook<[RuntimeModule, Chunk]>; seal: liteTapable.SyncHook<[]>; afterSeal: liteTapable.AsyncSeriesHook<[], void>; needAdditionalPass: liteTapable.SyncBailHook<[], boolean>; diff --git a/packages/rspack/src/RuntimeModule.ts b/packages/rspack/src/RuntimeModule.ts index dfe97ad096f4..c349b3cae727 100644 --- a/packages/rspack/src/RuntimeModule.ts +++ b/packages/rspack/src/RuntimeModule.ts @@ -1,4 +1,8 @@ -import type { JsAddingRuntimeModule } from '@rspack/binding'; +import type { + JsAddingRuntimeModule, + JsRuntimeModule, + JsSource, +} from '@rspack/binding'; import type { Chunk } from './Chunk'; import type { ChunkGraph } from './ChunkGraph'; import type { Compilation } from './Compilation'; @@ -71,3 +75,52 @@ export class RuntimeModule { ); } } + +export function createRenderedRuntimeModule( + module: JsRuntimeModule, +): RuntimeModule { + const RuntimeModuleClass = { + [module.constructorName]: class extends RuntimeModule { + private _source: JsSource | undefined; + constructor() { + super(module.name, module.stage); + this._source = module.source; + } + + /** + * @deprecated use `module.constructor.name` instead + */ + get constructorName() { + return module.constructorName; + } + + /** + * @deprecated use `module.identifier()` instead + */ + get moduleIdentifier() { + return module.moduleIdentifier; + } + + get source(): JsSource | undefined { + return this._source; + } + + identifier(): string { + return module.moduleIdentifier; + } + + readableIdentifier(): string { + return module.moduleIdentifier; + } + + shouldIsolate(): boolean { + return module.isolate; + } + + generate(): string { + return this._source?.source.toString('utf-8') || ''; + } + }, + }[module.constructorName]; + return new RuntimeModuleClass(); +} diff --git a/packages/rspack/src/taps/compilation.ts b/packages/rspack/src/taps/compilation.ts index 1a404d478595..ebebba20e4d8 100644 --- a/packages/rspack/src/taps/compilation.ts +++ b/packages/rspack/src/taps/compilation.ts @@ -6,6 +6,7 @@ import { __to_binding_runtime_globals, isReservedRuntimeGlobal, } from '../RuntimeGlobals'; +import { createRenderedRuntimeModule } from '../RuntimeModule'; import { createHash } from '../util/createHash'; import type { CreatePartialRegisters } from './types'; @@ -133,8 +134,11 @@ export const createCompilationHooksRegisters: CreatePartialRegisters< function (queried) { return function ({ module, chunk }: binding.JsRuntimeModuleArg) { + const runtimeModule = createRenderedRuntimeModule(module); + const compilation = getCompiler().__internal__get_compilation()!; + runtimeModule.attach(compilation, chunk, compilation.chunkGraph); const originSource = module.source?.source; - queried.call(module, chunk); + queried.call(runtimeModule, chunk); const newSource = module.source?.source; if (newSource && newSource !== originSource) { return module; diff --git a/tests/rspack-test/configCases/hooks/modify-extract-css-loading-runtime/rspack.config.js b/tests/rspack-test/configCases/hooks/modify-extract-css-loading-runtime/rspack.config.js index 5185739088a8..4f6fbf3427f3 100644 --- a/tests/rspack-test/configCases/hooks/modify-extract-css-loading-runtime/rspack.config.js +++ b/tests/rspack-test/configCases/hooks/modify-extract-css-loading-runtime/rspack.config.js @@ -4,7 +4,11 @@ class Plugin { apply(compiler) { compiler.hooks.compilation.tap("TestFakePlugin", compilation => { compilation.hooks.runtimeModule.tap("TestFakePlugin", (module, chunk) => { - if (module.constructorName === "CssLoadingRuntimeModule") { + if (module.constructor.name === "CssLoadingRuntimeModule") { + expect(module.constructorName).toBe("CssLoadingRuntimeModule"); + expect(module.moduleIdentifier).toBe("webpack/runtime/css loading"); + expect(module.identifier()).toBe("webpack/runtime/css loading"); + expect(module.readableIdentifier()).toBe("webpack/runtime/css loading"); const originSource = module.source.source.toString("utf-8"); module.source.source = Buffer.from( `${originSource}\n__webpack_require__.f.miniCss.test = true;\n`, diff --git a/website/docs/en/types/runtime-module.mdx b/website/docs/en/types/runtime-module.mdx index 2c18016ea79b..de5a6390d2fc 100644 --- a/website/docs/en/types/runtime-module.mdx +++ b/website/docs/en/types/runtime-module.mdx @@ -1,17 +1,18 @@ <> ```ts -type RuntimeModule = { +class RuntimeModule { source?: { isRaw: boolean; isBuffer: boolean; source: Buffer; map?: Buffer; }; - moduleIdentifier: string; - constructorName: string; + stage: number; name: string; -}; + identifier(): string; + readableIdentifier(): string; +} ``` diff --git a/website/docs/zh/types/runtime-module.mdx b/website/docs/zh/types/runtime-module.mdx index 2c18016ea79b..de5a6390d2fc 100644 --- a/website/docs/zh/types/runtime-module.mdx +++ b/website/docs/zh/types/runtime-module.mdx @@ -1,17 +1,18 @@ <> ```ts -type RuntimeModule = { +class RuntimeModule { source?: { isRaw: boolean; isBuffer: boolean; source: Buffer; map?: Buffer; }; - moduleIdentifier: string; - constructorName: string; + stage: number; name: string; -}; + identifier(): string; + readableIdentifier(): string; +} ``` From 2feb4550ddc48c94705876ef0f4324cfaf4b9b7a Mon Sep 17 00:00:00 2001 From: jinrui Date: Thu, 8 Jan 2026 17:45:40 +0800 Subject: [PATCH 28/87] fix: incremental rebuild no code generation entry panic (#12643) * fix: incremental rebuild bug * add test case * fix: ci --- crates/rspack_core/src/compilation/mod.rs | 6 ++++++ .../recover-from-error/delete-file/0/file.js | 1 + .../recover-from-error/delete-file/0/index.js | 15 +++++++++++++++ .../recover-from-error/delete-file/1/errors.js | 1 + .../recover-from-error/delete-file/1/file.js | 1 + .../recover-from-error/delete-file/2/file.js | 1 + .../delete-file/rspack.config.js | 7 +++++++ 7 files changed, 32 insertions(+) create mode 100644 tests/rspack-test/watchCases/recover-from-error/delete-file/0/file.js create mode 100644 tests/rspack-test/watchCases/recover-from-error/delete-file/0/index.js create mode 100644 tests/rspack-test/watchCases/recover-from-error/delete-file/1/errors.js create mode 100644 tests/rspack-test/watchCases/recover-from-error/delete-file/1/file.js create mode 100644 tests/rspack-test/watchCases/recover-from-error/delete-file/2/file.js create mode 100644 tests/rspack-test/watchCases/recover-from-error/delete-file/rspack.config.js diff --git a/crates/rspack_core/src/compilation/mod.rs b/crates/rspack_core/src/compilation/mod.rs index c1bc0c865172..f469a7904e04 100644 --- a/crates/rspack_core/src/compilation/mod.rs +++ b/crates/rspack_core/src/compilation/mod.rs @@ -1292,6 +1292,7 @@ impl Compilation { )); chunks } else { + self.chunk_render_artifact.clear(); self.chunk_by_ukey.keys().copied().collect() }; let results = rspack_futures::scope::<_, Result<_>>(|token| { @@ -1850,6 +1851,7 @@ impl Compilation { modules } else { + self.cgm_hash_artifact.clear(); self.get_module_graph().modules().keys().copied().collect() }; self @@ -1889,6 +1891,7 @@ impl Compilation { )); modules } else { + self.code_generation_results = Default::default(); self.get_module_graph().modules().keys().copied().collect() }; self.code_generation(code_generation_modules).await?; @@ -1934,6 +1937,7 @@ impl Compilation { )); modules } else { + self.cgm_runtime_requirements_artifact = Default::default(); self.get_module_graph().modules().keys().copied().collect() }; self @@ -1975,6 +1979,7 @@ impl Compilation { )); affected_chunks } else { + self.cgc_runtime_requirements_artifact.clear(); self.chunk_by_ukey.keys().copied().collect() }; self @@ -2377,6 +2382,7 @@ impl Compilation { )); chunks } else { + self.chunk_hashes_artifact.clear(); self.chunk_by_ukey.keys().copied().collect() }; diff --git a/tests/rspack-test/watchCases/recover-from-error/delete-file/0/file.js b/tests/rspack-test/watchCases/recover-from-error/delete-file/0/file.js new file mode 100644 index 000000000000..46c7130a8a1f --- /dev/null +++ b/tests/rspack-test/watchCases/recover-from-error/delete-file/0/file.js @@ -0,0 +1 @@ +module.exports = 'ok'; diff --git a/tests/rspack-test/watchCases/recover-from-error/delete-file/0/index.js b/tests/rspack-test/watchCases/recover-from-error/delete-file/0/index.js new file mode 100644 index 000000000000..0cc4b5bbb95b --- /dev/null +++ b/tests/rspack-test/watchCases/recover-from-error/delete-file/0/index.js @@ -0,0 +1,15 @@ +it('should recover when recreate file', function () { + switch (WATCH_STEP) { + case '0': + expect(require('./file')).toBe('ok'); + break; + case '1': + expect(function () { + require('./file'); + }).toThrow(); + break; + case '2': + expect(require('./file')).toBe('ok'); + break; + } +}); diff --git a/tests/rspack-test/watchCases/recover-from-error/delete-file/1/errors.js b/tests/rspack-test/watchCases/recover-from-error/delete-file/1/errors.js new file mode 100644 index 000000000000..5608e5447bfd --- /dev/null +++ b/tests/rspack-test/watchCases/recover-from-error/delete-file/1/errors.js @@ -0,0 +1 @@ +module.exports = [/Module not found: Can't resolve/]; diff --git a/tests/rspack-test/watchCases/recover-from-error/delete-file/1/file.js b/tests/rspack-test/watchCases/recover-from-error/delete-file/1/file.js new file mode 100644 index 000000000000..f42a9f0e7e14 --- /dev/null +++ b/tests/rspack-test/watchCases/recover-from-error/delete-file/1/file.js @@ -0,0 +1 @@ +DELETE diff --git a/tests/rspack-test/watchCases/recover-from-error/delete-file/2/file.js b/tests/rspack-test/watchCases/recover-from-error/delete-file/2/file.js new file mode 100644 index 000000000000..46c7130a8a1f --- /dev/null +++ b/tests/rspack-test/watchCases/recover-from-error/delete-file/2/file.js @@ -0,0 +1 @@ +module.exports = 'ok'; diff --git a/tests/rspack-test/watchCases/recover-from-error/delete-file/rspack.config.js b/tests/rspack-test/watchCases/recover-from-error/delete-file/rspack.config.js new file mode 100644 index 000000000000..5e67dfe8e2d3 --- /dev/null +++ b/tests/rspack-test/watchCases/recover-from-error/delete-file/rspack.config.js @@ -0,0 +1,7 @@ +/** @type {import("@rspack/core").Configuration} */ +module.exports = { + ignoreWarnings: [/FlagDependencyUsagePlugin/], + optimization: { + usedExports: true, + }, +}; From 70ffab9077c7cf0f6e81827913b242321972fc51 Mon Sep 17 00:00:00 2001 From: hardfist Date: Thu, 8 Jan 2026 19:12:54 +0800 Subject: [PATCH 29/87] refactor: unify artifact clear logic (#12677) --- .../build_chunk_graph/code_splitter.rs | 1 - crates/rspack_core/src/compilation/mod.rs | 60 +++++++++++++++---- .../plugin/flag_dependency_usage_plugin.rs | 1 - .../src/plugin/inline_exports_plugin.rs | 1 - .../src/plugin/mangle_exports_plugin.rs | 8 +-- .../src/plugin/module_concatenation_plugin.rs | 9 +-- 6 files changed, 54 insertions(+), 26 deletions(-) diff --git a/crates/rspack_core/src/compilation/build_chunk_graph/code_splitter.rs b/crates/rspack_core/src/compilation/build_chunk_graph/code_splitter.rs index f35e3224a6cc..c86f75981aa0 100644 --- a/crates/rspack_core/src/compilation/build_chunk_graph/code_splitter.rs +++ b/crates/rspack_core/src/compilation/build_chunk_graph/code_splitter.rs @@ -404,7 +404,6 @@ impl CodeSplitter { ) { incremental_diagnostic = diagnostic; - compilation.chunk_render_artifact.clear(); } } diff --git a/crates/rspack_core/src/compilation/mod.rs b/crates/rspack_core/src/compilation/mod.rs index f469a7904e04..1c20382b1737 100644 --- a/crates/rspack_core/src/compilation/mod.rs +++ b/crates/rspack_core/src/compilation/mod.rs @@ -1254,10 +1254,16 @@ impl Compilation { "Chunk filename that dependent on full hash", "chunk filename that dependent on full hash is not supported in incremental compilation", ) + && let Some(diagnostic) = diagnostic + { + self.push_diagnostic(diagnostic); + } + + // Check if CHUNKS_RENDER pass is disabled, and clear artifact if needed + if !self + .incremental + .passes_enabled(IncrementalPasses::CHUNKS_RENDER) { - if let Some(diagnostic) = diagnostic { - self.push_diagnostic(diagnostic); - } self.chunk_render_artifact.clear(); } @@ -1292,7 +1298,6 @@ impl Compilation { )); chunks } else { - self.chunk_render_artifact.clear(); self.chunk_by_ukey.keys().copied().collect() }; let results = rspack_futures::scope::<_, Result<_>>(|token| { @@ -1732,6 +1737,14 @@ impl Compilation { let start = logger.time("module ids"); + // Check if MODULE_IDS pass is disabled, and clear artifact if needed + if !self + .incremental + .passes_enabled(IncrementalPasses::MODULE_IDS) + { + self.module_ids_artifact.clear(); + } + let mut diagnostics = vec![]; let mut module_ids_artifact = mem::take(&mut self.module_ids_artifact); plugin_driver @@ -1745,6 +1758,15 @@ impl Compilation { logger.time_end(start); let start = logger.time("chunk ids"); + + // Check if CHUNK_IDS pass is disabled, and clear artifact if needed + if !self + .incremental + .passes_enabled(IncrementalPasses::CHUNK_IDS) + { + self.named_chunk_ids_artifact.clear(); + } + let mut diagnostics = vec![]; let mut chunk_by_ukey = mem::take(&mut self.chunk_by_ukey); let mut named_chunk_ids_artifact = mem::take(&mut self.named_chunk_ids_artifact); @@ -1775,6 +1797,14 @@ impl Compilation { .map_err(|e| e.wrap_err("caused by plugins in Compilation.hooks.optimizeCodeGeneration"))?; logger.time_end(start); + // Check if MODULES_HASHES pass is disabled, and clear artifact if needed + if !self + .incremental + .passes_enabled(IncrementalPasses::MODULES_HASHES) + { + self.cgm_hash_artifact.clear(); + } + let create_module_hashes_modules = if let Some(mutations) = self .incremental .mutations_read(IncrementalPasses::MODULES_HASHES) @@ -1851,7 +1881,6 @@ impl Compilation { modules } else { - self.cgm_hash_artifact.clear(); self.get_module_graph().modules().keys().copied().collect() }; self @@ -1947,6 +1976,15 @@ impl Compilation { ) .await?; let runtime_chunks = self.get_chunk_graph_entries().collect(); + + // Check if CHUNKS_RUNTIME_REQUIREMENTS pass is disabled, and clear artifact if needed + if !self + .incremental + .passes_enabled(IncrementalPasses::CHUNKS_RUNTIME_REQUIREMENTS) + { + self.cgc_runtime_requirements_artifact.clear(); + } + let process_runtime_requirements_chunks = if let Some(mutations) = self .incremental .mutations_read(IncrementalPasses::CHUNKS_RUNTIME_REQUIREMENTS) @@ -1979,7 +2017,6 @@ impl Compilation { )); affected_chunks } else { - self.cgc_runtime_requirements_artifact.clear(); self.chunk_by_ukey.keys().copied().collect() }; self @@ -2350,10 +2387,14 @@ impl Compilation { "Chunk content that dependent on full hash", "it requires calculating the hashes of all the chunks, which is a global effect", ) + && let Some(diagnostic) = diagnostic + { + self.push_diagnostic(diagnostic); + } + if !self + .incremental + .passes_enabled(IncrementalPasses::CHUNKS_HASHES) { - if let Some(diagnostic) = diagnostic { - self.push_diagnostic(diagnostic); - } self.chunk_hashes_artifact.clear(); } @@ -2382,7 +2423,6 @@ impl Compilation { )); chunks } else { - self.chunk_hashes_artifact.clear(); self.chunk_by_ukey.keys().copied().collect() }; diff --git a/crates/rspack_plugin_javascript/src/plugin/flag_dependency_usage_plugin.rs b/crates/rspack_plugin_javascript/src/plugin/flag_dependency_usage_plugin.rs index ef25f1c83fc9..7ce8c35f045b 100644 --- a/crates/rspack_plugin_javascript/src/plugin/flag_dependency_usage_plugin.rs +++ b/crates/rspack_plugin_javascript/src/plugin/flag_dependency_usage_plugin.rs @@ -501,7 +501,6 @@ async fn optimize_dependencies( "it requires calculating the used exports based on all modules, which is a global effect", ) { diagnostics.extend(diagnostic); - // compilation.cgm_hash_artifact.clear(); } let mut proxy = diff --git a/crates/rspack_plugin_javascript/src/plugin/inline_exports_plugin.rs b/crates/rspack_plugin_javascript/src/plugin/inline_exports_plugin.rs index 50edeaff9992..1b6ff83b4f2f 100644 --- a/crates/rspack_plugin_javascript/src/plugin/inline_exports_plugin.rs +++ b/crates/rspack_plugin_javascript/src/plugin/inline_exports_plugin.rs @@ -107,7 +107,6 @@ async fn optimize_dependencies( "it requires calculating the export names of all the modules, which is a global effect", ) { diagnostics.extend(diagnostic); - //compilation.cgm_hash_artifact.clear(); } let mg = build_module_graph_artifact.get_module_graph_mut(); diff --git a/crates/rspack_plugin_javascript/src/plugin/mangle_exports_plugin.rs b/crates/rspack_plugin_javascript/src/plugin/mangle_exports_plugin.rs index e998e35c16ca..c5d965053442 100644 --- a/crates/rspack_plugin_javascript/src/plugin/mangle_exports_plugin.rs +++ b/crates/rspack_plugin_javascript/src/plugin/mangle_exports_plugin.rs @@ -64,11 +64,9 @@ async fn optimize_code_generation(&self, compilation: &mut Compilation) -> Resul IncrementalPasses::MODULES_HASHES, "MangleExportsPlugin (optimization.mangleExports = true)", "it requires calculating the export names of all the modules, which is a global effect", - ) { - if let Some(diagnostic) = diagnostic { - compilation.push_diagnostic(diagnostic); - } - compilation.cgm_hash_artifact.clear(); + ) && let Some(diagnostic) = diagnostic + { + compilation.push_diagnostic(diagnostic); } let mg = compilation.get_module_graph_mut(); diff --git a/crates/rspack_plugin_javascript/src/plugin/module_concatenation_plugin.rs b/crates/rspack_plugin_javascript/src/plugin/module_concatenation_plugin.rs index 5f2acab395c0..a1a70ea25b27 100644 --- a/crates/rspack_plugin_javascript/src/plugin/module_concatenation_plugin.rs +++ b/crates/rspack_plugin_javascript/src/plugin/module_concatenation_plugin.rs @@ -1402,15 +1402,8 @@ async fn optimize_chunk_modules(&self, compilation: &mut Compilation) -> Result< | IncrementalPasses::CHUNKS_HASHES, "ModuleConcatenationPlugin (optimization.concatenateModules = true)", "it requires calculating the modules that can be concatenated based on all the modules, which is a global effect", - ) { - if let Some(diagnostic) = diagnostic { + ) && let Some(diagnostic) = diagnostic { compilation.push_diagnostic(diagnostic); - } - compilation.cgm_hash_artifact.clear(); - compilation.module_ids_artifact.clear(); - compilation.named_chunk_ids_artifact.clear(); - compilation.cgc_runtime_requirements_artifact.clear(); - compilation.chunk_hashes_artifact.clear(); } self.optimize_chunk_modules_impl(compilation).await?; From 29642b28fd963fd5dd4a2db27fb73b90f8c1349b Mon Sep 17 00:00:00 2001 From: pshu Date: Thu, 8 Jan 2026 21:08:48 +0800 Subject: [PATCH 30/87] refactor: use DerfOpt's take/replace assist artifact mutation (#12659) * refactor: remove Default trait of DerefOption * refactor: `replace` is better than `insert` --- crates/rspack_core/src/compilation/mod.rs | 27 ++++++++++++------- crates/rspack_core/src/utils/deref_option.rs | 13 +++------ .../benches/groups/build_chunk_graph.rs | 18 ++++++++----- 3 files changed, 32 insertions(+), 26 deletions(-) diff --git a/crates/rspack_core/src/compilation/mod.rs b/crates/rspack_core/src/compilation/mod.rs index 1c20382b1737..f124be2ee07b 100644 --- a/crates/rspack_core/src/compilation/mod.rs +++ b/crates/rspack_core/src/compilation/mod.rs @@ -662,7 +662,7 @@ impl Compilation { } let make_artifact = self.build_module_graph_artifact.take(); - self.build_module_graph_artifact = DerefOption::new( + self.build_module_graph_artifact.replace( update_module_graph( self, make_artifact, @@ -713,7 +713,7 @@ impl Compilation { // Recheck entry and clean useless entry // This should before finish_modules hook is called, ensure providedExports effects on new added modules let make_artifact = self.build_module_graph_artifact.take(); - self.build_module_graph_artifact = DerefOption::new( + self.build_module_graph_artifact.replace( update_module_graph( self, make_artifact, @@ -1025,7 +1025,9 @@ impl Compilation { } let artifact = self.build_module_graph_artifact.take(); - self.build_module_graph_artifact = DerefOption::new(build_module_graph(self, artifact).await?); + self + .build_module_graph_artifact + .replace(build_module_graph(self, artifact).await?); self.in_finish_make.store(true, Ordering::Release); @@ -1042,7 +1044,7 @@ impl Compilation { // https://github.com/webpack/webpack/blob/19ca74127f7668aaf60d59f4af8fcaee7924541a/lib/Compilation.js#L2462C21-L2462C25 self.module_graph_cache_artifact.unfreeze(); - self.build_module_graph_artifact = DerefOption::new( + self.build_module_graph_artifact.replace( update_module_graph( self, artifact, @@ -1456,8 +1458,9 @@ impl Compilation { self.in_finish_make.store(false, Ordering::Release); // clean up the entry deps let make_artifact = self.build_module_graph_artifact.take(); - self.build_module_graph_artifact = - DerefOption::new(finish_build_module_graph(self, make_artifact).await?); + self + .build_module_graph_artifact + .replace(finish_build_module_graph(self, make_artifact).await?); // sync assets to module graph from module_executor if let Some(module_executor) = &mut self.module_executor { let mut module_executor = std::mem::take(module_executor); @@ -1645,9 +1648,9 @@ impl Compilation { let start = logger.time("optimize dependencies"); // https://github.com/webpack/webpack/blob/d15c73469fd71cf98734685225250148b68ddc79/lib/Compilation.js#L2812-L2814 - let mut side_effects_optimize_artifact = self.side_effects_optimize_artifact.take(); let mut diagnostics: Vec = vec![]; - let mut build_module_graph_artifact = mem::take(&mut self.build_module_graph_artifact); + let mut side_effects_optimize_artifact = self.side_effects_optimize_artifact.take(); + let mut build_module_graph_artifact = self.build_module_graph_artifact.take(); while matches!( plugin_driver .compilation_hooks @@ -1662,8 +1665,12 @@ impl Compilation { .map_err(|e| e.wrap_err("caused by plugins in Compilation.hooks.optimizeDependencies"))?, Some(true) ) {} - self.side_effects_optimize_artifact = DerefOption::new(side_effects_optimize_artifact); - self.build_module_graph_artifact = build_module_graph_artifact; + self + .side_effects_optimize_artifact + .replace(side_effects_optimize_artifact); + self + .build_module_graph_artifact + .replace(build_module_graph_artifact); self.extend_diagnostics(diagnostics); logger.time_end(start); diff --git a/crates/rspack_core/src/utils/deref_option.rs b/crates/rspack_core/src/utils/deref_option.rs index 013b3750eb64..78d1f0889166 100644 --- a/crates/rspack_core/src/utils/deref_option.rs +++ b/crates/rspack_core/src/utils/deref_option.rs @@ -6,15 +6,6 @@ use std::{ #[derive(Debug)] pub struct DerefOption(Option); -impl Default for DerefOption -where - T: Default, -{ - fn default() -> Self { - Self(Some(T::default())) - } -} - impl From for DerefOption { fn from(value: T) -> Self { Self::new(value) @@ -42,6 +33,10 @@ impl DerefOption { other, ); } + + pub fn replace(&mut self, value: T) -> Option { + self.0.replace(value) + } } impl Deref for DerefOption { type Target = T; diff --git a/xtask/benchmark/benches/groups/build_chunk_graph.rs b/xtask/benchmark/benches/groups/build_chunk_graph.rs index 080a3a8e4bda..f41612a55531 100644 --- a/xtask/benchmark/benches/groups/build_chunk_graph.rs +++ b/xtask/benchmark/benches/groups/build_chunk_graph.rs @@ -1,11 +1,11 @@ #![allow(clippy::unwrap_used)] -use std::{mem, sync::Arc}; +use std::sync::Arc; use criterion::criterion_group; use rspack::builder::Builder as _; use rspack_benchmark::Criterion; use rspack_core::{ - Compilation, Compiler, DerefOption, Experiments, Optimization, build_chunk_graph, fast_set, + Compilation, Compiler, Experiments, Optimization, build_chunk_graph, fast_set, incremental::{Incremental, IncrementalOptions}, }; use rspack_error::Diagnostic; @@ -180,8 +180,7 @@ pub fn build_chunk_graph_benchmark_inner(c: &mut Criterion) { let mut side_effects_optimize_artifact = compiler.compilation.side_effects_optimize_artifact.take(); let mut diagnostics: Vec = vec![]; - let mut build_module_graph_artifact = - mem::take(&mut compiler.compilation.build_module_graph_artifact); + let mut build_module_graph_artifact = compiler.compilation.build_module_graph_artifact.take(); while matches!( compiler .plugin_driver @@ -197,10 +196,15 @@ pub fn build_chunk_graph_benchmark_inner(c: &mut Criterion) { .unwrap(), Some(true) ) {} - compiler.compilation.build_module_graph_artifact = build_module_graph_artifact; + compiler + .compilation + .build_module_graph_artifact + .replace(build_module_graph_artifact); - compiler.compilation.side_effects_optimize_artifact = - DerefOption::new(side_effects_optimize_artifact); + compiler + .compilation + .side_effects_optimize_artifact + .replace(side_effects_optimize_artifact); compiler.compilation.extend_diagnostics(diagnostics); compiler From 219a773f89b27cd9d869d3cb958fd1e5ac3965fd Mon Sep 17 00:00:00 2001 From: jinrui Date: Fri, 9 Jan 2026 13:37:08 +0800 Subject: [PATCH 31/87] feat: rspack_cacheable context expose project root (#12685) * feat: rspack_cacheable context expose project root * fix: comment --- crates/rspack_cacheable/src/context.rs | 38 +++++++++++++++---- crates/rspack_cacheable/src/deserialize.rs | 6 +-- crates/rspack_cacheable/src/lib.rs | 5 ++- crates/rspack_cacheable/src/serialize.rs | 6 +-- crates/rspack_cacheable/src/with/as.rs | 14 +++---- crates/rspack_cacheable/src/with/custom.rs | 16 ++++---- crates/rspack_cacheable_test/tests/context.rs | 32 ++++++++++------ .../tests/macro/cacheable_dyn.rs | 13 ++++++- .../tests/macro/manual_cacheable_dyn.rs | 9 ++++- .../manual_cacheable_dyn_with_generics.rs | 9 ++++- crates/rspack_cacheable_test/tests/with/as.rs | 8 ++-- .../tests/with/custom.rs | 8 ++-- .../src/cache/persistent/cacheable_context.rs | 6 +++ crates/rspack_core/src/module_profile.rs | 9 ++--- 14 files changed, 117 insertions(+), 62 deletions(-) diff --git a/crates/rspack_cacheable/src/context.rs b/crates/rspack_cacheable/src/context.rs index ec9d235ff64c..8911b256d910 100644 --- a/crates/rspack_cacheable/src/context.rs +++ b/crates/rspack_cacheable/src/context.rs @@ -1,4 +1,4 @@ -use std::{any::Any, ptr::NonNull}; +use std::{any::Any, ops::Deref, path::Path, ptr::NonNull}; use rkyv::{ de::{ErasedPtr, Pooling, PoolingState}, @@ -10,13 +10,31 @@ use crate::error::{Error, Result}; const CONTEXT_ADDR: usize = 0; unsafe fn default_drop(_: ErasedPtr) {} +pub trait CacheableContext: Any { + fn project_root(&self) -> Option<&Path>; +} + +// Implement for unit type for convenience in tests and simple cases +impl CacheableContext for () { + fn project_root(&self) -> Option<&Path> { + None + } +} + /// A context wrapper that provides shared context methods pub struct ContextGuard<'a> { - context: &'a dyn Any, + context: &'a dyn CacheableContext, +} + +impl<'a> Deref for ContextGuard<'a> { + type Target = dyn CacheableContext; + fn deref(&self) -> &Self::Target { + self.context + } } impl<'a> ContextGuard<'a> { - pub fn new(context: &'a dyn Any) -> Self { + pub fn new(context: &'a dyn CacheableContext) -> Self { Self { context } } @@ -25,11 +43,11 @@ impl<'a> ContextGuard<'a> { sharing.finish_sharing(CONTEXT_ADDR, self as *const _ as usize) } - pub fn sharing_context + ?Sized>(sharing: &'a mut S) -> Result<&'a dyn Any> { + pub fn sharing_guard + ?Sized>(sharing: &'a mut S) -> Result<&'a Self> { match sharing.start_sharing(CONTEXT_ADDR) { SharingState::Finished(addr) => { let guard: &Self = unsafe { &*(addr as *const Self) }; - Ok(guard.context) + Ok(guard) } _ => Err(Error::NoContext), } @@ -43,13 +61,19 @@ impl<'a> ContextGuard<'a> { } } - pub fn pooling_context + ?Sized>(pooling: &'a mut P) -> Result<&'a dyn Any> { + pub fn pooling_guard + ?Sized>(pooling: &'a mut P) -> Result<&'a Self> { match pooling.start_pooling(CONTEXT_ADDR) { PoolingState::Finished(ptr) => { let guard: &Self = unsafe { &*(ptr.data_address() as *const Self) }; - Ok(guard.context) + Ok(guard) } _ => Err(Error::NoContext), } } + + pub fn downcast_context(&'a self) -> Result<&'a T> { + (self.context as &dyn Any) + .downcast_ref() + .ok_or(Error::NoContext) + } } diff --git a/crates/rspack_cacheable/src/deserialize.rs b/crates/rspack_cacheable/src/deserialize.rs index 54777f6be193..1815d3a4c65e 100644 --- a/crates/rspack_cacheable/src/deserialize.rs +++ b/crates/rspack_cacheable/src/deserialize.rs @@ -1,5 +1,3 @@ -use std::any::Any; - use rkyv::{ Archive, Deserialize, access, api::{deserialize_using, high::HighValidator}, @@ -10,7 +8,7 @@ use rkyv::{ }; use crate::{ - context::ContextGuard, + context::{CacheableContext, ContextGuard}, error::{Error, Result}, }; @@ -21,7 +19,7 @@ pub type Deserializer = Strategy; /// /// This function implementation refers to rkyv::from_bytes and /// add custom error and context support -pub fn from_bytes(bytes: &[u8], context: &C) -> Result +pub fn from_bytes(bytes: &[u8], context: &C) -> Result where T: Archive, T::Archived: for<'a> CheckBytes> + Deserialize, diff --git a/crates/rspack_cacheable/src/lib.rs b/crates/rspack_cacheable/src/lib.rs index 7ba5c296366e..71357875aab8 100644 --- a/crates/rspack_cacheable/src/lib.rs +++ b/crates/rspack_cacheable/src/lib.rs @@ -29,7 +29,7 @@ pub mod __private { #[cfg(not(feature = "noop"))] pub use deserialize::from_bytes; #[cfg(feature = "noop")] -pub fn from_bytes(_bytes: &[u8], _context: &C) -> Result { +pub fn from_bytes(_bytes: &[u8], _context: &C) -> Result { let _ = deserialize::from_bytes::; panic!("Cannot use from_bytes when noop feature is enabled") } @@ -37,11 +37,12 @@ pub fn from_bytes(_bytes: &[u8], _context: &C) -> Result #[cfg(not(feature = "noop"))] pub use serialize::to_bytes; #[cfg(feature = "noop")] -pub fn to_bytes(_value: &T, _ctx: &C) -> Result> { +pub fn to_bytes(_value: &T, _ctx: &C) -> Result> { let _ = serialize::to_bytes::; panic!("Cannot use to_bytes when noop feature is enabled") } +pub use context::{CacheableContext, ContextGuard}; pub use deserialize::{Deserializer, Validator}; pub use error::{Error, Result}; pub use serialize::Serializer; diff --git a/crates/rspack_cacheable/src/serialize.rs b/crates/rspack_cacheable/src/serialize.rs index 987f223b228f..f5ec772aa7b5 100644 --- a/crates/rspack_cacheable/src/serialize.rs +++ b/crates/rspack_cacheable/src/serialize.rs @@ -1,5 +1,3 @@ -use std::any::Any; - use rkyv::{ Serialize, api::{high::HighSerializer, serialize_using}, @@ -12,7 +10,7 @@ use rkyv::{ }; use crate::{ - context::ContextGuard, + context::{CacheableContext, ContextGuard}, error::{Error, Result}, }; @@ -22,7 +20,7 @@ pub type Serializer<'a> = HighSerializer, Error>; /// /// This function implementation refers to rkyv::to_bytes and /// add custom error and context support -pub fn to_bytes(value: &T, ctx: &C) -> Result> +pub fn to_bytes(value: &T, ctx: &C) -> Result> where T: for<'a> Serialize>, { diff --git a/crates/rspack_cacheable/src/with/as.rs b/crates/rspack_cacheable/src/with/as.rs index 31711cdb15ce..6de22f98ea63 100644 --- a/crates/rspack_cacheable/src/with/as.rs +++ b/crates/rspack_cacheable/src/with/as.rs @@ -1,5 +1,3 @@ -use std::any::Any; - use rkyv::{ Archive, Archived, Deserialize, Place, Resolver, Serialize, de::Pooling, @@ -11,10 +9,10 @@ use rkyv::{ use crate::{Error, Result, context::ContextGuard}; pub trait AsConverter { - fn serialize(data: &T, ctx: &dyn Any) -> Result + fn serialize(data: &T, guard: &ContextGuard) -> Result where Self: Sized; - fn deserialize(self, ctx: &dyn Any) -> Result; + fn deserialize(self, guard: &ContextGuard) -> Result; } pub struct As { @@ -47,8 +45,8 @@ where { #[inline] fn serialize_with(field: &T, serializer: &mut S) -> Result { - let ctx = ContextGuard::sharing_context(serializer)?; - let value = >::serialize(field, ctx)?; + let guard = ContextGuard::sharing_guard(serializer)?; + let value = >::serialize(field, guard)?; Ok(AsResolver { resolver: value.serialize(serializer)?, value, @@ -65,7 +63,7 @@ where #[inline] fn deserialize_with(field: &Archived, de: &mut D) -> Result { let field = A::Archived::deserialize(field, de)?; - let ctx = ContextGuard::pooling_context(de)?; - field.deserialize(ctx) + let guard = ContextGuard::pooling_guard(de)?; + field.deserialize(guard) } } diff --git a/crates/rspack_cacheable/src/with/custom.rs b/crates/rspack_cacheable/src/with/custom.rs index 7c298b351a4d..8d871bc3a1c7 100644 --- a/crates/rspack_cacheable/src/with/custom.rs +++ b/crates/rspack_cacheable/src/with/custom.rs @@ -1,5 +1,3 @@ -use std::any::Any; - use rkyv::{ Archive, Deserialize, Place, Serialize, de::Pooling, @@ -8,15 +6,15 @@ use rkyv::{ with::{ArchiveWith, DeserializeWith, SerializeWith}, }; -use crate::{Error, Result, cacheable, context::ContextGuard}; +use crate::{ContextGuard, Error, Result, cacheable}; /// A trait for writing custom serialization and deserialization. /// /// `#[cacheable(with=Custom)]` will use this trait. pub trait CustomConverter { type Target: Archive; - fn serialize(&self, ctx: &dyn Any) -> Result; - fn deserialize(data: Self::Target, ctx: &dyn Any) -> Result + fn serialize(&self, guard: &ContextGuard) -> Result; + fn deserialize(data: Self::Target, guard: &ContextGuard) -> Result where Self: Sized; } @@ -57,8 +55,8 @@ where { #[inline] fn serialize_with(field: &T, serializer: &mut S) -> Result { - let ctx = ContextGuard::sharing_context(serializer)?; - let value = DataBox(T::serialize(field, ctx)?); + let guard = ContextGuard::sharing_guard(serializer)?; + let value = DataBox(T::serialize(field, guard)?); Ok(CustomResolver { resolver: value.serialize(serializer)?, value, @@ -76,7 +74,7 @@ where #[inline] fn deserialize_with(field: &ArchivedDataBox, de: &mut D) -> Result { let value = field.deserialize(de)?; - let ctx = ContextGuard::pooling_context(de)?; - T::deserialize(value.0, ctx) + let guard = ContextGuard::pooling_guard(de)?; + T::deserialize(value.0, guard) } } diff --git a/crates/rspack_cacheable_test/tests/context.rs b/crates/rspack_cacheable_test/tests/context.rs index caab02399c8a..b145f5ceed06 100644 --- a/crates/rspack_cacheable_test/tests/context.rs +++ b/crates/rspack_cacheable_test/tests/context.rs @@ -1,7 +1,8 @@ -use std::{any::Any, sync::Arc}; +use std::sync::Arc; use rspack_cacheable::{ - Error, enable_cacheable as cacheable, from_bytes, to_bytes, + CacheableContext, ContextGuard, Error, Result, enable_cacheable as cacheable, from_bytes, + to_bytes, with::{As, AsConverter}, }; @@ -15,17 +16,21 @@ struct Context { option: Arc, } +impl CacheableContext for Context { + fn project_root(&self) -> Option<&std::path::Path> { + None + } +} + #[cacheable] struct FromContext; impl AsConverter> for FromContext { - fn serialize(_data: &Arc, _ctx: &dyn Any) -> Result { + fn serialize(_data: &Arc, _guard: &ContextGuard) -> Result { Ok(FromContext) } - fn deserialize(self, ctx: &dyn Any) -> Result, Error> { - let Some(ctx) = ctx.downcast_ref::() else { - return Err(Error::MessageError("context not match")); - }; + fn deserialize(self, guard: &ContextGuard) -> Result> { + let ctx = guard.downcast_context::()?; Ok(ctx.option.clone()) } } @@ -50,10 +55,15 @@ fn test_context() { let bytes = to_bytes(&module, &()).unwrap(); - assert!(matches!( - from_bytes::(&bytes, &()), - Err(Error::MessageError("context not match")) - )); + let result = from_bytes::(&bytes, &()); + assert!(result.is_err(), "should fail when using wrong context"); + if let Err(e) = result { + assert!( + matches!(e, Error::NoContext), + "expected NoContext but got: {:?}", + e + ); + } let new_module: Module = from_bytes(&bytes, &context).unwrap(); assert_eq!(module, new_module); } diff --git a/crates/rspack_cacheable_test/tests/macro/cacheable_dyn.rs b/crates/rspack_cacheable_test/tests/macro/cacheable_dyn.rs index 03fb5af3446c..350f9722ce73 100644 --- a/crates/rspack_cacheable_test/tests/macro/cacheable_dyn.rs +++ b/crates/rspack_cacheable_test/tests/macro/cacheable_dyn.rs @@ -1,11 +1,17 @@ use rspack_cacheable::{ - enable_cacheable as cacheable, enable_cacheable_dyn as cacheable_dyn, from_bytes, to_bytes, + CacheableContext, enable_cacheable as cacheable, enable_cacheable_dyn as cacheable_dyn, + from_bytes, to_bytes, }; #[test] #[cfg_attr(miri, ignore)] fn test_cacheable_dyn_macro() { struct Context; + impl CacheableContext for Context { + fn project_root(&self) -> Option<&std::path::Path> { + None + } + } #[cacheable_dyn] trait Animal { @@ -77,6 +83,11 @@ fn test_cacheable_dyn_macro() { #[cfg_attr(miri, ignore)] fn test_cacheable_dyn_macro_with_generics() { struct Context; + impl CacheableContext for Context { + fn project_root(&self) -> Option<&std::path::Path> { + None + } + } #[cacheable_dyn] trait Animal: Send + Sync diff --git a/crates/rspack_cacheable_test/tests/macro/manual_cacheable_dyn.rs b/crates/rspack_cacheable_test/tests/macro/manual_cacheable_dyn.rs index 9ed7f9e24cb0..4779ddf4eab1 100644 --- a/crates/rspack_cacheable_test/tests/macro/manual_cacheable_dyn.rs +++ b/crates/rspack_cacheable_test/tests/macro/manual_cacheable_dyn.rs @@ -1,9 +1,16 @@ -use rspack_cacheable::{r#dyn::VTablePtr, enable_cacheable as cacheable, from_bytes, to_bytes}; +use rspack_cacheable::{ + CacheableContext, r#dyn::VTablePtr, enable_cacheable as cacheable, from_bytes, to_bytes, +}; #[test] #[cfg_attr(miri, ignore)] fn test_manual_cacheable_dyn_macro() { struct Context; + impl CacheableContext for Context { + fn project_root(&self) -> Option<&std::path::Path> { + None + } + } trait Animal: rspack_cacheable::r#dyn::SerializeDyn { fn color(&self) -> &str; diff --git a/crates/rspack_cacheable_test/tests/macro/manual_cacheable_dyn_with_generics.rs b/crates/rspack_cacheable_test/tests/macro/manual_cacheable_dyn_with_generics.rs index 5aece11115b9..ed5182e53359 100644 --- a/crates/rspack_cacheable_test/tests/macro/manual_cacheable_dyn_with_generics.rs +++ b/crates/rspack_cacheable_test/tests/macro/manual_cacheable_dyn_with_generics.rs @@ -1,9 +1,16 @@ -use rspack_cacheable::{r#dyn::VTablePtr, enable_cacheable as cacheable, from_bytes, to_bytes}; +use rspack_cacheable::{ + CacheableContext, r#dyn::VTablePtr, enable_cacheable as cacheable, from_bytes, to_bytes, +}; #[test] #[cfg_attr(miri, ignore)] fn test_manual_cacheable_dyn_macro_with_generics() { struct Context; + impl CacheableContext for Context { + fn project_root(&self) -> Option<&std::path::Path> { + None + } + } trait Animal: rspack_cacheable::r#dyn::SerializeDyn { fn color(&self) -> &str; diff --git a/crates/rspack_cacheable_test/tests/with/as.rs b/crates/rspack_cacheable_test/tests/with/as.rs index cb97ffd9add6..eff0b83eac73 100644 --- a/crates/rspack_cacheable_test/tests/with/as.rs +++ b/crates/rspack_cacheable_test/tests/with/as.rs @@ -1,7 +1,7 @@ -use std::{any::Any, path::PathBuf}; +use std::path::PathBuf; use rspack_cacheable::{ - Error, enable_cacheable as cacheable, + ContextGuard, Result, enable_cacheable as cacheable, with::{As, AsConverter}, }; @@ -12,10 +12,10 @@ struct UnCacheableData(PathBuf); struct CacheableData(String); impl AsConverter for CacheableData { - fn serialize(data: &UnCacheableData, _ctx: &dyn Any) -> Result { + fn serialize(data: &UnCacheableData, _guard: &ContextGuard) -> Result { Ok(Self(data.0.to_string_lossy().to_string())) } - fn deserialize(self, _ctx: &dyn Any) -> Result { + fn deserialize(self, _guard: &ContextGuard) -> Result { Ok(UnCacheableData(PathBuf::from(&self.0))) } } diff --git a/crates/rspack_cacheable_test/tests/with/custom.rs b/crates/rspack_cacheable_test/tests/with/custom.rs index b47dea864d72..10f35a165000 100644 --- a/crates/rspack_cacheable_test/tests/with/custom.rs +++ b/crates/rspack_cacheable_test/tests/with/custom.rs @@ -1,7 +1,7 @@ -use std::{any::Any, path::PathBuf}; +use std::path::PathBuf; use rspack_cacheable::{ - Error, enable_cacheable as cacheable, + ContextGuard, Result, enable_cacheable as cacheable, with::{Custom, CustomConverter}, }; @@ -11,10 +11,10 @@ struct Data(PathBuf); impl CustomConverter for Data { type Target = String; - fn serialize(&self, _ctx: &dyn Any) -> Result { + fn serialize(&self, _guard: &ContextGuard) -> Result { Ok(self.0.to_string_lossy().to_string()) } - fn deserialize(data: Self::Target, _ctx: &dyn Any) -> Result { + fn deserialize(data: Self::Target, _guard: &ContextGuard) -> Result { Ok(Data(PathBuf::from(&data))) } } diff --git a/crates/rspack_core/src/cache/persistent/cacheable_context.rs b/crates/rspack_core/src/cache/persistent/cacheable_context.rs index 96838b089dc1..b2e919abb23d 100644 --- a/crates/rspack_core/src/cache/persistent/cacheable_context.rs +++ b/crates/rspack_core/src/cache/persistent/cacheable_context.rs @@ -1,2 +1,8 @@ #[derive(Debug)] pub struct CacheableContext; + +impl rspack_cacheable::CacheableContext for CacheableContext { + fn project_root(&self) -> Option<&std::path::Path> { + None + } +} diff --git a/crates/rspack_core/src/module_profile.rs b/crates/rspack_core/src/module_profile.rs index 46ff39ae2714..71da68128ffd 100644 --- a/crates/rspack_core/src/module_profile.rs +++ b/crates/rspack_core/src/module_profile.rs @@ -1,7 +1,7 @@ use std::time::Instant; use rspack_cacheable::{ - cacheable, + ContextGuard, Result, cacheable, with::{Custom, CustomConverter}, }; @@ -17,13 +17,10 @@ enum ProfileState { impl CustomConverter for ProfileState { type Target = Option; - fn serialize(&self, _ctx: &dyn std::any::Any) -> Result { + fn serialize(&self, _guard: &ContextGuard) -> Result { Ok(self.duration()) } - fn deserialize( - data: Self::Target, - _ctx: &dyn std::any::Any, - ) -> Result { + fn deserialize(data: Self::Target, _guard: &ContextGuard) -> Result { if let Some(time) = data { Ok(ProfileState::Finish(time)) } else { From 0d1d58f8b877a0869e6af78b8819fa37fc272a95 Mon Sep 17 00:00:00 2001 From: jinrui Date: Fri, 9 Jan 2026 14:20:23 +0800 Subject: [PATCH 32/87] feat: rspack_cacheable add portable path & portable string (#12688) feat: add portable path & portable string --- Cargo.lock | 2 + crates/rspack_cacheable/Cargo.toml | 2 + crates/rspack_cacheable/src/lib.rs | 4 +- crates/rspack_cacheable/src/utils/mod.rs | 4 + .../src/utils/portable_path.rs | 77 ++++++++ .../src/utils/portable_string.rs | 167 ++++++++++++++++++ .../src/with/as_preset/camino.rs | 45 +++-- .../src/with/as_preset/rspack_resolver.rs | 62 ++++--- .../macro/disable_cacheable/with_macro.rs | 4 +- .../rspack_cacheable_test/tests/utils/mod.rs | 2 + .../tests/utils/portable_path.rs | 102 +++++++++++ .../tests/utils/portable_string.rs | 149 ++++++++++++++++ .../tests/with/as_inner.rs | 5 +- .../tests/with/as_map.rs | 5 +- .../tests/with/as_preset/camino.rs | 37 +++- .../tests/with/as_string.rs | 5 +- .../tests/with/as_tuple2.rs | 5 +- .../tests/with/as_tuple3.rs | 5 +- .../tests/with/as_vec.rs | 5 +- 19 files changed, 626 insertions(+), 61 deletions(-) create mode 100644 crates/rspack_cacheable/src/utils/portable_path.rs create mode 100644 crates/rspack_cacheable/src/utils/portable_string.rs create mode 100644 crates/rspack_cacheable_test/tests/utils/portable_path.rs create mode 100644 crates/rspack_cacheable_test/tests/utils/portable_string.rs diff --git a/Cargo.lock b/Cargo.lock index 17bad5f159aa..13065d5a77ab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3738,6 +3738,7 @@ dependencies = [ "json", "lightningcss", "once_cell", + "regex", "rkyv 0.8.8", "rspack-allocative", "rspack_cacheable_macros", @@ -3745,6 +3746,7 @@ dependencies = [ "rspack_sources", "serde_json", "smol_str", + "sugar_path", "swc_core", "ustr-fxhash", "xxhash-rust", diff --git a/crates/rspack_cacheable/Cargo.toml b/crates/rspack_cacheable/Cargo.toml index b816e36abe7c..93ca8fa9fbca 100644 --- a/crates/rspack_cacheable/Cargo.toml +++ b/crates/rspack_cacheable/Cargo.toml @@ -19,12 +19,14 @@ inventory = { workspace = true } json = { workspace = true } lightningcss = { workspace = true } once_cell = { workspace = true } +regex = { workspace = true } rkyv = { workspace = true } rspack_cacheable_macros = { workspace = true } rspack_resolver = { workspace = true } rspack_sources = { workspace = true } serde_json = { workspace = true } smol_str = { workspace = true } +sugar_path = { workspace = true } swc_core = { workspace = true, features = ["ecma_ast"] } ustr = { workspace = true } xxhash-rust = { workspace = true, features = ["const_xxh64"] } diff --git a/crates/rspack_cacheable/src/lib.rs b/crates/rspack_cacheable/src/lib.rs index 71357875aab8..75574462fbe8 100644 --- a/crates/rspack_cacheable/src/lib.rs +++ b/crates/rspack_cacheable/src/lib.rs @@ -30,7 +30,7 @@ pub mod __private { pub use deserialize::from_bytes; #[cfg(feature = "noop")] pub fn from_bytes(_bytes: &[u8], _context: &C) -> Result { - let _ = deserialize::from_bytes::; + let _ = deserialize::from_bytes::; panic!("Cannot use from_bytes when noop feature is enabled") } @@ -38,7 +38,7 @@ pub fn from_bytes(_bytes: &[u8], _context: &C) -> Result pub use serialize::to_bytes; #[cfg(feature = "noop")] pub fn to_bytes(_value: &T, _ctx: &C) -> Result> { - let _ = serialize::to_bytes::; + let _ = serialize::to_bytes::; panic!("Cannot use to_bytes when noop feature is enabled") } diff --git a/crates/rspack_cacheable/src/utils/mod.rs b/crates/rspack_cacheable/src/utils/mod.rs index 5abdf43e1548..86102b1de940 100644 --- a/crates/rspack_cacheable/src/utils/mod.rs +++ b/crates/rspack_cacheable/src/utils/mod.rs @@ -1,3 +1,7 @@ mod owned_or_ref; +mod portable_path; +mod portable_string; pub use owned_or_ref::OwnedOrRef; +pub use portable_path::PortablePath; +pub use portable_string::PortableString; diff --git a/crates/rspack_cacheable/src/utils/portable_path.rs b/crates/rspack_cacheable/src/utils/portable_path.rs new file mode 100644 index 000000000000..0238f2468bc7 --- /dev/null +++ b/crates/rspack_cacheable/src/utils/portable_path.rs @@ -0,0 +1,77 @@ +use std::path::Path; + +use sugar_path::SugarPath; + +use crate::{ContextGuard, Result, cacheable, with::AsConverter}; + +/// A portable path representation that can be serialized and deserialized across different +/// environments with different project roots. +/// +/// When serializing with a `project_root`, absolute paths are converted to relative paths. +/// When deserializing, relative paths are resolved back to absolute paths. +/// +/// # Example +/// +/// ```rust,ignore +/// // Serialize on Linux (project_root = /home/user/project) +/// let path = PathBuf::from("/home/user/project/src/main.rs"); +/// // Stored as: "src/main.rs" (relative) +/// +/// // Deserialize on Windows (project_root = C:\workspace) +/// // Results in: "C:\workspace\src\main.rs" +/// ``` +#[cacheable(crate=crate, hashable)] +pub struct PortablePath { + path: String, + /// Whether the path was transformed to relative during serialization + transformed: bool, +} + +impl PortablePath { + /// Create a portable path, converting to relative if both path and project_root are absolute + pub fn new(path: &Path, project_root: Option<&Path>) -> Self { + if path.is_absolute() + && let Some(project_root) = project_root + { + return Self { + path: path.relative(project_root).to_slash_lossy().into_owned(), + transformed: true, + }; + } + + Self { + path: path.to_slash_lossy().into_owned(), + transformed: false, + } + } + + /// Convert back to path string using project_root if the path was transformed + pub fn into_path_string(self, project_root: Option<&Path>) -> String { + if self.transformed + && let Some(project_root) = project_root + { + return self + .path + .absolutize_with(project_root) + .to_string_lossy() + .into_owned(); + } + self.path + } +} + +impl AsConverter for PortablePath +where + T: From + AsRef, +{ + fn serialize(data: &T, guard: &ContextGuard) -> Result + where + Self: Sized, + { + Ok(Self::new(data.as_ref(), guard.project_root())) + } + + fn deserialize(self, guard: &ContextGuard) -> Result { + Ok(T::from(self.into_path_string(guard.project_root()))) + } +} diff --git a/crates/rspack_cacheable/src/utils/portable_string.rs b/crates/rspack_cacheable/src/utils/portable_string.rs new file mode 100644 index 000000000000..f0a7fac6291a --- /dev/null +++ b/crates/rspack_cacheable/src/utils/portable_string.rs @@ -0,0 +1,167 @@ +use std::{path::Path, sync::LazyLock}; + +use regex::Regex; +use sugar_path::SugarPath; + +use crate::{ContextGuard, Result, cacheable, with::AsConverter}; + +static PATH_REGEX: LazyLock = LazyLock::new(|| { + #[cfg(windows)] + { + Regex::new(r"(^|[^a-zA-Z0-9./\\])([a-zA-Z]:\\([^/\\ \t\n\r?=,;:#&|!]+\\)*)") + .expect("Invalid regex pattern") + } + #[cfg(not(windows))] + { + Regex::new(r"(^|[^a-zA-Z0-9./\\])(/([^/\\ \t\n\r?=,;:#&|!]+/)*)") + .expect("Invalid regex pattern") + } +}); + +const PROJECT_ROOT_PLACEHOLDER: &str = ""; + +static PROJECT_ROOT_PATH_REGEX: LazyLock = LazyLock::new(|| { + let pattern = format!( + r"{}/(([^/\\ \t\n\r?=,;:#&|!]+/)*)", + regex::escape(PROJECT_ROOT_PLACEHOLDER) + ); + Regex::new(&pattern).expect("Invalid regex pattern") +}); + +/// A portable string representation that can detect and convert absolute paths within +/// the string to portable format using `` placeholder for cross-platform serialization. +/// +/// # Serialization Strategy +/// +/// Absolute paths are replaced with `` prefix: +/// - `/home/user/project/src/` → `/src/` +/// - `C:\Users\project\src\` → `/src/` +/// +/// Paths outside project_root use relative paths with `..`: +/// - `/home/user/other/lib/` → `/../other/lib/` +/// +/// # Deserialization Strategy +/// +/// Replace `` with actual project_root and normalize: +/// - `/src/` + `/home/user/project` → `/home/user/project/src/` +/// - `/../other/lib/` + `/home/user/project` → `/home/user/other/lib/` +/// +/// # Use Cases +/// +/// - Module identifiers containing paths: `"ignored|/home/user/project/src/"` +/// - Cache keys with paths: `"/absolute/path/to/module/|hash_value"` +/// - Composite identifiers: `"module_type|/path/file/|layer"` +/// - Multiple paths: `"ignored|/home/aaa/?name=/home/bbb/"` +/// +/// # Example +/// +/// ```rust,ignore +/// // Serialize on Linux (project_root = /home/user/project) +/// let identifier = "ignored|/home/user/project/src/"; +/// // Stored as: "ignored|/src/" +/// +/// // Deserialize on Windows (project_root = C:\workspace) +/// // Results in: "ignored|C:\workspace\src\" +/// ``` +#[cacheable(crate=crate, hashable)] +pub struct PortableString { + /// The string with paths converted to portable format using placeholder + content: String, +} + +impl PortableString { + /// Create a portable string, converting absolute paths to use placeholder + pub fn new(content: &str, project_root: Option<&Path>) -> Self { + let Some(project_root) = project_root else { + return Self { + content: content.to_string(), + }; + }; + + let mut result = String::with_capacity(content.len()); + let mut last_end = 0; + + for cap in PATH_REGEX.captures_iter(content) { + let path_match = cap.get(2).expect("PATH_REGEX should have capture group 2"); + + result.push_str(&content[last_end..path_match.start()]); + + // Convert to portable format with placeholder + let relative_path = path_match + .as_str() + .relative(project_root) + .to_slash_lossy() + .to_string(); + let portable_path = if relative_path.is_empty() || relative_path == "." { + format!("{}/", PROJECT_ROOT_PLACEHOLDER) + } else { + format!("{}/{}/", PROJECT_ROOT_PLACEHOLDER, relative_path) + }; + result.push_str(&portable_path); + + last_end = path_match.end(); + } + + // Add remaining content + result.push_str(&content[last_end..]); + + Self { content: result } + } + + /// Convert back to string, replacing with actual project_root + pub fn into_path_string(self, project_root: Option<&Path>) -> String { + let Some(project_root) = project_root else { + return self.content; + }; + + if !self.content.contains(PROJECT_ROOT_PLACEHOLDER) { + return self.content; + } + + let content = &self.content; + let project_root_str = project_root.to_slash_lossy(); + let mut result = String::with_capacity(content.len()); + let mut last_end = 0; + + for cap in PROJECT_ROOT_PATH_REGEX.captures_iter(content) { + let full_match = cap + .get(0) + .expect("PROJECT_ROOT_PATH_REGEX should have capture group 0"); + let relative_match = cap + .get(1) + .expect("PROJECT_ROOT_PATH_REGEX should have capture group 1"); + + // Add content before this match including the prefix + result.push_str(&content[last_end..full_match.start()]); + + // Convert to absolute path + let abs_path = format!("{}/{}", &project_root_str, relative_match.as_str()).normalize(); + + result.push_str(&abs_path.to_string_lossy()); + if !abs_path.ends_with(std::path::MAIN_SEPARATOR_STR) { + result.push(std::path::MAIN_SEPARATOR); + } + last_end = full_match.end(); + } + + result.push_str(&content[last_end..]); + + result + } +} + +impl AsConverter for PortableString +where + T: From + AsRef, +{ + fn serialize(data: &T, guard: &ContextGuard) -> Result + where + Self: Sized, + { + Ok(Self::new(data.as_ref(), guard.project_root())) + } + + fn deserialize(self, guard: &ContextGuard) -> Result { + Ok(T::from(self.into_path_string(guard.project_root()))) + } +} diff --git a/crates/rspack_cacheable/src/with/as_preset/camino.rs b/crates/rspack_cacheable/src/with/as_preset/camino.rs index ddb7b389f1f0..0030480e542d 100644 --- a/crates/rspack_cacheable/src/with/as_preset/camino.rs +++ b/crates/rspack_cacheable/src/with/as_preset/camino.rs @@ -1,41 +1,56 @@ use camino::Utf8PathBuf; use rkyv::{ - Place, - rancor::{Fallible, Source}, - ser::Writer, - string::{ArchivedString, StringResolver}, + Archive, Archived, Deserialize, Place, Resolver, Serialize, + de::Pooling, + rancor::Fallible, + ser::{Sharing, Writer}, with::{ArchiveWith, DeserializeWith, SerializeWith}, }; use super::AsPreset; +use crate::{ContextGuard, Error, utils::PortablePath}; + +pub struct PathResolver { + inner: Resolver, + path: PortablePath, +} impl ArchiveWith for AsPreset { - type Archived = ArchivedString; - type Resolver = StringResolver; + type Archived = Archived; + type Resolver = PathResolver; #[inline] - fn resolve_with(field: &Utf8PathBuf, resolver: Self::Resolver, out: Place) { - ArchivedString::resolve_from_str(field.as_str(), resolver, out); + fn resolve_with(_field: &Utf8PathBuf, resolver: Self::Resolver, out: Place) { + let PathResolver { inner, path } = resolver; + Archive::resolve(&path, inner, out); } } impl SerializeWith for AsPreset where - S: ?Sized + Fallible + Writer, - S::Error: Source, + S: ?Sized + Fallible + Writer + Sharing, { #[inline] fn serialize_with(field: &Utf8PathBuf, serializer: &mut S) -> Result { - ArchivedString::serialize_from_str(field.as_str(), serializer) + let guard = ContextGuard::sharing_guard(serializer)?; + let portable_path = PortablePath::new(field.as_ref(), guard.project_root()); + Ok(PathResolver { + inner: Serialize::serialize(&portable_path, serializer)?, + path: portable_path, + }) } } -impl DeserializeWith for AsPreset +impl DeserializeWith, Utf8PathBuf, D> for AsPreset where - D: ?Sized + Fallible, + D: ?Sized + Fallible + Pooling, { #[inline] - fn deserialize_with(field: &ArchivedString, _: &mut D) -> Result { - Ok(Utf8PathBuf::from(field.as_str())) + fn deserialize_with(field: &Archived, de: &mut D) -> Result { + let portable_path: PortablePath = Deserialize::deserialize(field, de)?; + let guard = ContextGuard::pooling_guard(de)?; + Ok(Utf8PathBuf::from( + portable_path.into_path_string(guard.project_root()), + )) } } diff --git a/crates/rspack_cacheable/src/with/as_preset/rspack_resolver.rs b/crates/rspack_cacheable/src/with/as_preset/rspack_resolver.rs index 4fd55273aa38..714893fb0e54 100644 --- a/crates/rspack_cacheable/src/with/as_preset/rspack_resolver.rs +++ b/crates/rspack_cacheable/src/with/as_preset/rspack_resolver.rs @@ -1,24 +1,26 @@ use rkyv::{ - Archive, Deserialize, Place, Portable, + Archive, Archived, Deserialize, Place, Portable, Resolver, bytecheck::{CheckBytes, StructCheckContext}, - rancor::{Fallible, Source, Trace}, - ser::Writer, - string::{ArchivedString, StringResolver}, + de::Pooling, + rancor::{Fallible, Trace}, + ser::{Sharing, Writer}, with::{ArchiveWith, DeserializeWith, SerializeWith}, }; use rspack_resolver::AliasValue; use super::AsPreset; +use crate::{ContextGuard, Error, utils::PortablePath}; pub struct ArchivedAliasValue { is_ignore: bool, - path: ArchivedString, + path: Archived, } unsafe impl Portable for ArchivedAliasValue {} pub struct AliasValueResolver { - path: StringResolver, + inner: Resolver, + path: PortablePath, } impl ArchiveWith for AsPreset { @@ -27,42 +29,40 @@ impl ArchiveWith for AsPreset { #[inline] fn resolve_with(field: &AliasValue, resolver: Self::Resolver, out: Place) { + let AliasValueResolver { inner, path } = resolver; let field_ptr = unsafe { &raw mut (*out.ptr()).is_ignore }; let field_out = unsafe { Place::from_field_unchecked(out, field_ptr) }; let is_ignore = matches!(field, AliasValue::Ignore); is_ignore.resolve((), field_out); let field_ptr = unsafe { &raw mut (*out.ptr()).path }; let field_out = unsafe { Place::from_field_unchecked(out, field_ptr) }; - let path = if let AliasValue::Path(path) = field { - path - } else { - "" - }; - ArchivedString::resolve_from_str(path, resolver.path, field_out); + Archive::resolve(&path, inner, field_out); } } impl SerializeWith for AsPreset where - S: Fallible + Writer + ?Sized, - S::Error: Source, + S: Fallible + Writer + Sharing + ?Sized, { #[inline] fn serialize_with(field: &AliasValue, serializer: &mut S) -> Result { - let path = if let AliasValue::Path(path) = field { - path + let guard = ContextGuard::sharing_guard(serializer)?; + let path_str = if let AliasValue::Path(path) = field { + path.as_str() } else { "" }; + let portable_path = PortablePath::new(path_str.as_ref(), guard.project_root()); Ok(AliasValueResolver { - path: ArchivedString::serialize_from_str(path, serializer)?, + inner: rkyv::Serialize::serialize(&portable_path, serializer)?, + path: portable_path, }) } } unsafe impl CheckBytes for ArchivedAliasValue where - ArchivedString: CheckBytes, + Archived: CheckBytes, C: Fallible + ?Sized, C::Error: Trace, bool: CheckBytes, @@ -80,15 +80,17 @@ where })?; } unsafe { - ArchivedString::check_bytes(core::ptr::addr_of!((*value).path), context).map_err(|e| { - ::trace( - e, - StructCheckContext { - struct_name: "ArchivedAliasValue", - field_name: "path", - }, - ) - })?; + >::check_bytes(core::ptr::addr_of!((*value).path), context).map_err( + |e| { + ::trace( + e, + StructCheckContext { + struct_name: "ArchivedAliasValue", + field_name: "path", + }, + ) + }, + )?; } Ok(()) } @@ -96,7 +98,7 @@ where impl DeserializeWith for AsPreset where - D: ?Sized + Fallible, + D: Fallible + Pooling + ?Sized, { fn deserialize_with( field: &ArchivedAliasValue, @@ -105,7 +107,9 @@ where Ok(if field.is_ignore { AliasValue::Ignore } else { - AliasValue::Path(field.path.deserialize(deserializer)?) + let portable_path: PortablePath = Deserialize::deserialize(&field.path, deserializer)?; + let guard = ContextGuard::pooling_guard(deserializer)?; + AliasValue::Path(portable_path.into_path_string(guard.project_root())) }) } } diff --git a/crates/rspack_cacheable_test/tests/macro/disable_cacheable/with_macro.rs b/crates/rspack_cacheable_test/tests/macro/disable_cacheable/with_macro.rs index a312c6481b65..b378d44e1593 100644 --- a/crates/rspack_cacheable_test/tests/macro/disable_cacheable/with_macro.rs +++ b/crates/rspack_cacheable_test/tests/macro/disable_cacheable/with_macro.rs @@ -1,10 +1,10 @@ use std::path::PathBuf; -use rspack_cacheable::{disable_cacheable, with::AsString}; +use rspack_cacheable::{disable_cacheable, utils::PortablePath, with::As}; #[disable_cacheable] struct FileInfo { - #[cacheable(with=AsString)] + #[cacheable(with=As)] path: PathBuf, } diff --git a/crates/rspack_cacheable_test/tests/utils/mod.rs b/crates/rspack_cacheable_test/tests/utils/mod.rs index f3eb666f43d3..ee8ea2fb618d 100644 --- a/crates/rspack_cacheable_test/tests/utils/mod.rs +++ b/crates/rspack_cacheable_test/tests/utils/mod.rs @@ -1 +1,3 @@ mod owned_or_ref; +mod portable_path; +mod portable_string; diff --git a/crates/rspack_cacheable_test/tests/utils/portable_path.rs b/crates/rspack_cacheable_test/tests/utils/portable_path.rs new file mode 100644 index 000000000000..dbb1a6b3ecab --- /dev/null +++ b/crates/rspack_cacheable_test/tests/utils/portable_path.rs @@ -0,0 +1,102 @@ +use std::path::{Path, PathBuf}; + +use camino::Utf8PathBuf; +use rspack_cacheable::{CacheableContext, cacheable, utils::PortablePath, with::As}; + +/// Test context with project_root +struct TestContext(Option); + +impl CacheableContext for TestContext { + fn project_root(&self) -> Option<&Path> { + self.0.as_deref() + } +} + +/// Test struct with multiple paths +#[cacheable] +#[derive(Debug, PartialEq, Eq)] +struct PathData { + #[cacheable(with=As)] + path1: PathBuf, + #[cacheable(with=As)] + path2: Utf8PathBuf, +} + +#[test] +#[cfg(not(windows))] +fn test_with_context() { + let context = TestContext(Some(PathBuf::from("/home/user/project"))); + let new_context = TestContext(Some(PathBuf::from("/new/location"))); + + // Test path inside project_root + let inside_path = PathData { + path1: PathBuf::from("/home/user/project/src/main.rs"), + path2: Utf8PathBuf::from("/home/user/project/src/lib.rs"), + }; + + let bytes = rspack_cacheable::to_bytes(&inside_path, &context).unwrap(); + let new_data: PathData = rspack_cacheable::from_bytes(&bytes, &new_context).unwrap(); + assert_eq!(new_data.path1, PathBuf::from("/new/location/src/main.rs")); + assert_eq!(new_data.path2, PathBuf::from("/new/location/src/lib.rs")); + + // Test path outside project_root (now uses relative paths with ..) + let outside_path = PathData { + path1: PathBuf::from("/usr/lib/a.so"), + path2: Utf8PathBuf::from("/usr/lib/src/b.txt"), + }; + let bytes = rspack_cacheable::to_bytes(&outside_path, &context).unwrap(); + let new_data: PathData = rspack_cacheable::from_bytes(&bytes, &new_context).unwrap(); + // The paths are now relative to project_root, so they get translated + // /usr/lib/a.so relative to /home/user/project is ../../../usr/lib/a.so + // When deserialized with /new/location as project_root: + // /new/location/../../../usr/lib/a.so => /usr/lib/a.so (after normalization) + assert_eq!(new_data, outside_path); +} + +#[test] +#[cfg(not(windows))] +fn test_relative_path_outside_project() { + // Test that paths outside project_root are converted to relative paths with ".." + let context = TestContext(Some(PathBuf::from("/home/user/project"))); + + let data = PathData { + // /home/other/file.txt relative to /home/user/project => ../../other/file.txt + path1: PathBuf::from("/home/other/file.txt"), + // /etc/config.ini relative to /home/user/project => ../../../etc/config.ini + path2: Utf8PathBuf::from("/etc/config.ini"), + }; + + let bytes = rspack_cacheable::to_bytes(&data, &context).unwrap(); + + // Deserialize with different project_root + let new_context = TestContext(Some(PathBuf::from("/workspace/app"))); + let new_data: PathData = rspack_cacheable::from_bytes(&bytes, &new_context).unwrap(); + + // Paths maintain their relative structure from project_root: + // ../../other/file.txt from /workspace/app => /workspace/other/file.txt + // But due to normalization: /workspace/app/../../other/file.txt => /other/file.txt + assert_eq!(new_data.path1, PathBuf::from("/other/file.txt")); + // ../../../etc/config.ini from /workspace/app => /etc/config.ini + assert_eq!(new_data.path2, PathBuf::from("/etc/config.ini")); +} + +#[test] +#[cfg(windows)] +fn test_windows_path() { + let context = TestContext(Some(PathBuf::from("C:\\Users\\test\\project"))); + + let data = PathData { + path1: PathBuf::from("C:\\Users\\test\\project\\src\\main.rs"), + path2: Utf8PathBuf::from("C:\\Users\\test\\project\\src\\lib.rs"), + }; + + let bytes = rspack_cacheable::to_bytes(&data, &context).unwrap(); + + // Deserialize on different Windows path + let new_context = TestContext(Some(PathBuf::from("D:\\workspace"))); + let new_data: PathData = rspack_cacheable::from_bytes(&bytes, &new_context).unwrap(); + + // Path separators should be normalized + assert_eq!(new_data.path1, PathBuf::from("D:\\workspace\\src\\main.rs")); + assert_eq!(new_data.path2, PathBuf::from("D:\\workspace\\src\\lib.rs")); +} diff --git a/crates/rspack_cacheable_test/tests/utils/portable_string.rs b/crates/rspack_cacheable_test/tests/utils/portable_string.rs new file mode 100644 index 000000000000..6b33aea3ab7a --- /dev/null +++ b/crates/rspack_cacheable_test/tests/utils/portable_string.rs @@ -0,0 +1,149 @@ +use std::path::{Path, PathBuf}; + +use rspack_cacheable::{ + CacheableContext, cacheable, + utils::PortableString, + with::{As, AsVec}, +}; + +/// Test context with project_root +struct TestContext(Option); + +impl CacheableContext for TestContext { + fn project_root(&self) -> Option<&Path> { + self.0.as_deref() + } +} + +/// Test struct with string identifiers containing paths +#[cacheable] +#[derive(Debug, PartialEq, Eq)] +struct Data { + #[cacheable(with=AsVec>)] + paths: Vec, +} + +#[test] +#[cfg(not(windows))] +fn test_basic_feature() { + let context = TestContext(Some(PathBuf::from("/home/user/project"))); + + let data = Data { + paths: vec![ + "ignored|/home/user/project/src/".into(), + "ignored|/home/user/project/src/a.js".into(), + "home/home/user/project/src/".into(), + "/home/user/project/src/".into(), + "/home/user/project/a.js".into(), + "/home/user/project/src/a.js".into(), + "ignored|/home/user/project/a/ other|/home/user/project/b/c.js".into(), + "ignored|/home/user/aaa/?name=/home/user/bbb/d.txt".into(), + "javascript/auto|/home/user/project/src/|layer1".into(), + "just a regular string without any paths".into(), + "/home/user/project/src/文本.txt".into(), + "ignored|./a/b/c/d?query=./e/f/g".into(), + "/home/user/project/src/loader.js!/home/user/project/index.js".into(), + "/home/user".into(), + "/home".into(), + "/root".into(), + ], + }; + + let bytes = rspack_cacheable::to_bytes(&data, &context).unwrap(); + + // Deserialize with different project_root + let new_context = TestContext(Some(PathBuf::from("/workspace"))); + let new_data: Data = rspack_cacheable::from_bytes(&bytes, &new_context).unwrap(); + + assert_eq!( + new_data.paths, + vec![ + "ignored|/workspace/src/", + "ignored|/workspace/src/a.js", + "home/home/user/project/src/", + "/workspace/src/", + "/workspace/a.js", + "/workspace/src/a.js", + "ignored|/workspace/a/ other|/workspace/b/c.js", + "ignored|/aaa/?name=/bbb/d.txt", + "javascript/auto|/workspace/src/|layer1", + "just a regular string without any paths", + "/workspace/src/文本.txt", + "ignored|./a/b/c/d?query=./e/f/g", + "/workspace/src/loader.js!/workspace/index.js", + "/user", + "/home", + "/root" + ] + ); +} + +#[test] +#[cfg(not(windows))] +fn test_no_project_root() { + let context = TestContext(None); + + let data = Data { + paths: vec!["ignored|/home/user/project/src/main.rs".into()], + }; + + let bytes = rspack_cacheable::to_bytes(&data, &context).unwrap(); + let new_data: Data = rspack_cacheable::from_bytes(&bytes, &context).unwrap(); + + // Without project_root, paths should remain unchanged + assert_eq!(new_data.paths, data.paths); +} + +#[test] +#[cfg(windows)] +fn test_windows() { + let context = TestContext(Some(PathBuf::from("C:\\Users\\project"))); + + let data = Data { + paths: vec![ + "ignored|C:\\Users\\project\\src\\".into(), + "ignored|C:\\Users\\project\\src\\a.js".into(), + "cC:\\Users\\project\\src\\".into(), + "C:\\Users\\project\\src\\".into(), + "C:\\Users\\project\\a.js".into(), + "C:\\Users\\project\\src\\a.js".into(), + "ignored|C:\\Users\\project\\a\\ other|C:\\Users\\project\\b\\c.js".into(), + "ignored|C:\\Users\\aaa\\?name=C:\\Users\\bbb\\d.txt".into(), + "javascript/auto|C:\\Users\\project\\src\\|layer1".into(), + "just a regular string without any paths".into(), + "C:\\Users\\project\\src\\文本.txt".into(), + "ignored|.\\a\\b\\c\\d?query=.\\e\\f\\g".into(), + "C:\\Users\\project\\src\\loader.js!C:\\Users\\project\\index.js".into(), + "C:\\Users".into(), + "C:\\".into(), + "C:\\Windows".into(), + ], + }; + + let bytes = rspack_cacheable::to_bytes(&data, &context).unwrap(); + + let new_context = TestContext(Some(PathBuf::from("D:\\other"))); + let new_data: Data = rspack_cacheable::from_bytes(&bytes, &new_context).unwrap(); + + assert_eq!( + new_data.paths, + vec![ + "ignored|D:\\other\\src\\", + "ignored|D:\\other\\src\\a.js", + "cC:\\Users\\project\\src\\", + "D:\\other\\src\\", + "D:\\other\\a.js", + "D:\\other\\src\\a.js", + "ignored|D:\\other\\a\\ other|D:\\other\\b\\c.js", + "ignored|D:\\aaa\\?name=D:\\bbb\\d.txt", + "javascript/auto|D:\\other\\src\\|layer1", + "just a regular string without any paths", + "D:\\other\\src\\文本.txt", + "ignored|.\\a\\b\\c\\d?query=.\\e\\f\\g", + "D:\\other\\src\\loader.js!D:\\other\\index.js", + "D:\\Users".into(), + "D:\\".into(), + "D:\\Windows".into(), + ] + ); +} diff --git a/crates/rspack_cacheable_test/tests/with/as_inner.rs b/crates/rspack_cacheable_test/tests/with/as_inner.rs index 667ca8ca38b9..e3f5f2f534f1 100644 --- a/crates/rspack_cacheable_test/tests/with/as_inner.rs +++ b/crates/rspack_cacheable_test/tests/with/as_inner.rs @@ -2,13 +2,14 @@ use std::{path::PathBuf, sync::Arc}; use rspack_cacheable::{ enable_cacheable as cacheable, - with::{AsInner, AsString}, + utils::PortablePath, + with::{As, AsInner}, }; #[cacheable] #[derive(Debug, PartialEq, Eq)] struct Data { - #[cacheable(with=AsInner)] + #[cacheable(with=AsInner>)] block1: once_cell::sync::OnceCell, #[cacheable(with=AsInner)] block2: once_cell::sync::OnceCell, diff --git a/crates/rspack_cacheable_test/tests/with/as_map.rs b/crates/rspack_cacheable_test/tests/with/as_map.rs index 58ea46312032..298a5a3c40b7 100644 --- a/crates/rspack_cacheable_test/tests/with/as_map.rs +++ b/crates/rspack_cacheable_test/tests/with/as_map.rs @@ -3,7 +3,8 @@ use std::path::PathBuf; use dashmap::DashMap; use rspack_cacheable::{ enable_cacheable as cacheable, - with::{AsCacheable, AsMap, AsString}, + utils::PortablePath, + with::{As, AsCacheable, AsMap}, }; use rustc_hash::FxHashMap; @@ -21,7 +22,7 @@ struct Module { #[derive(Debug)] struct App { modules: FxHashMap, - #[cacheable(with=AsMap)] + #[cacheable(with=AsMap>)] paths: DashMap, } diff --git a/crates/rspack_cacheable_test/tests/with/as_preset/camino.rs b/crates/rspack_cacheable_test/tests/with/as_preset/camino.rs index 9ceb48d897a2..64d2af355087 100644 --- a/crates/rspack_cacheable_test/tests/with/as_preset/camino.rs +++ b/crates/rspack_cacheable_test/tests/with/as_preset/camino.rs @@ -1,5 +1,9 @@ +use std::path::PathBuf; + use camino::Utf8PathBuf; -use rspack_cacheable::{enable_cacheable as cacheable, from_bytes, to_bytes, with::AsPreset}; +use rspack_cacheable::{ + CacheableContext, enable_cacheable as cacheable, from_bytes, to_bytes, with::AsPreset, +}; #[cacheable] #[derive(Debug, PartialEq, Eq)] @@ -8,6 +12,16 @@ struct Module { path: Utf8PathBuf, } +struct Context { + project_root: PathBuf, +} + +impl CacheableContext for Context { + fn project_root(&self) -> Option<&std::path::Path> { + Some(&self.project_root) + } +} + #[test] fn test_preset_camino() { let module = Module { @@ -17,4 +31,25 @@ fn test_preset_camino() { let bytes = to_bytes(&module, &()).unwrap(); let new_module: Module = from_bytes(&bytes, &()).unwrap(); assert_eq!(module, new_module); + + // test with context + let context = Context { + project_root: PathBuf::from("/home"), + }; + let bytes = to_bytes(&module, &context).unwrap(); + let new_module: Module = from_bytes(&bytes, &context).unwrap(); + assert_eq!(module, new_module); + + // test portable context + let other_context = Context { + project_root: PathBuf::from("/root"), + }; + let bytes = to_bytes(&module, &context).unwrap(); + let new_module: Module = from_bytes(&bytes, &other_context).unwrap(); + assert_eq!( + Module { + path: Utf8PathBuf::from("/root/user") + }, + new_module + ); } diff --git a/crates/rspack_cacheable_test/tests/with/as_string.rs b/crates/rspack_cacheable_test/tests/with/as_string.rs index 97064043b0bb..dcfa021ad07c 100644 --- a/crates/rspack_cacheable_test/tests/with/as_string.rs +++ b/crates/rspack_cacheable_test/tests/with/as_string.rs @@ -2,7 +2,8 @@ use std::path::PathBuf; use rspack_cacheable::{ Error, enable_cacheable as cacheable, - with::{AsString, AsStringConverter}, + utils::PortablePath, + with::{As, AsString, AsStringConverter}, }; #[cacheable(with=AsString)] @@ -30,7 +31,7 @@ impl AsStringConverter for Regex { #[cacheable] #[derive(Debug, PartialEq, Eq)] struct Module { - #[cacheable(with=AsString)] + #[cacheable(with=As)] path: PathBuf, #[cacheable(with=AsString)] regex: Regex, diff --git a/crates/rspack_cacheable_test/tests/with/as_tuple2.rs b/crates/rspack_cacheable_test/tests/with/as_tuple2.rs index 2cdff8e86229..4e02e6353ebf 100644 --- a/crates/rspack_cacheable_test/tests/with/as_tuple2.rs +++ b/crates/rspack_cacheable_test/tests/with/as_tuple2.rs @@ -2,7 +2,8 @@ use std::path::PathBuf; use rspack_cacheable::{ enable_cacheable as cacheable, - with::{AsCacheable, AsString, AsTuple2}, + utils::PortablePath, + with::{As, AsCacheable, AsTuple2}, }; #[cacheable] @@ -11,7 +12,7 @@ struct Data { param1: (u32, u32), #[cacheable(with=AsTuple2)] param2: (u32, u32), - #[cacheable(with=AsTuple2)] + #[cacheable(with=AsTuple2>)] param3: (u32, PathBuf), } diff --git a/crates/rspack_cacheable_test/tests/with/as_tuple3.rs b/crates/rspack_cacheable_test/tests/with/as_tuple3.rs index a4562e988f2a..c380b1e00560 100644 --- a/crates/rspack_cacheable_test/tests/with/as_tuple3.rs +++ b/crates/rspack_cacheable_test/tests/with/as_tuple3.rs @@ -2,7 +2,8 @@ use std::path::PathBuf; use rspack_cacheable::{ enable_cacheable as cacheable, - with::{AsCacheable, AsString, AsTuple3}, + utils::PortablePath, + with::{As, AsCacheable, AsTuple3}, }; #[cacheable] @@ -11,7 +12,7 @@ struct Data { param1: (u32, u32, u32), #[cacheable(with=AsTuple3)] param2: (u32, u32, u32), - #[cacheable(with=AsTuple3)] + #[cacheable(with=AsTuple3>)] param3: (u32, u32, PathBuf), } diff --git a/crates/rspack_cacheable_test/tests/with/as_vec.rs b/crates/rspack_cacheable_test/tests/with/as_vec.rs index 1680faffe604..8e2d994a0b04 100644 --- a/crates/rspack_cacheable_test/tests/with/as_vec.rs +++ b/crates/rspack_cacheable_test/tests/with/as_vec.rs @@ -2,7 +2,8 @@ use std::path::PathBuf; use rspack_cacheable::{ enable_cacheable as cacheable, - with::{AsString, AsVec}, + utils::PortablePath, + with::{As, AsVec}, }; use rustc_hash::FxHashSet; @@ -16,7 +17,7 @@ struct Module { #[derive(Debug, PartialEq, Eq)] struct App { modules: FxHashSet, - #[cacheable(with=AsVec)] + #[cacheable(with=AsVec>)] paths: Vec, sizes: Vec, } From b81dfa27cd51336d46b86d90a319a19569964b4c Mon Sep 17 00:00:00 2001 From: Gengkun Date: Fri, 9 Jan 2026 15:48:54 +0800 Subject: [PATCH 33/87] fix: inlined export invalid syntax comment (#12681) --- crates/rspack_core/src/concatenated_module.rs | 48 ++++++++----------- .../src/exports/export_info_getter.rs | 2 +- crates/rspack_core/src/exports/utils.rs | 8 ++-- crates/rspack_core/src/runtime_template.rs | 12 ++--- crates/rspack_plugin_esm_library/src/link.rs | 41 ++++++---------- .../common_js_export_require_dependency.rs | 8 ++-- .../common_js_full_require_dependency.rs | 8 ++-- .../common_js_self_reference_dependency.rs | 2 +- ...sm_export_imported_specifier_dependency.rs | 4 +- .../src/modern_module_library_plugin.rs | 2 +- .../src/module_library_plugin.rs | 2 +- .../configCases/inline-const/basic/index.js | 40 ++++++++-------- .../generated-syntax/constants.js | 1 + .../inline-const/generated-syntax/index.js | 13 +++++ .../generated-syntax/rspack.config.js | 9 ++++ .../inline-const/suffix-properties/index.js | 6 +-- .../inline-const/with-node-stuff/index.js | 2 +- .../configCases/inline-enum/basic/index.js | 14 +++--- .../inline-enum/const-enum-only/index.js | 4 +- .../enum-dynamically-defined/index.js | 4 +- .../inline-enum/enum-expression/index.js | 14 +++--- .../inline-enum/enum-merging/index.js | 4 +- .../member-value-undefined/only-a.js | 2 +- .../inline-enum/not-last-loader/index.js | 4 +- .../__snapshot__/e.js.txt | 2 +- .../__snapshot__/f.js.txt | 2 +- .../rsdoctor/assets/rspack.config.js | 4 +- .../async-modules/__snapshots__/esm.snap.txt | 2 +- .../__snapshots__/esm.snap.txt | 2 +- .../__snapshots__/esm.snap.txt | 6 +-- .../contains-cjs/__snapshots__/esm.snap.txt | 2 +- .../__snapshots__/esm.snap.txt | 4 +- .../__snapshots__/esm.snap.txt | 4 +- .../__snapshots__/esm.snap.txt | 4 +- .../__snapshots__/esm.snap.txt | 4 +- 35 files changed, 147 insertions(+), 143 deletions(-) create mode 100644 tests/rspack-test/configCases/inline-const/generated-syntax/constants.js create mode 100644 tests/rspack-test/configCases/inline-const/generated-syntax/index.js create mode 100644 tests/rspack-test/configCases/inline-const/generated-syntax/rspack.config.js diff --git a/crates/rspack_core/src/concatenated_module.rs b/crates/rspack_core/src/concatenated_module.rs index 30c67dce3716..27f08fecf13b 100644 --- a/crates/rspack_core/src/concatenated_module.rs +++ b/crates/rspack_core/src/concatenated_module.rs @@ -2826,15 +2826,13 @@ impl ConcatenatedModule { } UsedName::Inlined(inlined) => { return FinalBindingResult::from_binding(Binding::Raw(RawBinding { - raw_name: format!( - "{} {}", - to_normal_comment(&format!( + raw_name: inlined + .inlined_value() + .render(&to_normal_comment(&format!( "inlined export {}", property_access(&export_name, 0) - )), - inlined.inlined_value().render() - ) - .into(), + ))) + .into(), ids: inlined.suffix_ids().to_vec(), export_name, info_id: info.module, @@ -2888,15 +2886,13 @@ impl ConcatenatedModule { &export, ) { return FinalBindingResult::from_binding(Binding::Raw(RawBinding { - raw_name: format!( - "{} {}", - to_normal_comment(&format!( + raw_name: inlined + .inlined_value() + .render(&to_normal_comment(&format!( "inlined export {}", property_access(&export_name, 0) - )), - inlined.inlined_value().render() - ) - .into(), + ))) + .into(), ids: inlined.suffix_ids().to_vec(), export_name, info_id: info.module, @@ -2958,15 +2954,13 @@ impl ConcatenatedModule { // Inlined namespace export symbol is not possible for now but we compat it here UsedName::Inlined(inlined) => Binding::Raw(RawBinding { info_id: info.module, - raw_name: format!( - "{} {}", - to_normal_comment(&format!( + raw_name: inlined + .inlined_value() + .render(&to_normal_comment(&format!( "inlined export {}", property_access(&export_name, 0) - )), - inlined.inlined_value().render() - ) - .into(), + ))) + .into(), ids: inlined.suffix_ids().to_vec(), export_name, comment: None, @@ -3018,15 +3012,13 @@ impl ConcatenatedModule { "inlined export is not possible for deferred external module" ); Binding::Raw(RawBinding { - raw_name: format!( - "{} {}", - to_normal_comment(&format!( + raw_name: inlined + .inlined_value() + .render(&to_normal_comment(&format!( "inlined export {}", property_access(&export_name, 0) - )), - inlined.inlined_value().render() - ) - .into(), + ))) + .into(), ids: inlined.suffix_ids().to_vec(), export_name, info_id: info.module, diff --git a/crates/rspack_core/src/exports/export_info_getter.rs b/crates/rspack_core/src/exports/export_info_getter.rs index 1b42f50adb39..ed822e3a9fb4 100644 --- a/crates/rspack_core/src/exports/export_info_getter.rs +++ b/crates/rspack_core/src/exports/export_info_getter.rs @@ -106,7 +106,7 @@ impl ExportInfoData { pub fn get_rename_info(&self) -> Cow<'_, str> { match (self.used_name(), self.name()) { (Some(UsedNameItem::Inlined(inlined)), _) => { - return format!("inlined to {}", inlined.render()).into(); + return format!("inlined to {}", inlined.render("")).into(); } (Some(UsedNameItem::Str(used)), Some(name)) if used != name => { return format!("renamed to {used}").into(); diff --git a/crates/rspack_core/src/exports/utils.rs b/crates/rspack_core/src/exports/utils.rs index 13781615a6d8..ae234f097554 100644 --- a/crates/rspack_core/src/exports/utils.rs +++ b/crates/rspack_core/src/exports/utils.rs @@ -83,7 +83,7 @@ impl EvaluatedInlinableValue { Self::String(v) } - pub fn render(&self) -> String { + pub fn render(&self, comment: &str) -> String { let s: Cow = match self { Self::Null => "null".into(), Self::Undefined => "undefined".into(), @@ -94,7 +94,7 @@ impl EvaluatedInlinableValue { } Self::String(v) => json_stringify(v.as_str()).into(), }; - format!("({s})") + format!("({comment}{s})") } } @@ -129,8 +129,8 @@ impl InlinedUsedName { } } - pub fn render(&self) -> String { - let mut inlined = self.value.render(); + pub fn render(&self, comment: &str) -> String { + let mut inlined = self.value.render(comment); inlined.push_str(&property_access(&self.suffix, 0)); inlined } diff --git a/crates/rspack_core/src/runtime_template.rs b/crates/rspack_core/src/runtime_template.rs index 644dc5f95f20..2f9a502f63e0 100644 --- a/crates/rspack_core/src/runtime_template.rs +++ b/crates/rspack_core/src/runtime_template.rs @@ -663,14 +663,10 @@ impl RuntimeTemplate { !is_deferred, "can't inline the exports of defer imported module" ); - return format!( - "{} {}", - to_normal_comment(&format!( - "inlined export {}", - property_access(export_name, 0) - )), - inlined.render() - ); + return inlined.render(&to_normal_comment(&format!( + "inlined export {}", + property_access(export_name, 0) + ))); } None => { return format!( diff --git a/crates/rspack_plugin_esm_library/src/link.rs b/crates/rspack_plugin_esm_library/src/link.rs index ea7e2667076a..2893140e0cf9 100644 --- a/crates/rspack_plugin_esm_library/src/link.rs +++ b/crates/rspack_plugin_esm_library/src/link.rs @@ -1955,14 +1955,10 @@ var {} = {{}}; )); } UsedName::Inlined(inlined) => { - return Ref::Inline(format!( - "{} {}", - to_normal_comment(&format!( - "inlined export {}", - property_access(&export_name, 0) - )), - inlined.render() - )); + return Ref::Inline(inlined.render(&to_normal_comment(&format!( + "inlined export {}", + property_access(&export_name, 0) + )))); } } } else { @@ -2007,14 +2003,10 @@ var {} = {{}}; None, &export, ) { - return Ref::Inline(format!( - "{} {}", - to_normal_comment(&format!( - "inlined export {}", - property_access(&export_name, 0) - )), - inlined.inlined_value().render() - )); + return Ref::Inline(inlined.inlined_value().render(&to_normal_comment(&format!( + "inlined export {}", + property_access(&export_name, 0) + )))); } } panic!( @@ -2072,16 +2064,15 @@ var {} = {{}}; Arc::new(move |binding| normal_render(binding, as_call, call_context, asi_safe)), )), // Inlined namespace export symbol is not possible for now but we compat it here - UsedName::Inlined(inlined) => Ref::Inline(inlined.render()), + UsedName::Inlined(inlined) => Ref::Inline(inlined.render("")), }; } if let Some(UsedName::Inlined(inlined)) = used_name { - let comment = to_normal_comment(&format!( + return Ref::Inline(inlined.render(&to_normal_comment(&format!( "inlined export {}", property_access(&export_name, 0) - )); - return Ref::Inline(format!("{comment}{}", inlined.render())); + )))); } panic!( @@ -2112,13 +2103,9 @@ var {} = {{}}; used_name, Arc::new(move |binding| normal_render(binding, as_call, call_context, asi_safe)), )), - UsedName::Inlined(inlined) => { - let comment = to_normal_comment(&format!( - "inlined export {}", - property_access(&export_name, 0) - )); - Ref::Inline(format!("{}{comment}", inlined.render())) - } + UsedName::Inlined(inlined) => Ref::Inline(inlined.render(&to_normal_comment( + &format!("inlined export {}", property_access(&export_name, 0)), + ))), } } else { Ref::Inline("/* unused export */ undefined".into()) diff --git a/crates/rspack_plugin_javascript/src/dependency/commonjs/common_js_export_require_dependency.rs b/crates/rspack_plugin_javascript/src/dependency/commonjs/common_js_export_require_dependency.rs index 1dc33e825e07..c58597ed1c73 100644 --- a/crates/rspack_plugin_javascript/src/dependency/commonjs/common_js_export_require_dependency.rs +++ b/crates/rspack_plugin_javascript/src/dependency/commonjs/common_js_export_require_dependency.rs @@ -500,7 +500,6 @@ impl DependencyTemplate for CommonJsExportRequireDependencyTemplate { *runtime, ids, ) { - let comment = to_normal_comment(&property_access(ids, 0)); match used_imported { UsedName::Normal(used_imported) => { format!( @@ -512,11 +511,14 @@ impl DependencyTemplate for CommonJsExportRequireDependencyTemplate { &dep.request, false, ), - comment, + to_normal_comment(&property_access(ids, 0)), property_access(used_imported, 0) ) } - UsedName::Inlined(inlined) => format!("{}{}", comment, inlined.render()), + UsedName::Inlined(inlined) => inlined.render(&to_normal_comment(&format!( + "inlined export {}", + property_access(ids, 0) + ))), } } else { compilation.runtime_template.module_raw( diff --git a/crates/rspack_plugin_javascript/src/dependency/commonjs/common_js_full_require_dependency.rs b/crates/rspack_plugin_javascript/src/dependency/commonjs/common_js_full_require_dependency.rs index 0e2af5f3e4f2..8507e3926581 100644 --- a/crates/rspack_plugin_javascript/src/dependency/commonjs/common_js_full_require_dependency.rs +++ b/crates/rspack_plugin_javascript/src/dependency/commonjs/common_js_full_require_dependency.rs @@ -191,7 +191,6 @@ impl DependencyTemplate for CommonJsFullRequireDependencyTemplate { } && let Some(used) = used { - let comment = to_normal_comment(&property_access(&dep.names, 0)); let mut require_expr = match used { UsedName::Normal(used) => { format!( @@ -202,11 +201,14 @@ impl DependencyTemplate for CommonJsFullRequireDependencyTemplate { compilation .runtime_template .module_id(compilation, &dep.id, &dep.request, false), - comment, + to_normal_comment(&property_access(&dep.names, 0)), property_access(used, 0) ) } - UsedName::Inlined(inlined) => format!("{}{}", comment, inlined.render()), + UsedName::Inlined(inlined) => inlined.render(&to_normal_comment(&format!( + "inlined export {}", + property_access(&dep.names, 0) + ))), }; if dep.asi_safe { require_expr = format!("({require_expr})"); diff --git a/crates/rspack_plugin_javascript/src/dependency/commonjs/common_js_self_reference_dependency.rs b/crates/rspack_plugin_javascript/src/dependency/commonjs/common_js_self_reference_dependency.rs index bf42f62659c4..042d3c77fe70 100644 --- a/crates/rspack_plugin_javascript/src/dependency/commonjs/common_js_self_reference_dependency.rs +++ b/crates/rspack_plugin_javascript/src/dependency/commonjs/common_js_self_reference_dependency.rs @@ -198,7 +198,7 @@ impl DependencyTemplate for CommonJsSelfReferenceDependencyTemplate { UsedName::Normal(used) => format!("{}{}", base, property_access(used, 0)), // Export a inlinable const from cjs is not possible for now, so self reference a inlinable // const is also not possible for now, but we compat it here - UsedName::Inlined(inlined) => inlined.render(), + UsedName::Inlined(inlined) => inlined.render(""), }, None, ) diff --git a/crates/rspack_plugin_javascript/src/dependency/esm/esm_export_imported_specifier_dependency.rs b/crates/rspack_plugin_javascript/src/dependency/esm/esm_export_imported_specifier_dependency.rs index 2b0e5363a429..b50a9a0d6348 100644 --- a/crates/rspack_plugin_javascript/src/dependency/esm/esm_export_imported_specifier_dependency.rs +++ b/crates/rspack_plugin_javascript/src/dependency/esm/esm_export_imported_specifier_dependency.rs @@ -932,7 +932,9 @@ impl ESMExportImportedSpecifierDependency { ValueKey::Name => name, ValueKey::UsedName(used) => match used { UsedName::Normal(used) => format!("{}{}", name, property_access(used, 0)), - UsedName::Inlined(inlined) => inlined.render(), + UsedName::Inlined(inlined) => { + inlined.render(&to_normal_comment(&format!("inlined export {name}",))) + } }, } } diff --git a/crates/rspack_plugin_library/src/modern_module_library_plugin.rs b/crates/rspack_plugin_library/src/modern_module_library_plugin.rs index e2ae35a2b6c7..6b6f239c7a0b 100644 --- a/crates/rspack_plugin_library/src/modern_module_library_plugin.rs +++ b/crates/rspack_plugin_library/src/modern_module_library_plugin.rs @@ -335,7 +335,7 @@ async fn render_startup( source.add(RawStringSource::from(format!( "var {var_name} = {};\n", - inlined.render() + inlined.render("") ))); exports.push((var_name, Some(info_name.to_string()))); diff --git a/crates/rspack_plugin_library/src/module_library_plugin.rs b/crates/rspack_plugin_library/src/module_library_plugin.rs index 340820469dbe..09aacfff6d9d 100644 --- a/crates/rspack_plugin_library/src/module_library_plugin.rs +++ b/crates/rspack_plugin_library/src/module_library_plugin.rs @@ -122,7 +122,7 @@ async fn render_startup( match used_name { UsedNameItem::Str(used_name) => format!("{exports_name}{}", property_access(vec![used_name], 0)), - UsedNameItem::Inlined(inlined) => inlined.render(), + UsedNameItem::Inlined(inlined) => inlined.render(""), } ))); } diff --git a/tests/rspack-test/configCases/inline-const/basic/index.js b/tests/rspack-test/configCases/inline-const/basic/index.js index 7b4f743e0166..83849bb14506 100644 --- a/tests/rspack-test/configCases/inline-const/basic/index.js +++ b/tests/rspack-test/configCases/inline-const/basic/index.js @@ -21,13 +21,13 @@ it("should inline constants", () => { expect(constants.REMOVE_m).toBe(13); // END:A const block = generated.match(/\/\/ START:A([\s\S]*)\/\/ END:A/)[1]; - expect(block.includes(`(/* inlined export .REMOVE_n */ (null)).toBe(null)`)).toBe(true); - expect(block.includes(`(/* inlined export .REMOVE_u */ (undefined)).toBe(undefined)`)).toBe(true); - expect(block.includes(`(/* inlined export .REMOVE_b */ (true)).toBe(true)`)).toBe(true); - expect(block.includes(`(/* inlined export .REMOVE_i */ (123456)).toBe(123456)`)).toBe(true); - expect(block.includes(`(/* inlined export .REMOVE_f */ (123.45)).toBe(123.45)`)).toBe(true); - expect(block.includes(`(/* inlined export .REMOVE_s */ ("remove")).toBe("remove")`)).toBe(true); - expect(block.includes(`(/* inlined export .REMOVE_m */ (13)).toBe(13)`)).toBe(true); + expect(block.includes(`((/* inlined export .REMOVE_n */null)).toBe(null)`)).toBe(true); + expect(block.includes(`((/* inlined export .REMOVE_u */undefined)).toBe(undefined)`)).toBe(true); + expect(block.includes(`((/* inlined export .REMOVE_b */true)).toBe(true)`)).toBe(true); + expect(block.includes(`((/* inlined export .REMOVE_i */123456)).toBe(123456)`)).toBe(true); + expect(block.includes(`((/* inlined export .REMOVE_f */123.45)).toBe(123.45)`)).toBe(true); + expect(block.includes(`((/* inlined export .REMOVE_s */"remove")).toBe("remove")`)).toBe(true); + expect(block.includes(`((/* inlined export .REMOVE_m */13)).toBe(13)`)).toBe(true); }) it("should inline constants with re-export", () => { @@ -40,12 +40,12 @@ it("should inline constants with re-export", () => { expect(reexported.REMOVE_s).toBe("remove"); // END:B const block = generated.match(/\/\/ START:B([\s\S]*)\/\/ END:B/)[1]; - expect(block.includes(`(/* inlined export .REMOVE_n */ (null)).toBe(null)`)).toBe(true); - expect(block.includes(`(/* inlined export .REMOVE_u */ (undefined)).toBe(undefined)`)).toBe(true); - expect(block.includes(`(/* inlined export .REMOVE_b */ (true)).toBe(true)`)).toBe(true); - expect(block.includes(`(/* inlined export .REMOVE_i */ (123456)).toBe(123456)`)).toBe(true); - expect(block.includes(`(/* inlined export .REMOVE_f */ (123.45)).toBe(123.45)`)).toBe(true); - expect(block.includes(`(/* inlined export .REMOVE_s */ ("remove")).toBe("remove")`)).toBe(true); + expect(block.includes(`((/* inlined export .REMOVE_n */null)).toBe(null)`)).toBe(true); + expect(block.includes(`((/* inlined export .REMOVE_u */undefined)).toBe(undefined)`)).toBe(true); + expect(block.includes(`((/* inlined export .REMOVE_b */true)).toBe(true)`)).toBe(true); + expect(block.includes(`((/* inlined export .REMOVE_i */123456)).toBe(123456)`)).toBe(true); + expect(block.includes(`((/* inlined export .REMOVE_f */123.45)).toBe(123.45)`)).toBe(true); + expect(block.includes(`((/* inlined export .REMOVE_s */"remove")).toBe("remove")`)).toBe(true); }) it("should not inline constants with destructing", () => { @@ -69,9 +69,9 @@ it("should allow inline constants if the rest exports is not used with destructi expect(destructing.REMOVE_s).toBe("remove"); // END:D const block = generated.match(/\/\/ START:D([\s\S]*)\/\/ END:D/)[1]; - expect(block.includes(`(/* inlined export .REMOVE_i */ (123456)).toBe(123456)`)).toBe(true); - expect(block.includes(`(/* inlined export .REMOVE_f */ (123.45)).toBe(123.45)`)).toBe(true); - expect(block.includes(`(/* inlined export .REMOVE_s */ ("remove")).toBe("remove")`)).toBe(true); + expect(block.includes(`((/* inlined export .REMOVE_i */123456)).toBe(123456)`)).toBe(true); + expect(block.includes(`((/* inlined export .REMOVE_f */123.45)).toBe(123.45)`)).toBe(true); + expect(block.includes(`((/* inlined export .REMOVE_s */"remove")).toBe("remove")`)).toBe(true); }) it("should respect side effects when inline constants", () => { @@ -80,7 +80,7 @@ it("should respect side effects when inline constants", () => { expect(globalThis.__sideEffects).toBe("constants.side-effects.js"); // END:E const block = generated.match(/\/\/ START:E([\s\S]*)\/\/ END:E/)[1]; - expect(block.includes(`(/* inlined export .REMOVE_CONST */ (true)).toBe(true)`)).toBe(true); + expect(block.includes(`((/* inlined export .REMOVE_CONST */true)).toBe(true)`)).toBe(true); }) it("should not inline and link to re-export module when have side effects", () => { @@ -125,9 +125,9 @@ it("should not inline destructing with re-export", () => { expect(block.includes(`(REMOVE_n).toBe(null)`)).toBe(true); expect(block.includes(`(REMOVE_u).toBe(undefined)`)).toBe(true); expect(block.includes(`(REMOVE_b).toBe(true)`)).toBe(true); - expect(block.includes(`(123456)).toBe(123456)`)).toBe(true); - expect(block.includes(`(123.45)).toBe(123.45)`)).toBe(true); - expect(block.includes(`("remove")).toBe("remove")`)).toBe(true); + expect(block.includes(`.REMOVE_i */123456)).toBe(123456)`)).toBe(true); + expect(block.includes(`.REMOVE_f */123.45)).toBe(123.45)`)).toBe(true); + expect(block.includes(`.REMOVE_s */"remove")).toBe("remove")`)).toBe(true); }) it("should not inline for cjs", () => { diff --git a/tests/rspack-test/configCases/inline-const/generated-syntax/constants.js b/tests/rspack-test/configCases/inline-const/generated-syntax/constants.js new file mode 100644 index 000000000000..1833bec294aa --- /dev/null +++ b/tests/rspack-test/configCases/inline-const/generated-syntax/constants.js @@ -0,0 +1 @@ +export const minutesInDay = 1440; diff --git a/tests/rspack-test/configCases/inline-const/generated-syntax/index.js b/tests/rspack-test/configCases/inline-const/generated-syntax/index.js new file mode 100644 index 000000000000..29c0a768939e --- /dev/null +++ b/tests/rspack-test/configCases/inline-const/generated-syntax/index.js @@ -0,0 +1,13 @@ +import { minutesInDay } from './constants.js'; + +const minutes = 2880; + +it("should generated correct syntax", () => { + let days = minutes/minutesInDay; + expect(days).toBe(2); + let then = false; + if (minutes/minutesInDay) { + then = true + } + expect(then).toBe(true); +}); diff --git a/tests/rspack-test/configCases/inline-const/generated-syntax/rspack.config.js b/tests/rspack-test/configCases/inline-const/generated-syntax/rspack.config.js new file mode 100644 index 000000000000..735725f71626 --- /dev/null +++ b/tests/rspack-test/configCases/inline-const/generated-syntax/rspack.config.js @@ -0,0 +1,9 @@ +/** @type {import("@rspack/core").Configuration} */ +module.exports = { + optimization: { + moduleIds: "named" + }, + experiments: { + inlineConst: true + } +}; diff --git a/tests/rspack-test/configCases/inline-const/suffix-properties/index.js b/tests/rspack-test/configCases/inline-const/suffix-properties/index.js index 52399b99ed7b..3e03ab8ccc7f 100644 --- a/tests/rspack-test/configCases/inline-const/suffix-properties/index.js +++ b/tests/rspack-test/configCases/inline-const/suffix-properties/index.js @@ -9,7 +9,7 @@ it("should generate correct code for inline value with properties access", () => expect(constants.REMOVE_i["toFixed"](1)).toBe("123456.0"); // END:A const block = generated.match(/\/\/ START:A([\s\S]*)\/\/ END:A/)[1]; - expect(block.includes(`/* inlined export .REMOVE_s.toUpperCase */ ("remove").toUpperCase()`)).toBe(true); - expect(block.includes(`/* inlined export .REMOVE_b.valueOf */ (true).valueOf().toString()`)).toBe(true); - expect(block.includes(`/* inlined export .REMOVE_i.toFixed */ (123456).toFixed(1)`)).toBe(true); + expect(block.includes(`((/* inlined export .REMOVE_s.toUpperCase */"remove").toUpperCase())`)).toBe(true); + expect(block.includes(`((/* inlined export .REMOVE_b.valueOf */true).valueOf().toString())`)).toBe(true); + expect(block.includes(`((/* inlined export .REMOVE_i.toFixed */123456).toFixed(1))`)).toBe(true); }) diff --git a/tests/rspack-test/configCases/inline-const/with-node-stuff/index.js b/tests/rspack-test/configCases/inline-const/with-node-stuff/index.js index d34e1ba7f8f5..f99dea2188db 100644 --- a/tests/rspack-test/configCases/inline-const/with-node-stuff/index.js +++ b/tests/rspack-test/configCases/inline-const/with-node-stuff/index.js @@ -12,5 +12,5 @@ it("should have correct exports", () => { it("should be inlined for userGlobal", () => { const block = generated.match(/\/\/ START:A([\s\S]*)\/\/ END:A/)[1]; - expect(block.includes(`(/* inlined export .global */ ("global")).toBe("global")`)).toBe(true); + expect(block.includes(`((/* inlined export .global */"global"))`)).toBe(true); }) diff --git a/tests/rspack-test/configCases/inline-enum/basic/index.js b/tests/rspack-test/configCases/inline-enum/basic/index.js index 0e6ed72c8ac2..2e54e3116d55 100644 --- a/tests/rspack-test/configCases/inline-enum/basic/index.js +++ b/tests/rspack-test/configCases/inline-enum/basic/index.js @@ -15,8 +15,8 @@ it("should inline enums", () => { expect(enums.E.B).toBe(1); // END:A const block = generated.match(/\/\/ START:A([\s\S]*)\/\/ END:A/)[1]; - expect(block.includes(`(/* inlined export .E.A */ (0)).toBe(0)`)).toBe(true); - expect(block.includes(`(/* inlined export .E.B */ (1)).toBe(1)`)).toBe(true); + expect(block.includes(`((/* inlined export .E.A */0)).toBe(0)`)).toBe(true); + expect(block.includes(`((/* inlined export .E.B */1)).toBe(1)`)).toBe(true); }) it("should inline enums with re-export", () => { @@ -25,8 +25,8 @@ it("should inline enums with re-export", () => { expect(reexported.E.B).toBe(1); // END:B const block = generated.match(/\/\/ START:B([\s\S]*)\/\/ END:B/)[1]; - expect(block.includes(`(/* inlined export .E.A */ (0)).toBe(0)`)).toBe(true); - expect(block.includes(`(/* inlined export .E.B */ (1)).toBe(1)`)).toBe(true); + expect(block.includes(`((/* inlined export .E.A */0)).toBe(0)`)).toBe(true); + expect(block.includes(`((/* inlined export .E.B */1)).toBe(1)`)).toBe(true); }) it("should not inline enums with destructuring", () => { @@ -47,8 +47,8 @@ it("should allow inline enums if the rest exports is not used with destructuring expect(destructuring.E.D).toBe(3); // END:D const block = generated.match(/\/\/ START:D([\s\S]*)\/\/ END:D/)[1]; - expect(block.includes(`(/* inlined export .E.C */ (2)).toBe(2)`)).toBe(true); - expect(block.includes(`(/* inlined export .E.D */ (3)).toBe(3)`)).toBe(true); + expect(block.includes(`((/* inlined export .E.C */2)).toBe(2)`)).toBe(true); + expect(block.includes(`((/* inlined export .E.D */3)).toBe(3)`)).toBe(true); }) it("should respect side effects when inline enums", () => { @@ -57,7 +57,7 @@ it("should respect side effects when inline enums", () => { expect(globalThis.__sideEffects).toBe("enum.side-effects.ts"); // END:E const block = generated.match(/\/\/ START:E([\s\S]*)\/\/ END:E/)[1]; - expect(block.includes(`(/* inlined export .E.A */ (0)).toBe(0)`)).toBe(true); + expect(block.includes(`((/* inlined export .E.A */0)).toBe(0)`)).toBe(true); }) it("should respect side effects when inline enums with re-exports", () => { diff --git a/tests/rspack-test/configCases/inline-enum/const-enum-only/index.js b/tests/rspack-test/configCases/inline-enum/const-enum-only/index.js index c2ac1376ec7b..441803984815 100644 --- a/tests/rspack-test/configCases/inline-enum/const-enum-only/index.js +++ b/tests/rspack-test/configCases/inline-enum/const-enum-only/index.js @@ -18,6 +18,6 @@ it("should inline for const enum for const-only mode", () => { expect(E2.B).toBe(1); // END:B const block = generated.match(/\/\/ START:B([\s\S]*)\/\/ END:B/)[1]; - expect(block.includes(`(/* inlined export .E2.A */ (0)).toBe(0)`)).toBe(true); - expect(block.includes(`(/* inlined export .E2.B */ (1)).toBe(1)`)).toBe(true); + expect(block.includes(`((/* inlined export .E2.A */0)).toBe(0)`)).toBe(true); + expect(block.includes(`((/* inlined export .E2.B */1)).toBe(1)`)).toBe(true); }) diff --git a/tests/rspack-test/configCases/inline-enum/enum-dynamically-defined/index.js b/tests/rspack-test/configCases/inline-enum/enum-dynamically-defined/index.js index 3a445b142ad5..af5f03d1a1b5 100644 --- a/tests/rspack-test/configCases/inline-enum/enum-dynamically-defined/index.js +++ b/tests/rspack-test/configCases/inline-enum/enum-dynamically-defined/index.js @@ -14,8 +14,8 @@ it("should inline enum if there is no usage of non-statical defined (no usage of expect(InlineableKind.B).toBe(1); // END:A const block = generated.match(/\/\/ START:A([\s\S]*)\/\/ END:A/)[1]; - expect(block.includes(`(/* inlined export .InlineableKind.A */ (0)).toBe(0)`)).toBe(true); - expect(block.includes(`(/* inlined export .InlineableKind.B */ (1)).toBe(1)`)).toBe(true); + expect(block.includes(`((/* inlined export .InlineableKind.A */0)).toBe(0)`)).toBe(true); + expect(block.includes(`((/* inlined export .InlineableKind.B */1)).toBe(1)`)).toBe(true); const inlinedModuleId = "./inlineable-enum.ts"; expect(generated.includes(`"${inlinedModuleId}"(`)).toBe(false); }) diff --git a/tests/rspack-test/configCases/inline-enum/enum-expression/index.js b/tests/rspack-test/configCases/inline-enum/enum-expression/index.js index 80b6c12e68f3..85eb2eef2465 100644 --- a/tests/rspack-test/configCases/inline-enum/enum-expression/index.js +++ b/tests/rspack-test/configCases/inline-enum/enum-expression/index.js @@ -9,7 +9,7 @@ it("should inline for enum expression", () => { // END:A const block = generated.match(/\/\/ START:A([\s\S]*)\/\/ END:A/)[1]; expect(block.includes(`Dynamic).toBe("number")`)).toBe(true); - expect(block.includes(`(/* inlined export .E.Static */ (1)).toBe(1)`)).toBe(true); + expect(block.includes(`((/* inlined export .E.Static */1)).toBe(1)`)).toBe(true); }) it("should inline for enum evaluatable expression", () => { @@ -22,10 +22,10 @@ it("should inline for enum evaluatable expression", () => { expect(Evaluatable.Tail).toBe(5); // END:B const block = generated.match(/\/\/ START:B([\s\S]*)\/\/ END:B/)[1]; - expect(block.includes(`(/* inlined export .Evaluatable.Neg */ (-1)).toBe(-1)`)).toBe(true); - expect(block.includes(`(/* inlined export .Evaluatable.Pos */ (1)).toBe(1)`)).toBe(true); - expect(block.includes(`(/* inlined export .Evaluatable.Add */ (2)).toBe(2)`)).toBe(true); - expect(block.includes(`(/* inlined export .Evaluatable.Ref */ (3)).toBe(3)`)).toBe(true); - expect(block.includes(`(/* inlined export .Evaluatable.Ref2 */ (4)).toBe(4)`)).toBe(true); - expect(block.includes(`(/* inlined export .Evaluatable.Tail */ (5)).toBe(5)`)).toBe(true); + expect(block.includes(`((/* inlined export .Evaluatable.Neg */-1)).toBe(-1)`)).toBe(true); + expect(block.includes(`((/* inlined export .Evaluatable.Pos */1)).toBe(1)`)).toBe(true); + expect(block.includes(`((/* inlined export .Evaluatable.Add */2)).toBe(2)`)).toBe(true); + expect(block.includes(`((/* inlined export .Evaluatable.Ref */3)).toBe(3)`)).toBe(true); + expect(block.includes(`((/* inlined export .Evaluatable.Ref2 */4)).toBe(4)`)).toBe(true); + expect(block.includes(`((/* inlined export .Evaluatable.Tail */5)).toBe(5)`)).toBe(true); }) diff --git a/tests/rspack-test/configCases/inline-enum/enum-merging/index.js b/tests/rspack-test/configCases/inline-enum/enum-merging/index.js index 9db795e6e2e2..9ad0f3ab7569 100644 --- a/tests/rspack-test/configCases/inline-enum/enum-merging/index.js +++ b/tests/rspack-test/configCases/inline-enum/enum-merging/index.js @@ -8,6 +8,6 @@ it("should inline for enum merging", () => { expect(E.B).toBe(1); // END:A const block = generated.match(/\/\/ START:A([\s\S]*)\/\/ END:A/)[1]; - expect(block.includes(`(/* inlined export .E.A */ (0)).toBe(0)`)).toBe(true); - expect(block.includes(`(/* inlined export .E.B */ (1)).toBe(1)`)).toBe(true); + expect(block.includes(`((/* inlined export .E.A */0)).toBe(0)`)).toBe(true); + expect(block.includes(`((/* inlined export .E.B */1)).toBe(1)`)).toBe(true); }) diff --git a/tests/rspack-test/configCases/inline-enum/member-value-undefined/only-a.js b/tests/rspack-test/configCases/inline-enum/member-value-undefined/only-a.js index 703e640d5359..90768475113c 100644 --- a/tests/rspack-test/configCases/inline-enum/member-value-undefined/only-a.js +++ b/tests/rspack-test/configCases/inline-enum/member-value-undefined/only-a.js @@ -6,7 +6,7 @@ export const test = (it, generated) => { expect(E.A).toBe("a"); // END:ONLY_A const block = generated.match(/\/\/ START:ONLY_A([\s\S]*)\/\/ END:ONLY_A/)[1]; - expect(block.includes(`(/* inlined export .E.A */ ("a")).toBe("a")`)).toBe(true); + expect(block.includes(`((/* inlined export .E.A */"a")).toBe("a")`)).toBe(true); }) it("should remove the module if only enum member A is used", () => { diff --git a/tests/rspack-test/configCases/inline-enum/not-last-loader/index.js b/tests/rspack-test/configCases/inline-enum/not-last-loader/index.js index 3e9bf0a3b1b9..da82f84dccad 100644 --- a/tests/rspack-test/configCases/inline-enum/not-last-loader/index.js +++ b/tests/rspack-test/configCases/inline-enum/not-last-loader/index.js @@ -8,6 +8,6 @@ it("should inline for enum when builtin:swc-loader is not the last loader", () = expect(E.B).toBe(1); // END:A const block = generated.match(/\/\/ START:A([\s\S]*)\/\/ END:A/)[1]; - expect(block.includes(`(/* inlined export .E.A */ (0)).toBe(0)`)).toBe(true); - expect(block.includes(`(/* inlined export .E.B */ (1)).toBe(1)`)).toBe(true); + expect(block.includes(`((/* inlined export .E.A */0)).toBe(0)`)).toBe(true); + expect(block.includes(`((/* inlined export .E.B */1)).toBe(1)`)).toBe(true); }) diff --git a/tests/rspack-test/configCases/library/modern-module-force-concaten/__snapshot__/e.js.txt b/tests/rspack-test/configCases/library/modern-module-force-concaten/__snapshot__/e.js.txt index a3a22b13fd14..c2fd4ad68b28 100644 --- a/tests/rspack-test/configCases/library/modern-module-force-concaten/__snapshot__/e.js.txt +++ b/tests/rspack-test/configCases/library/modern-module-force-concaten/__snapshot__/e.js.txt @@ -65,5 +65,5 @@ var bar_default = /*#__PURE__*/__webpack_require__.n(bar); var __webpack_exports__bar = (bar_default()); -var __webpack_exports__foo = /* inlined export .foo */ ("foo"); +var __webpack_exports__foo = (/* inlined export .foo */"foo"); export { __webpack_exports__bar as bar, __webpack_exports__foo as foo }; \ No newline at end of file diff --git a/tests/rspack-test/configCases/library/modern-module-force-concaten/__snapshot__/f.js.txt b/tests/rspack-test/configCases/library/modern-module-force-concaten/__snapshot__/f.js.txt index df26442ac454..c25ead578b63 100644 --- a/tests/rspack-test/configCases/library/modern-module-force-concaten/__snapshot__/f.js.txt +++ b/tests/rspack-test/configCases/library/modern-module-force-concaten/__snapshot__/f.js.txt @@ -71,7 +71,7 @@ var bar_default = /*#__PURE__*/__webpack_require__.n(bar); -const value = /* inlined export .foo */ ("foo") + (bar_default()) +const value = (/* inlined export .foo */"foo") + (bar_default()) diff --git a/tests/rspack-test/configCases/rsdoctor/assets/rspack.config.js b/tests/rspack-test/configCases/rsdoctor/assets/rspack.config.js index 0840d60f2c3b..c93f49318aa7 100644 --- a/tests/rspack-test/configCases/rsdoctor/assets/rspack.config.js +++ b/tests/rspack-test/configCases/rsdoctor/assets/rspack.config.js @@ -37,11 +37,11 @@ module.exports = { Array [ Object { path: a.js, - size: 4004, + size: 4003, }, Object { path: b.js, - size: 4004, + size: 4003, }, Object { path: c_js.js, diff --git a/tests/rspack-test/esmOutputCases/basic/async-modules/__snapshots__/esm.snap.txt b/tests/rspack-test/esmOutputCases/basic/async-modules/__snapshots__/esm.snap.txt index 9d0bffab068e..f09241bd1a83 100644 --- a/tests/rspack-test/esmOutputCases/basic/async-modules/__snapshots__/esm.snap.txt +++ b/tests/rspack-test/esmOutputCases/basic/async-modules/__snapshots__/esm.snap.txt @@ -22,7 +22,7 @@ it('should has correct exec order and export value', async () => { expect(demo).toBe(84) }) -const demo = /* inlined export .lib */ (42) + _lib_defer_js__rspack_import_0.v +const demo = (/* inlined export .lib */42) + _lib_defer_js__rspack_import_0.v __rspack_async_done(); diff --git a/tests/rspack-test/esmOutputCases/deconflict/deconflit-local/__snapshots__/esm.snap.txt b/tests/rspack-test/esmOutputCases/deconflict/deconflit-local/__snapshots__/esm.snap.txt index ab425a3a7445..ec81ae2f4208 100644 --- a/tests/rspack-test/esmOutputCases/deconflict/deconflit-local/__snapshots__/esm.snap.txt +++ b/tests/rspack-test/esmOutputCases/deconflict/deconflit-local/__snapshots__/esm.snap.txt @@ -6,7 +6,7 @@ const local = 'index' const index_local = '' it('should have deconflicted symbol', () => { - expect(/* inlined export .value */(42)).toBe(42) + expect((/* inlined export .value */42)).toBe(42) expect(local).toBe('index') expect(index_local).toBe('') }) diff --git a/tests/rspack-test/esmOutputCases/deconflict/other-chunk-local/__snapshots__/esm.snap.txt b/tests/rspack-test/esmOutputCases/deconflict/other-chunk-local/__snapshots__/esm.snap.txt index c8c1dba1de6f..bde8644b807c 100644 --- a/tests/rspack-test/esmOutputCases/deconflict/other-chunk-local/__snapshots__/esm.snap.txt +++ b/tests/rspack-test/esmOutputCases/deconflict/other-chunk-local/__snapshots__/esm.snap.txt @@ -6,11 +6,11 @@ const local = 'index' const index_local = '' it('should have deconflicted symbol', async () => { - expect(/* inlined export .value */(42)).toBe(42) + expect((/* inlined export .value */42)).toBe(42) expect(local).toBe('index') expect(index_local).toBe('') const {value: v} = await import("./other_js.mjs").then((mod) => ({ value: mod.value })) - expect(v).toBe(/* inlined export .value */(42)) + expect(v).toBe((/* inlined export .value */42)) }) @@ -22,7 +22,7 @@ it('should have deconflicted symbol', async () => { const local = 'other' -const value = /* inlined export .value */(42) +const value = (/* inlined export .value */42) export { value }; diff --git a/tests/rspack-test/esmOutputCases/interop/contains-cjs/__snapshots__/esm.snap.txt b/tests/rspack-test/esmOutputCases/interop/contains-cjs/__snapshots__/esm.snap.txt index f22b0ba8bf3f..497e97203925 100644 --- a/tests/rspack-test/esmOutputCases/interop/contains-cjs/__snapshots__/esm.snap.txt +++ b/tests/rspack-test/esmOutputCases/interop/contains-cjs/__snapshots__/esm.snap.txt @@ -37,7 +37,7 @@ it('should have correct import', () => { expect(from_esm["default"]).toBe('esm') expect(foo.foo).toBe(42) - expect(/* inlined export .value */("value")).toBe('value') + expect((/* inlined export .value */"value")).toBe('value') }) // ./index.js diff --git a/tests/rspack-test/esmOutputCases/re-exports/deep-re-exports-esm/__snapshots__/esm.snap.txt b/tests/rspack-test/esmOutputCases/re-exports/deep-re-exports-esm/__snapshots__/esm.snap.txt index c59da4fb996b..71f403f1dd7a 100644 --- a/tests/rspack-test/esmOutputCases/re-exports/deep-re-exports-esm/__snapshots__/esm.snap.txt +++ b/tests/rspack-test/esmOutputCases/re-exports/deep-re-exports-esm/__snapshots__/esm.snap.txt @@ -20,8 +20,8 @@ it('should re-export esm correctly', async () => { expect(lib4).toBe(24) }) -var index_lib3 = /* inlined export .lib3 */(42); -var index_lib4 = /* inlined export .lib4 */(24); +var index_lib3 = (/* inlined export .lib3 */42); +var index_lib4 = (/* inlined export .lib4 */24); export { index_lib3 as lib3, index_lib4 as lib4, lib2_lib2 as lib2, lib_lib as lib }; ``` \ No newline at end of file diff --git a/tests/rspack-test/esmOutputCases/re-exports/re-export-external/__snapshots__/esm.snap.txt b/tests/rspack-test/esmOutputCases/re-exports/re-export-external/__snapshots__/esm.snap.txt index 30aaca7abb80..88b103ef2477 100644 --- a/tests/rspack-test/esmOutputCases/re-exports/re-export-external/__snapshots__/esm.snap.txt +++ b/tests/rspack-test/esmOutputCases/re-exports/re-export-external/__snapshots__/esm.snap.txt @@ -25,10 +25,10 @@ it('should compile and import success', async () => { }) var fs_0 = __rspack_external_fs["default"]; -var index_named = /* inlined export .named */(42); +var index_named = (/* inlined export .named */42); var r_0 = __rspack_external_fs.readFile; var readFile_0 = __rspack_external_fs.readFile; -var index_starExports = /* inlined export .starExports */(42); +var index_starExports = (/* inlined export .starExports */42); export { fs_0 as fs, index_named as named, index_starExports as starExports, r_0 as r, readFile_0 as readFile }; export * from "fs"; diff --git a/tests/rspack-test/esmOutputCases/re-exports/re-export-namespaced-external/__snapshots__/esm.snap.txt b/tests/rspack-test/esmOutputCases/re-exports/re-export-namespaced-external/__snapshots__/esm.snap.txt index 2885585f5e84..874a693faa8c 100644 --- a/tests/rspack-test/esmOutputCases/re-exports/re-export-namespaced-external/__snapshots__/esm.snap.txt +++ b/tests/rspack-test/esmOutputCases/re-exports/re-export-namespaced-external/__snapshots__/esm.snap.txt @@ -38,10 +38,10 @@ it('should compile and import success', async () => { var default_0 = __rspack_external_fs["default"]; var fs_0 = __rspack_external_fs["default"]; -var index_named = /* inlined export .named */(42); +var index_named = (/* inlined export .named */42); var r_0 = __rspack_external_fs.readFile; var readFile_0 = __rspack_external_fs.readFile; -var index_starExports = /* inlined export .starExports */(42); +var index_starExports = (/* inlined export .starExports */42); export { __rspack_external_fs as fsNs, fs_0 as fs, index_named as named, index_starExports as starExports, r_0 as r, readFile_0 as readFile }; export * from "fs"; export default default_0; diff --git a/tests/rspack-test/esmOutputCases/re-exports/wrapped-esm-entry/__snapshots__/esm.snap.txt b/tests/rspack-test/esmOutputCases/re-exports/wrapped-esm-entry/__snapshots__/esm.snap.txt index 47e4238b538d..391302094a8f 100644 --- a/tests/rspack-test/esmOutputCases/re-exports/wrapped-esm-entry/__snapshots__/esm.snap.txt +++ b/tests/rspack-test/esmOutputCases/re-exports/wrapped-esm-entry/__snapshots__/esm.snap.txt @@ -10,10 +10,10 @@ __webpack_require__.add({ __webpack_require__.r(__webpack_exports__); __webpack_require__.d(__webpack_exports__, { fs: () => (/* reexport safe */ fs__rspack_import_0["default"]), - named: () => (/* reexport safe */ (42)), + named: () => (/* reexport safe */ (/* inlined export _lib__rspack_import_1 */42)), r: () => (/* reexport safe */ fs__rspack_import_0.readFile), readFile: () => (/* reexport safe */ fs__rspack_import_0.readFile), - starExports: () => (/* reexport safe */ (42)) + starExports: () => (/* reexport safe */ (/* inlined export _lib2__rspack_import_2 */42)) }); /* import */ var fs__rspack_import_0 = __webpack_require__(/*! fs */ "fs"); From 6ee0d4b1f096707d99174bf38af4396f4840fcde Mon Sep 17 00:00:00 2001 From: harpsealjs Date: Fri, 9 Jan 2026 17:10:24 +0800 Subject: [PATCH 34/87] feat: add `requireAlias` option to control require variable renaming (#12686) * feat: add requireRename option to control require variable renaming * Update packages/rspack/src/config/types.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update tests/rspack-test/configCases/parsing/renaming-disabled/index.js Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * rename * rename --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- crates/node_binding/napi-binding.d.ts | 5 + crates/rspack/src/builder/mod.rs | 1 + .../snapshots/defaults__default_options.snap | 3 + .../src/raw_options/raw_module/mod.rs | 4 + crates/rspack_core/src/options/module.rs | 1 + .../common_js_imports_parse_plugin.rs | 4 +- packages/rspack/etc/core.api.md | 1 + packages/rspack/src/config/adapter.ts | 1 + packages/rspack/src/config/defaults.ts | 1 + packages/rspack/src/config/types.ts | 6 + .../parsing/renaming-disabled/file.js | 1 + .../parsing/renaming-disabled/index.js | 26 +++ .../renaming-disabled/rspack.config.js | 10 ++ .../rspack-test/defaultsCases/default/base.js | 1 + .../defaultsCases/library/library.js | 72 ++++----- .../defaultsCases/library/name-placeholder.js | 74 ++++----- .../library/name-root-placeholder.js | 78 ++++----- .../defaultsCases/library/placeholder.js | 72 ++++----- .../defaultsCases/library/root-placeholder.js | 76 ++++----- .../normalCases/parsing/renaming copy/file.js | 1 - .../parsing/renaming copy/index.js | 86 ---------- .../normalCases/parsing/renaming/index.js | 150 +++++++++--------- 22 files changed, 323 insertions(+), 351 deletions(-) create mode 100644 tests/rspack-test/configCases/parsing/renaming-disabled/file.js create mode 100644 tests/rspack-test/configCases/parsing/renaming-disabled/index.js create mode 100644 tests/rspack-test/configCases/parsing/renaming-disabled/rspack.config.js delete mode 100644 tests/rspack-test/normalCases/parsing/renaming copy/file.js delete mode 100644 tests/rspack-test/normalCases/parsing/renaming copy/index.js diff --git a/crates/node_binding/napi-binding.d.ts b/crates/node_binding/napi-binding.d.ts index b072c61cd319..051b908d785c 100644 --- a/crates/node_binding/napi-binding.d.ts +++ b/crates/node_binding/napi-binding.d.ts @@ -2339,6 +2339,11 @@ export interface RawJavascriptParserOptions { worker?: Array overrideStrict?: string importMeta?: boolean + /** + * This option is experimental in Rspack only and subject to change or be removed anytime. + * @experimental + */ + requireAlias?: boolean /** * This option is experimental in Rspack only and subject to change or be removed anytime. * @experimental diff --git a/crates/rspack/src/builder/mod.rs b/crates/rspack/src/builder/mod.rs index 6203d7f9efb7..b0c83c6e12de 100644 --- a/crates/rspack/src/builder/mod.rs +++ b/crates/rspack/src/builder/mod.rs @@ -1721,6 +1721,7 @@ impl ModuleOptionsBuilder { strict_export_presence: Some(false), worker: Some(vec!["...".to_string()]), import_meta: Some(true), + require_alias: Some(true), require_as_expression: Some(true), require_dynamic: Some(true), require_resolve: Some(true), diff --git a/crates/rspack/tests/snapshots/defaults__default_options.snap b/crates/rspack/tests/snapshots/defaults__default_options.snap index 86ca9041ff72..300eddb877b6 100644 --- a/crates/rspack/tests/snapshots/defaults__default_options.snap +++ b/crates/rspack/tests/snapshots/defaults__default_options.snap @@ -1456,6 +1456,9 @@ CompilerOptions { import_meta: Some( true, ), + require_alias: Some( + true, + ), require_as_expression: Some( true, ), diff --git a/crates/rspack_binding_api/src/raw_options/raw_module/mod.rs b/crates/rspack_binding_api/src/raw_options/raw_module/mod.rs index 48f0f8ad7f28..d5e7c27bbfae 100644 --- a/crates/rspack_binding_api/src/raw_options/raw_module/mod.rs +++ b/crates/rspack_binding_api/src/raw_options/raw_module/mod.rs @@ -290,6 +290,9 @@ pub struct RawJavascriptParserOptions { pub import_meta: Option, /// This option is experimental in Rspack only and subject to change or be removed anytime. /// @experimental + pub require_alias: Option, + /// This option is experimental in Rspack only and subject to change or be removed anytime. + /// @experimental pub require_as_expression: Option, /// This option is experimental in Rspack only and subject to change or be removed anytime. /// @experimental @@ -364,6 +367,7 @@ impl From for JavascriptParserOptions { .override_strict .map(|e| OverrideStrict::from(e.as_str())), import_meta: value.import_meta, + require_alias: value.require_alias, require_as_expression: value.require_as_expression, require_dynamic: value.require_dynamic, require_resolve: value.require_resolve, diff --git a/crates/rspack_core/src/options/module.rs b/crates/rspack_core/src/options/module.rs index 5f62ca8c68cc..3f73fbc0b707 100644 --- a/crates/rspack_core/src/options/module.rs +++ b/crates/rspack_core/src/options/module.rs @@ -301,6 +301,7 @@ pub struct JavascriptParserOptions { pub worker: Option>, pub override_strict: Option, pub import_meta: Option, + pub require_alias: Option, pub require_as_expression: Option, pub require_dynamic: Option, pub require_resolve: Option, diff --git a/crates/rspack_plugin_javascript/src/parser_plugin/common_js_imports_parse_plugin.rs b/crates/rspack_plugin_javascript/src/parser_plugin/common_js_imports_parse_plugin.rs index 15e720b5ad6a..2102bb8ad4f4 100644 --- a/crates/rspack_plugin_javascript/src/parser_plugin/common_js_imports_parse_plugin.rs +++ b/crates/rspack_plugin_javascript/src/parser_plugin/common_js_imports_parse_plugin.rs @@ -402,9 +402,9 @@ impl CommonJsImportsParserPlugin { } impl JavascriptParserPlugin for CommonJsImportsParserPlugin { - fn can_rename(&self, _parser: &mut JavascriptParser, for_name: &str) -> Option { + fn can_rename(&self, parser: &mut JavascriptParser, for_name: &str) -> Option { if for_name == expr_name::REQUIRE { - Some(true) + Some(parser.javascript_options.require_alias.unwrap_or(true)) } else { None } diff --git a/packages/rspack/etc/core.api.md b/packages/rspack/etc/core.api.md index 1238e9baa238..bbabb4b3c281 100644 --- a/packages/rspack/etc/core.api.md +++ b/packages/rspack/etc/core.api.md @@ -3563,6 +3563,7 @@ export type JavascriptParserOptions = { strictExportPresence?: boolean; worker?: string[] | boolean; overrideStrict?: 'strict' | 'non-strict'; + requireAlias?: boolean; requireAsExpression?: boolean; requireDynamic?: boolean; requireResolve?: boolean; diff --git a/packages/rspack/src/config/adapter.ts b/packages/rspack/src/config/adapter.ts index eb4f3f08d8c7..e14a5e9516e6 100644 --- a/packages/rspack/src/config/adapter.ts +++ b/packages/rspack/src/config/adapter.ts @@ -585,6 +585,7 @@ function getRawJavascriptParserOptions( : parser.worker, overrideStrict: parser.overrideStrict, requireAsExpression: parser.requireAsExpression, + requireAlias: parser.requireAlias, requireDynamic: parser.requireDynamic, requireResolve: parser.requireResolve, commonjs: parser.commonjs, diff --git a/packages/rspack/src/config/defaults.ts b/packages/rspack/src/config/defaults.ts index 64de108acf86..85788f39886a 100644 --- a/packages/rspack/src/config/defaults.ts +++ b/packages/rspack/src/config/defaults.ts @@ -322,6 +322,7 @@ const applyJavascriptParserOptionsDefaults = ( D(parserOptions, 'wrappedContextRegExp', /.*/); D(parserOptions, 'strictExportPresence', false); D(parserOptions, 'requireAsExpression', true); + D(parserOptions, 'requireAlias', true); D(parserOptions, 'requireDynamic', true); D(parserOptions, 'requireResolve', true); D(parserOptions, 'commonjs', true); diff --git a/packages/rspack/src/config/types.ts b/packages/rspack/src/config/types.ts index 6c7c79826ca5..6c0f7b4bf59c 100644 --- a/packages/rspack/src/config/types.ts +++ b/packages/rspack/src/config/types.ts @@ -1162,6 +1162,12 @@ export type JavascriptParserOptions = { /** Override the module to strict or non-strict. */ overrideStrict?: 'strict' | 'non-strict'; + /** + * Control whether renaming of the CommonJS `require` function will be parsed and transformed. + * @default true + */ + requireAlias?: boolean; + // TODO: add docs requireAsExpression?: boolean; diff --git a/tests/rspack-test/configCases/parsing/renaming-disabled/file.js b/tests/rspack-test/configCases/parsing/renaming-disabled/file.js new file mode 100644 index 000000000000..f74a2f2b5646 --- /dev/null +++ b/tests/rspack-test/configCases/parsing/renaming-disabled/file.js @@ -0,0 +1 @@ +module.exports = "ok"; diff --git a/tests/rspack-test/configCases/parsing/renaming-disabled/index.js b/tests/rspack-test/configCases/parsing/renaming-disabled/index.js new file mode 100644 index 000000000000..c3b4a6759f7c --- /dev/null +++ b/tests/rspack-test/configCases/parsing/renaming-disabled/index.js @@ -0,0 +1,26 @@ +var cjsRequire; // just to make it difficult +var cjsRequire = require, cjsRequire2 = typeof require !== "undefined" && require; + +function test() { + cjsRequire("./file"); +} + +function test2() { + cjsRequire2("./file"); +} + +test; +test2; + +it("should NOT rename require when requireAlias is false", function () { + const fs = __non_webpack_require__("fs"); + const path = __non_webpack_require__("path"); + + const content = fs.readFileSync(path.join(__dirname, "./bundle0.js"), "utf-8"); + const filename = "./file"; + const requireName = "require"; + + expect(content).toContain(`cjsRequire("${filename}")`); + expect(content).toContain(`cjsRequire2("${filename}")`); + expect(content).toContain(`var cjsRequire = ${requireName}, cjsRequire2 = true && ${requireName};`); +}); \ No newline at end of file diff --git a/tests/rspack-test/configCases/parsing/renaming-disabled/rspack.config.js b/tests/rspack-test/configCases/parsing/renaming-disabled/rspack.config.js new file mode 100644 index 000000000000..efb7dcf661ed --- /dev/null +++ b/tests/rspack-test/configCases/parsing/renaming-disabled/rspack.config.js @@ -0,0 +1,10 @@ +module.exports = { + module: { + parser: { + javascript: { + requireAlias: false, + requireAsExpression: false + } + } + }, +}; \ No newline at end of file diff --git a/tests/rspack-test/defaultsCases/default/base.js b/tests/rspack-test/defaultsCases/default/base.js index 9072b2e54a78..7a071595afe0 100644 --- a/tests/rspack-test/defaultsCases/default/base.js +++ b/tests/rspack-test/defaultsCases/default/base.js @@ -214,6 +214,7 @@ module.exports = { importDynamic: true, importMeta: true, jsx: false, + requireAlias: true, requireAsExpression: true, requireDynamic: true, requireResolve: true, diff --git a/tests/rspack-test/defaultsCases/library/library.js b/tests/rspack-test/defaultsCases/library/library.js index e1a13f217d52..4ab4cdb61361 100644 --- a/tests/rspack-test/defaultsCases/library/library.js +++ b/tests/rspack-test/defaultsCases/library/library.js @@ -4,41 +4,41 @@ module.exports = { options: () => ({ output: { library: ["myLib", "awesome"] } }), diff: e => e.toMatchInlineSnapshot(` - - Expected - + Received + - Expected + + Received - @@ ... @@ - - "force": true, - + "force": false, - @@ ... @@ - - "chunkLoadingGlobal": "webpackChunk_rspack_tests", - + "chunkLoadingGlobal": "webpackChunkmyLib_awesome", - @@ ... @@ - - "devtoolNamespace": "@rspack/tests", - + "devtoolNamespace": "myLib.awesome", - @@ ... @@ - - "enabledLibraryTypes": Array [], - + "enabledLibraryTypes": Array [ - + "var", - + ], - @@ ... @@ - - "hotUpdateGlobal": "webpackHotUpdate_rspack_tests", - + "hotUpdateGlobal": "webpackHotUpdatemyLib_awesome", - @@ ... @@ - - "library": undefined, - + "library": Object { - + "amdContainer": undefined, - + "auxiliaryComment": undefined, - + "export": undefined, - + "name": Array [ - + "myLib", - + "awesome", - + ], - + "type": "var", - + "umdNamedDefine": undefined, - + }, - @@ ... @@ - - "uniqueName": "@rspack/tests", - + "uniqueName": "myLib.awesome", - `) + @@ ... @@ + - "force": true, + + "force": false, + @@ ... @@ + - "chunkLoadingGlobal": "webpackChunk_rspack_tests", + + "chunkLoadingGlobal": "webpackChunkmyLib_awesome", + @@ ... @@ + - "devtoolNamespace": "@rspack/tests", + + "devtoolNamespace": "myLib.awesome", + @@ ... @@ + - "enabledLibraryTypes": Array [], + + "enabledLibraryTypes": Array [ + + "var", + + ], + @@ ... @@ + - "hotUpdateGlobal": "webpackHotUpdate_rspack_tests", + + "hotUpdateGlobal": "webpackHotUpdatemyLib_awesome", + @@ ... @@ + - "library": undefined, + + "library": Object { + + "amdContainer": undefined, + + "auxiliaryComment": undefined, + + "export": undefined, + + "name": Array [ + + "myLib", + + "awesome", + + ], + + "type": "var", + + "umdNamedDefine": undefined, + + }, + @@ ... @@ + - "uniqueName": "@rspack/tests", + + "uniqueName": "myLib.awesome", + `) }; diff --git a/tests/rspack-test/defaultsCases/library/name-placeholder.js b/tests/rspack-test/defaultsCases/library/name-placeholder.js index c3b41d6b2109..e93a639f7be3 100644 --- a/tests/rspack-test/defaultsCases/library/name-placeholder.js +++ b/tests/rspack-test/defaultsCases/library/name-placeholder.js @@ -11,42 +11,42 @@ module.exports = { }), diff: e => e.toMatchInlineSnapshot(` - - Expected - + Received + - Expected + + Received - @@ ... @@ - - "force": true, - + "force": false, - @@ ... @@ - - "chunkLoadingGlobal": "webpackChunk_rspack_tests", - + "chunkLoadingGlobal": "webpackChunkmyLib_lib", - @@ ... @@ - - "devtoolNamespace": "@rspack/tests", - + "devtoolNamespace": "myLib.lib", - @@ ... @@ - - "enabledLibraryTypes": Array [], - + "enabledLibraryTypes": Array [ - + "var", - + ], - @@ ... @@ - - "hotUpdateGlobal": "webpackHotUpdate_rspack_tests", - + "hotUpdateGlobal": "webpackHotUpdatemyLib_lib", - @@ ... @@ - - "library": undefined, - + "library": Object { - + "amdContainer": undefined, - + "auxiliaryComment": undefined, - + "export": undefined, - + "name": Array [ - + "my[name]Lib", - + "[name]", - + "lib", - + ], - + "type": "var", - + "umdNamedDefine": undefined, - + }, - @@ ... @@ - - "uniqueName": "@rspack/tests", - + "uniqueName": "myLib.lib", - `) + @@ ... @@ + - "force": true, + + "force": false, + @@ ... @@ + - "chunkLoadingGlobal": "webpackChunk_rspack_tests", + + "chunkLoadingGlobal": "webpackChunkmyLib_lib", + @@ ... @@ + - "devtoolNamespace": "@rspack/tests", + + "devtoolNamespace": "myLib.lib", + @@ ... @@ + - "enabledLibraryTypes": Array [], + + "enabledLibraryTypes": Array [ + + "var", + + ], + @@ ... @@ + - "hotUpdateGlobal": "webpackHotUpdate_rspack_tests", + + "hotUpdateGlobal": "webpackHotUpdatemyLib_lib", + @@ ... @@ + - "library": undefined, + + "library": Object { + + "amdContainer": undefined, + + "auxiliaryComment": undefined, + + "export": undefined, + + "name": Array [ + + "my[name]Lib", + + "[name]", + + "lib", + + ], + + "type": "var", + + "umdNamedDefine": undefined, + + }, + @@ ... @@ + - "uniqueName": "@rspack/tests", + + "uniqueName": "myLib.lib", + `) }; diff --git a/tests/rspack-test/defaultsCases/library/name-root-placeholder.js b/tests/rspack-test/defaultsCases/library/name-root-placeholder.js index 168d80446cd1..19c640435a2b 100644 --- a/tests/rspack-test/defaultsCases/library/name-root-placeholder.js +++ b/tests/rspack-test/defaultsCases/library/name-root-placeholder.js @@ -13,44 +13,44 @@ module.exports = { }), diff: e => e.toMatchInlineSnapshot(` - - Expected - + Received + - Expected + + Received - @@ ... @@ - - "force": true, - + "force": false, - @@ ... @@ - - "chunkLoadingGlobal": "webpackChunk_rspack_tests", - + "chunkLoadingGlobal": "webpackChunk_name_my_name_Lib_name_", - @@ ... @@ - - "devtoolNamespace": "@rspack/tests", - + "devtoolNamespace": "[name].my[name]Lib.[name]", - @@ ... @@ - - "enabledLibraryTypes": Array [], - + "enabledLibraryTypes": Array [ - + "var", - + ], - @@ ... @@ - - "hotUpdateGlobal": "webpackHotUpdate_rspack_tests", - + "hotUpdateGlobal": "webpackHotUpdate_name_my_name_Lib_name_", - @@ ... @@ - - "library": undefined, - + "library": Object { - + "amdContainer": undefined, - + "auxiliaryComment": undefined, - + "export": undefined, - + "name": Object { - + "root": Array [ - + "[\\\\name\\\\]", - + "my[\\\\name\\\\]Lib[name]", - + "[\\\\name\\\\]", - + ], - + }, - + "type": "var", - + "umdNamedDefine": undefined, - + }, - @@ ... @@ - - "uniqueName": "@rspack/tests", - + "uniqueName": "[name].my[name]Lib.[name]", - `) + @@ ... @@ + - "force": true, + + "force": false, + @@ ... @@ + - "chunkLoadingGlobal": "webpackChunk_rspack_tests", + + "chunkLoadingGlobal": "webpackChunk_name_my_name_Lib_name_", + @@ ... @@ + - "devtoolNamespace": "@rspack/tests", + + "devtoolNamespace": "[name].my[name]Lib.[name]", + @@ ... @@ + - "enabledLibraryTypes": Array [], + + "enabledLibraryTypes": Array [ + + "var", + + ], + @@ ... @@ + - "hotUpdateGlobal": "webpackHotUpdate_rspack_tests", + + "hotUpdateGlobal": "webpackHotUpdate_name_my_name_Lib_name_", + @@ ... @@ + - "library": undefined, + + "library": Object { + + "amdContainer": undefined, + + "auxiliaryComment": undefined, + + "export": undefined, + + "name": Object { + + "root": Array [ + + "[\\\\name\\\\]", + + "my[\\\\name\\\\]Lib[name]", + + "[\\\\name\\\\]", + + ], + + }, + + "type": "var", + + "umdNamedDefine": undefined, + + }, + @@ ... @@ + - "uniqueName": "@rspack/tests", + + "uniqueName": "[name].my[name]Lib.[name]", + `) }; diff --git a/tests/rspack-test/defaultsCases/library/placeholder.js b/tests/rspack-test/defaultsCases/library/placeholder.js index 7864e452684f..0614dcf5508a 100644 --- a/tests/rspack-test/defaultsCases/library/placeholder.js +++ b/tests/rspack-test/defaultsCases/library/placeholder.js @@ -8,41 +8,41 @@ module.exports = { }), diff: e => e.toMatchInlineSnapshot(` - - Expected - + Received + - Expected + + Received - @@ ... @@ - - "force": true, - + "force": false, - @@ ... @@ - - "chunkLoadingGlobal": "webpackChunk_rspack_tests", - + "chunkLoadingGlobal": "webpackChunkmyLib", - @@ ... @@ - - "devtoolNamespace": "@rspack/tests", - + "devtoolNamespace": "myLib", - @@ ... @@ - - "enabledLibraryTypes": Array [], - + "enabledLibraryTypes": Array [ - + "var", - + ], - @@ ... @@ - - "hotUpdateGlobal": "webpackHotUpdate_rspack_tests", - + "hotUpdateGlobal": "webpackHotUpdatemyLib", - @@ ... @@ - - "library": undefined, - + "library": Object { - + "amdContainer": undefined, - + "auxiliaryComment": undefined, - + "export": undefined, - + "name": Array [ - + "myLib", - + "[name]", - + ], - + "type": "var", - + "umdNamedDefine": undefined, - + }, - @@ ... @@ - - "uniqueName": "@rspack/tests", - + "uniqueName": "myLib", - `) + @@ ... @@ + - "force": true, + + "force": false, + @@ ... @@ + - "chunkLoadingGlobal": "webpackChunk_rspack_tests", + + "chunkLoadingGlobal": "webpackChunkmyLib", + @@ ... @@ + - "devtoolNamespace": "@rspack/tests", + + "devtoolNamespace": "myLib", + @@ ... @@ + - "enabledLibraryTypes": Array [], + + "enabledLibraryTypes": Array [ + + "var", + + ], + @@ ... @@ + - "hotUpdateGlobal": "webpackHotUpdate_rspack_tests", + + "hotUpdateGlobal": "webpackHotUpdatemyLib", + @@ ... @@ + - "library": undefined, + + "library": Object { + + "amdContainer": undefined, + + "auxiliaryComment": undefined, + + "export": undefined, + + "name": Array [ + + "myLib", + + "[name]", + + ], + + "type": "var", + + "umdNamedDefine": undefined, + + }, + @@ ... @@ + - "uniqueName": "@rspack/tests", + + "uniqueName": "myLib", + `) }; diff --git a/tests/rspack-test/defaultsCases/library/root-placeholder.js b/tests/rspack-test/defaultsCases/library/root-placeholder.js index 9a2ca2be6836..30424ba4c7b8 100644 --- a/tests/rspack-test/defaultsCases/library/root-placeholder.js +++ b/tests/rspack-test/defaultsCases/library/root-placeholder.js @@ -13,43 +13,43 @@ module.exports = { }), diff: e => e.toMatchInlineSnapshot(` - - Expected - + Received + - Expected + + Received - @@ ... @@ - - "force": true, - + "force": false, - @@ ... @@ - - "chunkLoadingGlobal": "webpackChunk_rspack_tests", - + "chunkLoadingGlobal": "webpackChunkmyLib", - @@ ... @@ - - "devtoolNamespace": "@rspack/tests", - + "devtoolNamespace": "myLib", - @@ ... @@ - - "enabledLibraryTypes": Array [], - + "enabledLibraryTypes": Array [ - + "var", - + ], - @@ ... @@ - - "hotUpdateGlobal": "webpackHotUpdate_rspack_tests", - + "hotUpdateGlobal": "webpackHotUpdatemyLib", - @@ ... @@ - - "library": undefined, - + "library": Object { - + "amdContainer": undefined, - + "auxiliaryComment": undefined, - + "export": undefined, - + "name": Object { - + "root": Array [ - + "[name]", - + "myLib", - + ], - + }, - + "type": "var", - + "umdNamedDefine": undefined, - + }, - @@ ... @@ - - "uniqueName": "@rspack/tests", - + "uniqueName": "myLib", - `) + @@ ... @@ + - "force": true, + + "force": false, + @@ ... @@ + - "chunkLoadingGlobal": "webpackChunk_rspack_tests", + + "chunkLoadingGlobal": "webpackChunkmyLib", + @@ ... @@ + - "devtoolNamespace": "@rspack/tests", + + "devtoolNamespace": "myLib", + @@ ... @@ + - "enabledLibraryTypes": Array [], + + "enabledLibraryTypes": Array [ + + "var", + + ], + @@ ... @@ + - "hotUpdateGlobal": "webpackHotUpdate_rspack_tests", + + "hotUpdateGlobal": "webpackHotUpdatemyLib", + @@ ... @@ + - "library": undefined, + + "library": Object { + + "amdContainer": undefined, + + "auxiliaryComment": undefined, + + "export": undefined, + + "name": Object { + + "root": Array [ + + "[name]", + + "myLib", + + ], + + }, + + "type": "var", + + "umdNamedDefine": undefined, + + }, + @@ ... @@ + - "uniqueName": "@rspack/tests", + + "uniqueName": "myLib", + `) }; diff --git a/tests/rspack-test/normalCases/parsing/renaming copy/file.js b/tests/rspack-test/normalCases/parsing/renaming copy/file.js deleted file mode 100644 index 654e0c92c5f7..000000000000 --- a/tests/rspack-test/normalCases/parsing/renaming copy/file.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = "ok"; \ No newline at end of file diff --git a/tests/rspack-test/normalCases/parsing/renaming copy/index.js b/tests/rspack-test/normalCases/parsing/renaming copy/index.js deleted file mode 100644 index fea96df2523b..000000000000 --- a/tests/rspack-test/normalCases/parsing/renaming copy/index.js +++ /dev/null @@ -1,86 +0,0 @@ -it("should be able to rename require by var", function() { - var cjsRequire; // just to make it difficult - var cjsRequire = require, cjsRequire2 = typeof require !== "undefined" && require; - expect(cjsRequire("./file")).toBe("ok"); - expect(cjsRequire2("./file")).toBe("ok"); -}); - -it("should be able to rename require by assign", function() { - var cjsRequire, cjsRequire2; - (function() { - cjsRequire = require; - cjsRequire2 = typeof require === "function" && require; - expect(cjsRequire("./file")).toBe("ok"); - expect(cjsRequire2("./file")).toBe("ok"); - }()); -}); - -it("should be able to rename require by IIFE", function() { - (function(cjsRequire) { - expect(cjsRequire("./file")).toBe("ok"); - }(require)); -}); - -it("should be able to rename require by IIFE call", function() { - (function(somethingElse, cjsRequire) { - expect(cjsRequire("./file")).toBe("ok"); - expect(somethingElse).toBe(123); - }.call(this, 123, typeof require === "function" ? require : "error")); -}); - -it("should be able to rename stuff by IIFE call", function() { - (function(_exports, _exports2, _module, _module2, _define, _define2, _require, _require2) { - _define(function(R, E, M) { - expect(R("./file")).toBe("ok"); - expect(_require("./file")).toBe("ok"); - expect(_require2("./file")).toBe("ok"); - expect(E).toBe(exports); - expect(_exports).toBe(exports); - expect(_exports2).toBe(exports); - expect(M).toBe(module); - expect(_module).toBe(module); - expect(_module2).toBe(module); - }); - _define2(["./file"], function(file) { - expect(file).toBe("ok"); - }); - }).call(this, - typeof exports !== 'undefined' ? exports : null, - exports, - typeof module !== 'undefined' ? module : null, - module, - typeof define !== 'undefined' ? define : null, - define, - typeof require !== 'undefined' ? require : null, - require); -}); - -it("should accept less parameters in a IIFE call", function() { - (function(r, require) { - expect(r("./file")).toBe("ok"); - expect((typeof require)).toBe("undefined"); - }(require)); -}); - -it("should accept more parameters in a IIFE call", function() { - (function() { - }(require)); -}); - -it("should be able to rename stuff by IIFE call", function() { - (function(_exports, _module, _define, _require) { - _define(function(R, E, M) { - expect(R("./file")).toBe("ok"); - expect(_require("./file")).toBe("ok"); - expect(E).toBe(exports); - expect(_exports).toBe(exports); - expect(M).toBe(module); - expect(_module).toBe(module); - }); - }).call(this, - typeof exports !== 'undefined' ? exports : null, - typeof module !== 'undefined' ? module : null, - typeof define !== 'undefined' ? define : null, - typeof require !== 'undefined' ? require : null); -}); - diff --git a/tests/rspack-test/normalCases/parsing/renaming/index.js b/tests/rspack-test/normalCases/parsing/renaming/index.js index 39af8a4ae80c..4e4c21889e09 100644 --- a/tests/rspack-test/normalCases/parsing/renaming/index.js +++ b/tests/rspack-test/normalCases/parsing/renaming/index.js @@ -1,88 +1,86 @@ it("should be able to rename require by var", function () { var cjsRequire; // just to make it difficult - var cjsRequire = require, - cjsRequire2 = typeof require !== "undefined" && require; - expect(typeof cjsRequire).toBe("function"); - expect(typeof cjsRequire2).toBe("function"); + var cjsRequire = require, cjsRequire2 = typeof require !== "undefined" && require; expect(cjsRequire("./file")).toBe("ok"); expect(cjsRequire2("./file")).toBe("ok"); }); -// it("should be able to rename require by assign", function() { -// var cjsRequire, cjsRequire2; -// (function() { -// cjsRequire = require; -// cjsRequire2 = typeof require === "function" && require; -// expect(cjsRequire("./file")).toBe("ok"); -// expect(cjsRequire2("./file")).toBe("ok"); -// }()); -// }); +it("should be able to rename require by assign", function () { + var cjsRequire, cjsRequire2; + (function () { + cjsRequire = require; + cjsRequire2 = typeof require === "function" && require; + expect(cjsRequire("./file")).toBe("ok"); + expect(cjsRequire2("./file")).toBe("ok"); + }()); +}); + +it("should be able to rename require by IIFE", function () { + (function (cjsRequire) { + expect(cjsRequire("./file")).toBe("ok"); + }(require)); +}); -// it("should be able to rename require by IIFE", function() { -// (function(cjsRequire) { -// expect(cjsRequire("./file")).toBe("ok"); -// }(require)); -// }); +it("should be able to rename require by IIFE call", function () { + (function (somethingElse, cjsRequire) { + expect(cjsRequire("./file")).toBe("ok"); + expect(somethingElse).toBe(123); + }.call(this, 123, typeof require === "function" ? require : "error")); +}); -// it("should be able to rename require by IIFE call", function() { -// (function(somethingElse, cjsRequire) { -// expect(cjsRequire("./file")).toBe("ok"); -// expect(somethingElse).toBe(123); -// }.call(this, 123, typeof require === "function" ? require : "error")); -// }); +it("should be able to rename stuff by IIFE call", function () { + (function (_exports, _exports2, _module, _module2, _define, _define2, _require, _require2) { + _define(function (R, E, M) { + expect(R("./file")).toBe("ok"); + expect(_require("./file")).toBe("ok"); + expect(_require2("./file")).toBe("ok"); + expect(E).toBe(exports); + expect(_exports).toBe(exports); + expect(_exports2).toBe(exports); + expect(M).toBe(module); + expect(_module).toBe(module); + expect(_module2).toBe(module); + }); + _define2(["./file"], function (file) { + expect(file).toBe("ok"); + }); + }).call(this, + typeof exports !== 'undefined' ? exports : null, + exports, + typeof module !== 'undefined' ? module : null, + module, + typeof define !== 'undefined' ? define : null, + define, + typeof require !== 'undefined' ? require : null, + require); +}); -// it("should be able to rename stuff by IIFE call", function() { -// (function(_exports, _exports2, _module, _module2, _define, _define2, _require, _require2) { -// _define(function(R, E, M) { -// expect(R("./file")).toBe("ok"); -// expect(_require("./file")).toBe("ok"); -// expect(_require2("./file")).toBe("ok"); -// expect(E).toBe(exports); -// expect(_exports).toBe(exports); -// expect(_exports2).toBe(exports); -// expect(M).toBe(module); -// expect(_module).toBe(module); -// expect(_module2).toBe(module); -// }); -// _define2(["./file"], function(file) { -// expect(file).toBe("ok"); -// }); -// }).call(this, -// typeof exports !== 'undefined' ? exports : null, -// exports, -// typeof module !== 'undefined' ? module : null, -// module, -// typeof define !== 'undefined' ? define : null, -// define, -// typeof require !== 'undefined' ? require : null, -// require); -// }); +it("should accept less parameters in a IIFE call", function () { + (function (r, require) { + expect(r("./file")).toBe("ok"); + expect((typeof require)).toBe("undefined"); + }(require)); +}); -// it("should accept less parameters in a IIFE call", function() { -// (function(r, require) { -// expect(r("./file")).toBe("ok"); -// expect((typeof require)).toBe("undefined"); -// }(require)); -// }); +it("should accept more parameters in a IIFE call", function () { + (function () { + }(require)); +}); -// it("should accept more parameters in a IIFE call", function() { -// (function() { -// }(require)); -// }); +it("should be able to rename stuff by IIFE call", function () { + (function (_exports, _module, _define, _require) { + _define(function (R, E, M) { + expect(R("./file")).toBe("ok"); + expect(_require("./file")).toBe("ok"); + expect(E).toBe(exports); + expect(_exports).toBe(exports); + expect(M).toBe(module); + expect(_module).toBe(module); + }); + }).call(this, + typeof exports !== 'undefined' ? exports : null, + typeof module !== 'undefined' ? module : null, + typeof define !== 'undefined' ? define : null, + typeof require !== 'undefined' ? require : null); +}); -// it("should be able to rename stuff by IIFE call", function() { -// (function(_exports, _module, _define, _require) { -// _define(function(R, E, M) { -// expect(R("./file")).toBe("ok"); -// expect(_require("./file")).toBe("ok"); -// expect(E).toBe(exports); -// expect(_exports).toBe(exports); -// expect(M).toBe(module); -// expect(_module).toBe(module); -// }); -// }).call(this, -// typeof exports !== 'undefined' ? exports : null, -// typeof module !== 'undefined' ? module : null, -// typeof define !== 'undefined' ? define : null, -// typeof require !== 'undefined' ? require : null); -// }); From a4152c52d2c4a8c2b85883a73d6672bba5d1820b Mon Sep 17 00:00:00 2001 From: pshu Date: Mon, 12 Jan 2026 10:59:48 +0800 Subject: [PATCH 35/87] fix(test): flaky test due to calling toJSON while hot updating (#12694) --- .../make/remove-dynamic-entry-with-loader/index.test.ts | 5 +---- .../make/remove-dynamic-entry-with-loader/rspack.config.js | 3 +++ 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/e2e/cases/make/remove-dynamic-entry-with-loader/index.test.ts b/tests/e2e/cases/make/remove-dynamic-entry-with-loader/index.test.ts index 669e6af32679..c25e216181ee 100644 --- a/tests/e2e/cases/make/remove-dynamic-entry-with-loader/index.test.ts +++ b/tests/e2e/cases/make/remove-dynamic-entry-with-loader/index.test.ts @@ -19,10 +19,7 @@ test('should compile', async ({ page, fileAction, rspack }) => { ), ); - await expect(async () => { - await page.reload(); - expect(await page.locator('#index1').innerText()).toBe('index1 updated'); - }).toPass(); + await expect(page.locator('#index1')).toContainText('index1 updated'); await expect(page.locator('#index2')).toHaveCount(0); await expect(page.locator('#webpack-dev-server-client-overlay')).toHaveCount( diff --git a/tests/e2e/cases/make/remove-dynamic-entry-with-loader/rspack.config.js b/tests/e2e/cases/make/remove-dynamic-entry-with-loader/rspack.config.js index 7604b3f96712..6ba5100271fc 100644 --- a/tests/e2e/cases/make/remove-dynamic-entry-with-loader/rspack.config.js +++ b/tests/e2e/cases/make/remove-dynamic-entry-with-loader/rspack.config.js @@ -26,6 +26,9 @@ module.exports = { }, context: __dirname, mode: 'development', + optimization: { + runtimeChunk: 'single', + }, plugins: [ new rspack.HtmlRspackPlugin(), function (compiler) { From df72860770ad12d2991fe6e5b439ceb5e0989285 Mon Sep 17 00:00:00 2001 From: CPunisher <1343316114@qq.com> Date: Mon, 12 Jan 2026 11:33:46 +0800 Subject: [PATCH 36/87] feat: impl `sync_trace` for `logger` tracing layer (#12687) * Sync node events for logger tracing * Align sync_trace * Remove unless info * Cargo shear * Use one writer * Filter JavaScript * Handle timestamps * Clippy * Clippy --- Cargo.lock | 15 +- Cargo.toml | 1 + crates/rspack_binding_api/src/trace_event.rs | 2 +- crates/rspack_tracing/Cargo.toml | 2 + crates/rspack_tracing/src/lib.rs | 30 ---- crates/rspack_tracing/src/stdout.rs | 169 +++++++++++++++++- .../tests/build/profile/profile.test.ts | 3 +- 7 files changed, 174 insertions(+), 48 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 13065d5a77ab..06b936ad9344 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -73,12 +73,6 @@ version = "0.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e9d4ee0d472d1cd2e28c97dfa124b3d8d992e10eb0a035f33f5d12e3a177ba3b" -[[package]] -name = "android-tzdata" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" - [[package]] name = "android_system_properties" version = "0.1.5" @@ -628,14 +622,13 @@ checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "chrono" -version = "0.4.39" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" +checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" dependencies = [ - "android-tzdata", "iana-time-zone", "num-traits", - "windows-targets 0.52.6", + "windows-link 0.2.1", ] [[package]] @@ -5121,7 +5114,9 @@ dependencies = [ name = "rspack_tracing" version = "0.7.1" dependencies = [ + "chrono", "rspack_tracing_perfetto", + "serde_json", "tracing-subscriber", ] diff --git a/Cargo.toml b/Cargo.toml index 20988b93f7a6..8aab94a8335b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,6 +30,7 @@ bytes = { version = "1.10.0", default-features = false } camino = { version = "1.2.2", default-features = false } cargo_toml = { version = "0.21.0", default-features = false } cfg-if = { version = "1.0.4", default-features = false } +chrono = { version = "0.4.42", default-features = false } clap = { version = "4.5.54", default-features = false } color-backtrace = { version = "0.7.2", default-features = false, features = ["use-backtrace-crate"] } concat-string = { version = "1.0.1", default-features = false } diff --git a/crates/rspack_binding_api/src/trace_event.rs b/crates/rspack_binding_api/src/trace_event.rs index 2c23ad8308ef..5ca1b63595ab 100644 --- a/crates/rspack_binding_api/src/trace_event.rs +++ b/crates/rspack_binding_api/src/trace_event.rs @@ -63,7 +63,7 @@ pub(super) fn register_global_trace( let mut state = state.borrow_mut(); if let TraceState::Uninitialized = *state { let mut tracer: Box = match layer.as_str() { - "logger" => Box::new(StdoutTracer), + "logger" => Box::new(StdoutTracer::default()), "perfetto" => Box::new(PerfettoTracer::default()), _ => anyhow::bail!( "Unexpected layer: {}, supported layers:'logger', 'perfetto' ", diff --git a/crates/rspack_tracing/Cargo.toml b/crates/rspack_tracing/Cargo.toml index 0d0068be7ea1..eac9f573e9e6 100644 --- a/crates/rspack_tracing/Cargo.toml +++ b/crates/rspack_tracing/Cargo.toml @@ -8,5 +8,7 @@ version.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +chrono = { workspace = true, features = ["alloc"] } rspack_tracing_perfetto = { workspace = true } +serde_json = { workspace = true } tracing-subscriber = { workspace = true, features = ["env-filter", "json"] } diff --git a/crates/rspack_tracing/src/lib.rs b/crates/rspack_tracing/src/lib.rs index e85233b111c5..0c2a418e0fe6 100644 --- a/crates/rspack_tracing/src/lib.rs +++ b/crates/rspack_tracing/src/lib.rs @@ -2,36 +2,6 @@ mod perfetto; mod stdout; mod tracer; -use std::{fs, io, path::PathBuf}; - pub use perfetto::PerfettoTracer; pub use stdout::StdoutTracer; pub use tracer::{TraceEvent, Tracer}; -use tracing_subscriber::fmt::writer::BoxMakeWriter; -pub(crate) enum TraceWriter { - Stdout, - Stderr, - File { path: PathBuf }, -} - -impl From for TraceWriter { - fn from(s: String) -> Self { - match s.as_str() { - "stdout" => Self::Stdout, - "stderr" => Self::Stderr, - _ => Self::File { path: s.into() }, - } - } -} - -impl TraceWriter { - pub fn make_writer(&self) -> BoxMakeWriter { - match self { - TraceWriter::Stdout => BoxMakeWriter::new(io::stdout), - TraceWriter::Stderr => BoxMakeWriter::new(io::stderr), - TraceWriter::File { path } => { - BoxMakeWriter::new(fs::File::create(path).expect("Failed to create trace file")) - } - } - } -} diff --git a/crates/rspack_tracing/src/stdout.rs b/crates/rspack_tracing/src/stdout.rs index a8adde5f8ccc..5a126d423dab 100644 --- a/crates/rspack_tracing/src/stdout.rs +++ b/crates/rspack_tracing/src/stdout.rs @@ -1,28 +1,185 @@ -use tracing_subscriber::fmt::format::FmtSpan; +use std::{ + io::Write, + sync::{Arc, Mutex}, +}; + +use tracing_subscriber::fmt::{MakeWriter, format::FmtSpan}; use crate::{ - TraceWriter, + TraceEvent, tracer::{Layered, Tracer}, }; -pub struct StdoutTracer; +// A custom MakeWriter that wraps a shared Arc> writer +#[derive(Clone)] +struct SharedWriterMaker { + writer: Arc>, +} + +// Wrapper to implement Write trait for the MakeWriter +struct SharedWriter { + writer: Arc>, +} + +impl Write for SharedWriter { + fn write(&mut self, buf: &[u8]) -> std::io::Result { + self + .writer + .lock() + .expect("Failed to lock writer") + .write(buf) + } + + fn flush(&mut self) -> std::io::Result<()> { + self.writer.lock().expect("Failed to lock writer").flush() + } +} + +impl<'a> MakeWriter<'a> for SharedWriterMaker { + type Writer = SharedWriter; + + fn make_writer(&'a self) -> Self::Writer { + SharedWriter { + writer: self.writer.clone(), + } + } +} + +/// Converts a microsecond timestamp to ISO 8601 format with microsecond precision +/// Example: 1704708707916028 -> "2026-01-08T11:31:47.916028Z" +fn format_timestamp_iso8601(micros: u64) -> String { + use chrono::{DateTime, Utc}; + + let secs = (micros / 1_000_000) as i64; + let subsec_micros = (micros % 1_000_000) as u32; + let nanos = subsec_micros * 1000; + + DateTime::::from_timestamp(secs, nanos) + .map(|dt| dt.to_rfc3339_opts(chrono::SecondsFormat::Micros, true)) + .unwrap_or_else(|| "Invalid timestamp".to_string()) +} + +#[derive(Default)] +pub struct StdoutTracer { + begin_ts: u64, + writer: Option>>, +} impl Tracer for StdoutTracer { fn setup(&mut self, output: &str) -> Option { use tracing_subscriber::{fmt, prelude::*}; - let trace_writer = TraceWriter::from(output.to_owned()); + + // Record the start time in microseconds since UNIX epoch + self.begin_ts = std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .expect("System time before UNIX epoch") + .as_micros() as u64; + + // Create the shared writer wrapped in Arc> + let writer: Arc>> = match output { + "stdout" => Arc::new(Mutex::new(Box::new(std::io::stdout()))), + "stderr" => Arc::new(Mutex::new(Box::new(std::io::stderr()))), + path => { + let file = std::fs::File::create(path) + .unwrap_or_else(|e| panic!("Failed to create trace file: {path} due to {e}")); + Arc::new(Mutex::new(Box::new(file))) + } + }; + + // Store the shared writer for sync_trace + self.writer = Some(writer.clone()); + + // Create a custom MakeWriter that uses the same shared writer + let make_writer = SharedWriterMaker { writer }; + Some( fmt::layer() .json() // Use JSON format for structured logging for easier parsing and debugging .with_file(false) // To keep track of the closing point of spans .with_span_events(FmtSpan::CLOSE) - .with_writer(trace_writer.make_writer()) + .with_writer(make_writer) .boxed(), ) } + fn sync_trace(&mut self, events: Vec) { + if let Some(writer) = &self.writer { + use std::collections::HashMap; + + // Track begin events by uuid to match with end events + let mut pending_events: HashMap = HashMap::new(); + + for event in events { + match event.ph.as_str() { + "b" => { + // Store begin event + pending_events.insert(event.uuid, event); + } + "e" => { + // Find matching begin event and calculate duration + if let Some(begin_event) = pending_events.remove(&event.uuid) { + let duration_ns = event.ts.saturating_sub(begin_event.ts); + let duration_ms = duration_ns as f64 / 1_000_000.0; + + // Build fields object + let mut fields = serde_json::Map::new(); + fields.insert("message".to_string(), serde_json::json!("close")); + fields.insert( + "time.busy".to_string(), + serde_json::json!(format!("{:.2}ms", duration_ms)), + ); + + // Add any args from the event + if let Some(args) = begin_event.args { + for (key, value) in args { + fields.insert(key, serde_json::json!(value)); + } + } + + // Build span object if we have track_name + let span_obj = begin_event.track_name.map(|track_name| { + serde_json::json!({ + "name": track_name, + }) + }); + + // Convert relative microsecond timestamp to absolute ISO 8601 format + let absolute_ts_micros = self.begin_ts + begin_event.ts; + let timestamp_iso = format_timestamp_iso8601(absolute_ts_micros); + + // Build JSON in Rust trace format + let json_value = serde_json::json!({ + "timestamp": timestamp_iso, + "level": "DEBUG", + "fields": fields, + "target": "javascript", + "span": span_obj, + }); + + if let Ok(json_str) = serde_json::to_string(&json_value) { + // Lock the mutex to access the writer + let _ = writeln!( + writer.lock().expect("Failed to lock writer"), + "{}", + json_str + ); + } + } + } + _ => {} + } + } + + // Flush to ensure events are written immediately + let _ = writer.lock().expect("Failed to lock writer").flush(); + } + } + fn teardown(&mut self) { - // noop + // Flush any remaining data + if let Some(writer) = &self.writer { + let _ = writer.lock().expect("Failed to lock writer").flush(); + } } } diff --git a/packages/rspack-cli/tests/build/profile/profile.test.ts b/packages/rspack-cli/tests/build/profile/profile.test.ts index 82692c198be8..d04aa41809e5 100644 --- a/packages/rspack-cli/tests/build/profile/profile.test.ts +++ b/packages/rspack-cli/tests/build/profile/profile.test.ts @@ -75,7 +75,8 @@ describe('profile', () => { .every( (line) => line.target.startsWith('rspack') || - line.target.startsWith('rspack_resolver'), + line.target.startsWith('rspack_resolver') || + line.target.startsWith('javascript'), ), ).toBe(true); }); From eb5635c6f248853df96245c9d0a710340e41d6ae Mon Sep 17 00:00:00 2001 From: harpsealjs Date: Mon, 12 Jan 2026 14:26:33 +0800 Subject: [PATCH 37/87] feat: add warning when requireAlias is disabled (#12700) --- .../src/parser_plugin/amd/amd_plugin.rs | 7 ++++++- .../common_js_imports_parse_plugin.rs | 16 ++++++++++++++-- .../src/parser_plugin/define_plugin/parser.rs | 2 +- .../src/parser_plugin/drive.rs | 4 ++-- .../src/parser_plugin/provide_plugin/parser.rs | 4 ++-- .../src/parser_plugin/trait.rs | 2 +- .../src/parser_plugin/url_plugin.rs | 7 ++++++- .../src/visitors/dependency/parser/walk.rs | 10 +++++++--- .../parsing/renaming-disabled/warnings.js | 4 ++++ 9 files changed, 43 insertions(+), 13 deletions(-) create mode 100644 tests/rspack-test/configCases/parsing/renaming-disabled/warnings.js diff --git a/crates/rspack_plugin_javascript/src/parser_plugin/amd/amd_plugin.rs b/crates/rspack_plugin_javascript/src/parser_plugin/amd/amd_plugin.rs index fbe83a8ab2c2..27ea6b959b5a 100644 --- a/crates/rspack_plugin_javascript/src/parser_plugin/amd/amd_plugin.rs +++ b/crates/rspack_plugin_javascript/src/parser_plugin/amd/amd_plugin.rs @@ -184,7 +184,12 @@ impl JavascriptParserPlugin for AMDParserPlugin { None } - fn can_rename(&self, _parser: &mut JavascriptParser, for_name: &str) -> Option { + fn can_rename( + &self, + _parser: &mut JavascriptParser, + _expr: &Expr, + for_name: &str, + ) -> Option { if for_name == DEFINE { return Some(true); } diff --git a/crates/rspack_plugin_javascript/src/parser_plugin/common_js_imports_parse_plugin.rs b/crates/rspack_plugin_javascript/src/parser_plugin/common_js_imports_parse_plugin.rs index 2102bb8ad4f4..e03a48abf5c7 100644 --- a/crates/rspack_plugin_javascript/src/parser_plugin/common_js_imports_parse_plugin.rs +++ b/crates/rspack_plugin_javascript/src/parser_plugin/common_js_imports_parse_plugin.rs @@ -402,9 +402,21 @@ impl CommonJsImportsParserPlugin { } impl JavascriptParserPlugin for CommonJsImportsParserPlugin { - fn can_rename(&self, parser: &mut JavascriptParser, for_name: &str) -> Option { + fn can_rename(&self, parser: &mut JavascriptParser, expr: &Expr, for_name: &str) -> Option { if for_name == expr_name::REQUIRE { - Some(parser.javascript_options.require_alias.unwrap_or(true)) + let require_alias = parser.javascript_options.require_alias.unwrap_or(true); + if !require_alias { + let mut warning = create_traceable_error( + "Critical dependency".into(), + "please enable 'module.parser.javascript.requireAlias' to analyze require alias" + .to_string(), + parser.source.to_owned(), + expr.span().into(), + ); + warning.severity = Severity::Warning; + parser.add_warning(warning.into()); + } + Some(require_alias) } else { None } diff --git a/crates/rspack_plugin_javascript/src/parser_plugin/define_plugin/parser.rs b/crates/rspack_plugin_javascript/src/parser_plugin/define_plugin/parser.rs index 2a330a5cceee..6ec6ad017eb0 100644 --- a/crates/rspack_plugin_javascript/src/parser_plugin/define_plugin/parser.rs +++ b/crates/rspack_plugin_javascript/src/parser_plugin/define_plugin/parser.rs @@ -52,7 +52,7 @@ impl DefineParserPlugin { } impl JavascriptParserPlugin for DefineParserPlugin { - fn can_rename(&self, parser: &mut JavascriptParser, str: &str) -> Option { + fn can_rename(&self, parser: &mut JavascriptParser, _expr: &Expr, str: &str) -> Option { if let Some(first_key) = self.walk_data.can_rename.get(str) { self.add_value_dependency(parser, str); if let Some(first_key) = first_key diff --git a/crates/rspack_plugin_javascript/src/parser_plugin/drive.rs b/crates/rspack_plugin_javascript/src/parser_plugin/drive.rs index 2424925e32eb..4420badb42c6 100644 --- a/crates/rspack_plugin_javascript/src/parser_plugin/drive.rs +++ b/crates/rspack_plugin_javascript/src/parser_plugin/drive.rs @@ -579,9 +579,9 @@ impl JavascriptParserPlugin for JavaScriptParserPluginDrive { None } - fn can_rename(&self, parser: &mut JavascriptParser, str: &str) -> Option { + fn can_rename(&self, parser: &mut JavascriptParser, expr: &Expr, str: &str) -> Option { for plugin in &self.plugins { - let res = plugin.can_rename(parser, str); + let res = plugin.can_rename(parser, expr, str); // `SyncBailHook` if res.is_some() { return res; diff --git a/crates/rspack_plugin_javascript/src/parser_plugin/provide_plugin/parser.rs b/crates/rspack_plugin_javascript/src/parser_plugin/provide_plugin/parser.rs index a65e35304492..b6c82e5a7551 100644 --- a/crates/rspack_plugin_javascript/src/parser_plugin/provide_plugin/parser.rs +++ b/crates/rspack_plugin_javascript/src/parser_plugin/provide_plugin/parser.rs @@ -4,7 +4,7 @@ use cow_utils::CowUtils; use itertools::Itertools; use rspack_core::DependencyRange; use rustc_hash::FxHashSet as HashSet; -use swc_core::{atoms::Atom, common::Spanned}; +use swc_core::{atoms::Atom, common::Spanned, ecma::ast::Expr}; use super::{super::JavascriptParserPlugin, ProvideValue, VALUE_DEP_PREFIX}; use crate::{dependency::ProvideDependency, visitors::JavascriptParser}; @@ -62,7 +62,7 @@ impl ProvideParserPlugin { } impl JavascriptParserPlugin for ProvideParserPlugin { - fn can_rename(&self, _parser: &mut JavascriptParser, str: &str) -> Option { + fn can_rename(&self, _parser: &mut JavascriptParser, _expr: &Expr, str: &str) -> Option { self.names.contains(str).then_some(true) } diff --git a/crates/rspack_plugin_javascript/src/parser_plugin/trait.rs b/crates/rspack_plugin_javascript/src/parser_plugin/trait.rs index e6c281f85db7..b788569e7a79 100644 --- a/crates/rspack_plugin_javascript/src/parser_plugin/trait.rs +++ b/crates/rspack_plugin_javascript/src/parser_plugin/trait.rs @@ -38,7 +38,7 @@ pub trait JavascriptParserPlugin { /// The return value will have no effect. fn top_level_for_of_await_stmt(&self, _parser: &mut JavascriptParser, _stmt: &ForOfStmt) {} - fn can_rename(&self, _parser: &mut JavascriptParser, _str: &str) -> Option { + fn can_rename(&self, _parser: &mut JavascriptParser, _expr: &Expr, _str: &str) -> Option { None } diff --git a/crates/rspack_plugin_javascript/src/parser_plugin/url_plugin.rs b/crates/rspack_plugin_javascript/src/parser_plugin/url_plugin.rs index 70e89ff3c003..ee8d932e37dc 100644 --- a/crates/rspack_plugin_javascript/src/parser_plugin/url_plugin.rs +++ b/crates/rspack_plugin_javascript/src/parser_plugin/url_plugin.rs @@ -104,7 +104,12 @@ pub struct URLPlugin { } impl JavascriptParserPlugin for URLPlugin { - fn can_rename(&self, _parser: &mut JavascriptParser, for_name: &str) -> Option { + fn can_rename( + &self, + _parser: &mut JavascriptParser, + _expr: &Expr, + for_name: &str, + ) -> Option { (for_name == "URL").then_some(true) } diff --git a/crates/rspack_plugin_javascript/src/visitors/dependency/parser/walk.rs b/crates/rspack_plugin_javascript/src/visitors/dependency/parser/walk.rs index 734f7d8ede8a..c05c4c472cc3 100644 --- a/crates/rspack_plugin_javascript/src/visitors/dependency/parser/walk.rs +++ b/crates/rspack_plugin_javascript/src/visitors/dependency/parser/walk.rs @@ -375,7 +375,7 @@ impl JavascriptParser<'_> { { let drive = self.plugin_drive.clone(); if drive - .can_rename(self, &renamed_identifier) + .can_rename(self, init, &renamed_identifier) .unwrap_or_default() { if !drive @@ -930,7 +930,9 @@ impl JavascriptParser<'_> { if let Some(rename_identifier) = parser.get_rename_identifier(expr) && let drive = parser.plugin_drive.clone() && rename_identifier - .call_hooks_name(parser, |this, for_name| drive.can_rename(this, for_name)) + .call_hooks_name(parser, |this, for_name| { + drive.can_rename(this, expr, for_name) + }) .unwrap_or_default() && !rename_identifier .call_hooks_name(parser, |this, for_name| drive.rename(this, expr, for_name)) @@ -1257,7 +1259,9 @@ impl JavascriptParser<'_> { if let Some(rename_identifier) = self.get_rename_identifier(&expr.right) && let drive = self.plugin_drive.clone() && rename_identifier - .call_hooks_name(self, |this, for_name| drive.can_rename(this, for_name)) + .call_hooks_name(self, |this, for_name| { + drive.can_rename(this, &expr.right, for_name) + }) .unwrap_or_default() { if !rename_identifier diff --git a/tests/rspack-test/configCases/parsing/renaming-disabled/warnings.js b/tests/rspack-test/configCases/parsing/renaming-disabled/warnings.js new file mode 100644 index 000000000000..01ec4f489bf9 --- /dev/null +++ b/tests/rspack-test/configCases/parsing/renaming-disabled/warnings.js @@ -0,0 +1,4 @@ +module.exports = [ + [/Critical dependency: please enable 'module.parser.javascript.requireAlias' to analyze require alias/], + [/Critical dependency: please enable 'module.parser.javascript.requireAlias' to analyze require alias/] +] \ No newline at end of file From b8e674b992860f336e903d8e54288b8aaed9ae30 Mon Sep 17 00:00:00 2001 From: "zhanghang.heal" Date: Mon, 12 Jan 2026 16:05:11 +0800 Subject: [PATCH 38/87] refactor: rename tree shaking field name --- crates/node_binding/napi-binding.d.ts | 8 +- crates/node_binding/rspack.wasi-browser.js | 61 +-------- crates/node_binding/rspack.wasi.cjs | 61 +-------- .../src/raw_options/raw_builtins/raw_mf.rs | 18 +-- .../src/sharing/consume_shared_module.rs | 2 +- .../src/sharing/consume_shared_plugin.rs | 6 +- .../sharing/consume_shared_runtime_module.rs | 6 +- .../src/sharing/provide_shared_dependency.rs | 6 +- .../src/sharing/provide_shared_module.rs | 8 +- .../sharing/provide_shared_module_factory.rs | 2 +- .../src/sharing/provide_shared_plugin.rs | 18 +-- .../src/sharing/share_runtime_module.rs | 6 +- .../shared_used_exports_optimizer_plugin.rs | 16 +-- packages/rspack/etc/core.api.md | 34 ++--- packages/rspack/package.json | 2 +- .../ModuleFederationManifestPlugin.ts | 12 +- .../src/container/ModuleFederationPlugin.ts | 32 ++--- packages/rspack/src/exports.ts | 6 +- .../runtime/moduleFederationDefaultRuntime.js | 12 +- .../rspack/src/sharing/ConsumeSharedPlugin.ts | 11 +- .../src/sharing/IndependentSharedPlugin.ts | 65 ++++------ .../rspack/src/sharing/ProvideSharedPlugin.ts | 4 +- packages/rspack/src/sharing/SharePlugin.ts | 10 +- .../SharedUsedExportsOptimizerPlugin.ts | 14 +- ...edPlugin.ts => TreeShakingSharedPlugin.ts} | 27 ++-- pnpm-lock.yaml | 101 ++++++++++----- .../App.js | 8 +- .../index.js | 32 ++--- .../node_modules/@scope-sc/ui-lib/index.js | 0 .../@scope-sc/ui-lib/package.json | 0 .../ui-lib-dynamic-default-export/index.js | 0 .../package.json | 0 .../ui-lib-dynamic-specific-export/index.js | 0 .../package.json | 0 .../node_modules/ui-lib-es/index.js | 0 .../node_modules/ui-lib-es/package.json | 0 .../node_modules/ui-lib-side-effect/index.js | 0 .../ui-lib-side-effect/package.json | 0 .../node_modules/ui-lib/index.js | 0 .../node_modules/ui-lib/package.json | 0 .../rspack.config.js | 28 ++-- .../runtime-plugin.js | 2 +- .../test.config.js | 0 .../App.js | 8 +- .../index.js | 32 ++--- .../node_modules/.federation/shared-entry.js | 0 .../ui-lib-dynamic-default-export/index.js | 0 .../package.json | 0 .../ui-lib-dynamic-specific-export/index.js | 0 .../package.json | 0 .../node_modules/ui-lib-es/index.js | 0 .../node_modules/ui-lib-es/package.json | 0 .../node_modules/ui-lib-side-effect/index.js | 0 .../ui-lib-side-effect/package.json | 0 .../node_modules/ui-lib/index.js | 0 .../node_modules/ui-lib/package.json | 0 .../rspack.config.js | 24 ++-- .../runtime-plugin.js | 2 +- .../test.config.js | 0 .../collect-share-entry-plugin/index.js | 14 -- .../collect-share-entry-plugin/module.js | 3 - .../node_modules/xreact/index.js | 4 - .../node_modules/xreact/package.json | 5 - .../collect-share-entry-plugin/package.json | 5 - .../rspack.config.js | 39 ------ .../sharing/reshake-share/CustomPlugin.js | 16 +++ .../sharing/reshake-share/index.js | 27 ++-- .../node_modules/ui-lib-dep/index.js | 6 - .../node_modules/ui-lib/index.js | 10 +- .../sharing/reshake-share/rspack.config.js | 44 +++---- .../sharing/tree-shaking-shared/App.js | 23 ++++ .../sharing/tree-shaking-shared/index.js | 122 ++++++++++++++++++ .../ui-lib-dynamic-default-export}/index.js | 0 .../package.json | 6 + .../ui-lib-dynamic-specific-export/index.js | 3 + .../package.json | 6 + .../node_modules/ui-lib-es/index.js | 3 + .../node_modules/ui-lib-es}/package.json | 2 +- .../node_modules/ui-lib-side-effect/index.js | 0 .../ui-lib-side-effect/package.json | 0 .../node_modules/ui-lib}/index.js | 0 .../node_modules/ui-lib/package.json | 0 .../tree-shaking-shared/rspack.config.js | 59 +++++++++ .../tree-shaking-shared/runtime-plugin.js | 18 +++ .../sharing/treeshake-share/index.js | 74 ----------- .../sharing/treeshake-share/rspack.config.js | 36 ------ .../configCases/sri/mf/rspack.config.js | 3 + .../share-plugin/__snapshots__/web/1.snap.txt | 4 +- .../webpack/tree-shake-shared-plugin.mdx | 10 +- .../webpack/tree-shake-shared-plugin.mdx | 12 +- 90 files changed, 608 insertions(+), 630 deletions(-) rename packages/rspack/src/sharing/{TreeShakeSharedPlugin.ts => TreeShakingSharedPlugin.ts} (66%) rename tests/rspack-test/configCases/container-1-5/{treeshake-shared-infer-strategy => tree-shaking-shared-infer-mode}/App.js (76%) rename tests/rspack-test/configCases/container-1-5/{treeshake-shared-infer-strategy => tree-shaking-shared-infer-mode}/index.js (76%) rename tests/rspack-test/configCases/container-1-5/{treeshake-shared-infer-strategy => tree-shaking-shared-infer-mode}/node_modules/@scope-sc/ui-lib/index.js (100%) rename tests/rspack-test/configCases/container-1-5/{treeshake-shared-infer-strategy => tree-shaking-shared-infer-mode}/node_modules/@scope-sc/ui-lib/package.json (100%) rename tests/rspack-test/configCases/container-1-5/{treeshake-shared-infer-strategy => tree-shaking-shared-infer-mode}/node_modules/ui-lib-dynamic-default-export/index.js (100%) rename tests/rspack-test/configCases/container-1-5/{treeshake-shared-infer-strategy => tree-shaking-shared-infer-mode}/node_modules/ui-lib-dynamic-default-export/package.json (100%) rename tests/rspack-test/configCases/container-1-5/{treeshake-shared-infer-strategy => tree-shaking-shared-infer-mode}/node_modules/ui-lib-dynamic-specific-export/index.js (100%) rename tests/rspack-test/configCases/container-1-5/{treeshake-shared-infer-strategy => tree-shaking-shared-infer-mode}/node_modules/ui-lib-dynamic-specific-export/package.json (100%) rename tests/rspack-test/configCases/container-1-5/{treeshake-shared-infer-strategy => tree-shaking-shared-infer-mode}/node_modules/ui-lib-es/index.js (100%) rename tests/rspack-test/configCases/container-1-5/{treeshake-shared-infer-strategy => tree-shaking-shared-infer-mode}/node_modules/ui-lib-es/package.json (100%) rename tests/rspack-test/configCases/container-1-5/{treeshake-shared-infer-strategy => tree-shaking-shared-infer-mode}/node_modules/ui-lib-side-effect/index.js (100%) rename tests/rspack-test/configCases/container-1-5/{treeshake-shared-infer-strategy => tree-shaking-shared-infer-mode}/node_modules/ui-lib-side-effect/package.json (100%) rename tests/rspack-test/configCases/container-1-5/{treeshake-shared-infer-strategy => tree-shaking-shared-infer-mode}/node_modules/ui-lib/index.js (100%) rename tests/rspack-test/configCases/container-1-5/{treeshake-shared-infer-strategy => tree-shaking-shared-infer-mode}/node_modules/ui-lib/package.json (100%) rename tests/rspack-test/configCases/container-1-5/{treeshake-shared-infer-strategy => tree-shaking-shared-infer-mode}/rspack.config.js (75%) rename tests/rspack-test/configCases/container-1-5/{treeshake-shared-infer-strategy => tree-shaking-shared-infer-mode}/runtime-plugin.js (82%) rename tests/rspack-test/configCases/container-1-5/{treeshake-shared-infer-strategy => tree-shaking-shared-infer-mode}/test.config.js (100%) rename tests/rspack-test/configCases/container-1-5/{treeshake-shared-server-strategy => tree-shaking-shared-server-mode}/App.js (71%) rename tests/rspack-test/configCases/container-1-5/{treeshake-shared-server-strategy => tree-shaking-shared-server-mode}/index.js (73%) rename tests/rspack-test/configCases/container-1-5/{treeshake-shared-server-strategy => tree-shaking-shared-server-mode}/node_modules/.federation/shared-entry.js (100%) rename tests/rspack-test/configCases/container-1-5/{treeshake-shared-server-strategy => tree-shaking-shared-server-mode}/node_modules/ui-lib-dynamic-default-export/index.js (100%) rename tests/rspack-test/configCases/container-1-5/{treeshake-shared-server-strategy => tree-shaking-shared-server-mode}/node_modules/ui-lib-dynamic-default-export/package.json (100%) rename tests/rspack-test/configCases/container-1-5/{treeshake-shared-server-strategy => tree-shaking-shared-server-mode}/node_modules/ui-lib-dynamic-specific-export/index.js (100%) rename tests/rspack-test/configCases/container-1-5/{treeshake-shared-server-strategy => tree-shaking-shared-server-mode}/node_modules/ui-lib-dynamic-specific-export/package.json (100%) rename tests/rspack-test/configCases/container-1-5/{treeshake-shared-server-strategy => tree-shaking-shared-server-mode}/node_modules/ui-lib-es/index.js (100%) rename tests/rspack-test/configCases/container-1-5/{treeshake-shared-server-strategy => tree-shaking-shared-server-mode}/node_modules/ui-lib-es/package.json (100%) rename tests/rspack-test/configCases/container-1-5/{treeshake-shared-server-strategy => tree-shaking-shared-server-mode}/node_modules/ui-lib-side-effect/index.js (100%) rename tests/rspack-test/configCases/container-1-5/{treeshake-shared-server-strategy => tree-shaking-shared-server-mode}/node_modules/ui-lib-side-effect/package.json (100%) rename tests/rspack-test/configCases/container-1-5/{treeshake-shared-server-strategy => tree-shaking-shared-server-mode}/node_modules/ui-lib/index.js (100%) rename tests/rspack-test/configCases/container-1-5/{treeshake-shared-server-strategy => tree-shaking-shared-server-mode}/node_modules/ui-lib/package.json (100%) rename tests/rspack-test/configCases/container-1-5/{treeshake-shared-server-strategy => tree-shaking-shared-server-mode}/rspack.config.js (76%) rename tests/rspack-test/configCases/container-1-5/{treeshake-shared-server-strategy => tree-shaking-shared-server-mode}/runtime-plugin.js (82%) rename tests/rspack-test/configCases/container-1-5/{treeshake-shared-server-strategy => tree-shaking-shared-server-mode}/test.config.js (100%) delete mode 100644 tests/rspack-test/configCases/sharing/collect-share-entry-plugin/index.js delete mode 100644 tests/rspack-test/configCases/sharing/collect-share-entry-plugin/module.js delete mode 100644 tests/rspack-test/configCases/sharing/collect-share-entry-plugin/node_modules/xreact/index.js delete mode 100644 tests/rspack-test/configCases/sharing/collect-share-entry-plugin/node_modules/xreact/package.json delete mode 100644 tests/rspack-test/configCases/sharing/collect-share-entry-plugin/package.json delete mode 100644 tests/rspack-test/configCases/sharing/collect-share-entry-plugin/rspack.config.js create mode 100644 tests/rspack-test/configCases/sharing/reshake-share/CustomPlugin.js create mode 100644 tests/rspack-test/configCases/sharing/tree-shaking-shared/App.js create mode 100644 tests/rspack-test/configCases/sharing/tree-shaking-shared/index.js rename tests/rspack-test/configCases/sharing/{treeshake-share/node_modules/ui-lib => tree-shaking-shared/node_modules/ui-lib-dynamic-default-export}/index.js (100%) create mode 100644 tests/rspack-test/configCases/sharing/tree-shaking-shared/node_modules/ui-lib-dynamic-default-export/package.json create mode 100644 tests/rspack-test/configCases/sharing/tree-shaking-shared/node_modules/ui-lib-dynamic-specific-export/index.js create mode 100644 tests/rspack-test/configCases/sharing/tree-shaking-shared/node_modules/ui-lib-dynamic-specific-export/package.json create mode 100644 tests/rspack-test/configCases/sharing/tree-shaking-shared/node_modules/ui-lib-es/index.js rename tests/rspack-test/configCases/sharing/{treeshake-share/node_modules/ui-lib2 => tree-shaking-shared/node_modules/ui-lib-es}/package.json (76%) rename tests/rspack-test/configCases/sharing/{treeshake-share => tree-shaking-shared}/node_modules/ui-lib-side-effect/index.js (100%) rename tests/rspack-test/configCases/sharing/{treeshake-share => tree-shaking-shared}/node_modules/ui-lib-side-effect/package.json (100%) rename tests/rspack-test/configCases/sharing/{treeshake-share/node_modules/ui-lib2 => tree-shaking-shared/node_modules/ui-lib}/index.js (100%) rename tests/rspack-test/configCases/sharing/{treeshake-share => tree-shaking-shared}/node_modules/ui-lib/package.json (100%) create mode 100644 tests/rspack-test/configCases/sharing/tree-shaking-shared/rspack.config.js create mode 100644 tests/rspack-test/configCases/sharing/tree-shaking-shared/runtime-plugin.js delete mode 100644 tests/rspack-test/configCases/sharing/treeshake-share/index.js delete mode 100644 tests/rspack-test/configCases/sharing/treeshake-share/rspack.config.js diff --git a/crates/node_binding/napi-binding.d.ts b/crates/node_binding/napi-binding.d.ts index 1be9b92ba3c4..76c85645e222 100644 --- a/crates/node_binding/napi-binding.d.ts +++ b/crates/node_binding/napi-binding.d.ts @@ -1865,7 +1865,7 @@ export interface RawConsumeOptions { strictVersion: boolean singleton: boolean eager: boolean - treeshakeStrategy?: string + treeShakingMode?: string } export interface RawConsumeSharedPluginOptions { @@ -2598,7 +2598,7 @@ export interface RawOptimizationOptions { export interface RawOptimizeSharedConfig { shareKey: string - treeshake: boolean + treeShaking: boolean usedExports?: Array } @@ -2702,7 +2702,7 @@ export interface RawProvideOptions { singleton?: boolean requiredVersion?: string | false | undefined strictVersion?: boolean - treeshakeStrategy?: string + treeShakingMode?: string } export interface RawRelated { @@ -2850,7 +2850,7 @@ export interface RawSharedContainerPluginOptions { export interface RawSharedUsedExportsOptimizerPluginOptions { shared: Array - injectUsedExports?: boolean + injectTreeShakingUsedExports?: boolean manifestFileName?: string statsFileName?: string } diff --git a/crates/node_binding/rspack.wasi-browser.js b/crates/node_binding/rspack.wasi-browser.js index e3e5c0a99d48..ee65959b37bc 100644 --- a/crates/node_binding/rspack.wasi-browser.js +++ b/crates/node_binding/rspack.wasi-browser.js @@ -63,63 +63,4 @@ const { }, }) export default __napiModule.exports -export const Assets = __napiModule.exports.Assets -export const AsyncDependenciesBlock = __napiModule.exports.AsyncDependenciesBlock -export const Chunk = __napiModule.exports.Chunk -export const ChunkGraph = __napiModule.exports.ChunkGraph -export const ChunkGroup = __napiModule.exports.ChunkGroup -export const Chunks = __napiModule.exports.Chunks -export const CodeGenerationResult = __napiModule.exports.CodeGenerationResult -export const CodeGenerationResults = __napiModule.exports.CodeGenerationResults -export const ConcatenatedModule = __napiModule.exports.ConcatenatedModule -export const ContextModule = __napiModule.exports.ContextModule -export const Dependency = __napiModule.exports.Dependency -export const Diagnostics = __napiModule.exports.Diagnostics -export const EntryDataDto = __napiModule.exports.EntryDataDto -export const EntryDataDTO = __napiModule.exports.EntryDataDTO -export const EntryDependency = __napiModule.exports.EntryDependency -export const EntryOptionsDto = __napiModule.exports.EntryOptionsDto -export const EntryOptionsDTO = __napiModule.exports.EntryOptionsDTO -export const ExternalModule = __napiModule.exports.ExternalModule -export const JsCompilation = __napiModule.exports.JsCompilation -export const JsCompiler = __napiModule.exports.JsCompiler -export const JsContextModuleFactoryAfterResolveData = __napiModule.exports.JsContextModuleFactoryAfterResolveData -export const JsContextModuleFactoryBeforeResolveData = __napiModule.exports.JsContextModuleFactoryBeforeResolveData -export const JsDependencies = __napiModule.exports.JsDependencies -export const JsEntries = __napiModule.exports.JsEntries -export const JsExportsInfo = __napiModule.exports.JsExportsInfo -export const JsModuleGraph = __napiModule.exports.JsModuleGraph -export const JsResolver = __napiModule.exports.JsResolver -export const JsResolverFactory = __napiModule.exports.JsResolverFactory -export const JsStats = __napiModule.exports.JsStats -export const KnownBuildInfo = __napiModule.exports.KnownBuildInfo -export const Module = __napiModule.exports.Module -export const ModuleGraphConnection = __napiModule.exports.ModuleGraphConnection -export const NativeWatcher = __napiModule.exports.NativeWatcher -export const NativeWatchResult = __napiModule.exports.NativeWatchResult -export const NormalModule = __napiModule.exports.NormalModule -export const RawExternalItemFnCtx = __napiModule.exports.RawExternalItemFnCtx -export const ReadonlyResourceData = __napiModule.exports.ReadonlyResourceData -export const ResolverFactory = __napiModule.exports.ResolverFactory -export const Sources = __napiModule.exports.Sources -export const VirtualFileStore = __napiModule.exports.VirtualFileStore -export const JsVirtualFileStore = __napiModule.exports.JsVirtualFileStore -export const async = __napiModule.exports.async -export const BuiltinPluginName = __napiModule.exports.BuiltinPluginName -export const cleanupGlobalTrace = __napiModule.exports.cleanupGlobalTrace -export const EnforceExtension = __napiModule.exports.EnforceExtension -export const EXPECTED_RSPACK_CORE_VERSION = __napiModule.exports.EXPECTED_RSPACK_CORE_VERSION -export const formatDiagnostic = __napiModule.exports.formatDiagnostic -export const JsLoaderState = __napiModule.exports.JsLoaderState -export const JsRspackSeverity = __napiModule.exports.JsRspackSeverity -export const loadBrowserslist = __napiModule.exports.loadBrowserslist -export const minify = __napiModule.exports.minify -export const minifySync = __napiModule.exports.minifySync -export const RawJavascriptParserCommonjsExports = __napiModule.exports.RawJavascriptParserCommonjsExports -export const RawRuleSetConditionType = __napiModule.exports.RawRuleSetConditionType -export const registerGlobalTrace = __napiModule.exports.registerGlobalTrace -export const RegisterJsTapKind = __napiModule.exports.RegisterJsTapKind -export const sync = __napiModule.exports.sync -export const syncTraceEvent = __napiModule.exports.syncTraceEvent -export const transform = __napiModule.exports.transform -export const transformSync = __napiModule.exports.transformSync + diff --git a/crates/node_binding/rspack.wasi.cjs b/crates/node_binding/rspack.wasi.cjs index a251ce4d0d7d..1ad96db4aac4 100644 --- a/crates/node_binding/rspack.wasi.cjs +++ b/crates/node_binding/rspack.wasi.cjs @@ -108,63 +108,4 @@ const { instance: __napiInstance, module: __wasiModule, napiModule: __napiModule }, }) module.exports = __napiModule.exports -module.exports.Assets = __napiModule.exports.Assets -module.exports.AsyncDependenciesBlock = __napiModule.exports.AsyncDependenciesBlock -module.exports.Chunk = __napiModule.exports.Chunk -module.exports.ChunkGraph = __napiModule.exports.ChunkGraph -module.exports.ChunkGroup = __napiModule.exports.ChunkGroup -module.exports.Chunks = __napiModule.exports.Chunks -module.exports.CodeGenerationResult = __napiModule.exports.CodeGenerationResult -module.exports.CodeGenerationResults = __napiModule.exports.CodeGenerationResults -module.exports.ConcatenatedModule = __napiModule.exports.ConcatenatedModule -module.exports.ContextModule = __napiModule.exports.ContextModule -module.exports.Dependency = __napiModule.exports.Dependency -module.exports.Diagnostics = __napiModule.exports.Diagnostics -module.exports.EntryDataDto = __napiModule.exports.EntryDataDto -module.exports.EntryDataDTO = __napiModule.exports.EntryDataDTO -module.exports.EntryDependency = __napiModule.exports.EntryDependency -module.exports.EntryOptionsDto = __napiModule.exports.EntryOptionsDto -module.exports.EntryOptionsDTO = __napiModule.exports.EntryOptionsDTO -module.exports.ExternalModule = __napiModule.exports.ExternalModule -module.exports.JsCompilation = __napiModule.exports.JsCompilation -module.exports.JsCompiler = __napiModule.exports.JsCompiler -module.exports.JsContextModuleFactoryAfterResolveData = __napiModule.exports.JsContextModuleFactoryAfterResolveData -module.exports.JsContextModuleFactoryBeforeResolveData = __napiModule.exports.JsContextModuleFactoryBeforeResolveData -module.exports.JsDependencies = __napiModule.exports.JsDependencies -module.exports.JsEntries = __napiModule.exports.JsEntries -module.exports.JsExportsInfo = __napiModule.exports.JsExportsInfo -module.exports.JsModuleGraph = __napiModule.exports.JsModuleGraph -module.exports.JsResolver = __napiModule.exports.JsResolver -module.exports.JsResolverFactory = __napiModule.exports.JsResolverFactory -module.exports.JsStats = __napiModule.exports.JsStats -module.exports.KnownBuildInfo = __napiModule.exports.KnownBuildInfo -module.exports.Module = __napiModule.exports.Module -module.exports.ModuleGraphConnection = __napiModule.exports.ModuleGraphConnection -module.exports.NativeWatcher = __napiModule.exports.NativeWatcher -module.exports.NativeWatchResult = __napiModule.exports.NativeWatchResult -module.exports.NormalModule = __napiModule.exports.NormalModule -module.exports.RawExternalItemFnCtx = __napiModule.exports.RawExternalItemFnCtx -module.exports.ReadonlyResourceData = __napiModule.exports.ReadonlyResourceData -module.exports.ResolverFactory = __napiModule.exports.ResolverFactory -module.exports.Sources = __napiModule.exports.Sources -module.exports.VirtualFileStore = __napiModule.exports.VirtualFileStore -module.exports.JsVirtualFileStore = __napiModule.exports.JsVirtualFileStore -module.exports.async = __napiModule.exports.async -module.exports.BuiltinPluginName = __napiModule.exports.BuiltinPluginName -module.exports.cleanupGlobalTrace = __napiModule.exports.cleanupGlobalTrace -module.exports.EnforceExtension = __napiModule.exports.EnforceExtension -module.exports.EXPECTED_RSPACK_CORE_VERSION = __napiModule.exports.EXPECTED_RSPACK_CORE_VERSION -module.exports.formatDiagnostic = __napiModule.exports.formatDiagnostic -module.exports.JsLoaderState = __napiModule.exports.JsLoaderState -module.exports.JsRspackSeverity = __napiModule.exports.JsRspackSeverity -module.exports.loadBrowserslist = __napiModule.exports.loadBrowserslist -module.exports.minify = __napiModule.exports.minify -module.exports.minifySync = __napiModule.exports.minifySync -module.exports.RawJavascriptParserCommonjsExports = __napiModule.exports.RawJavascriptParserCommonjsExports -module.exports.RawRuleSetConditionType = __napiModule.exports.RawRuleSetConditionType -module.exports.registerGlobalTrace = __napiModule.exports.registerGlobalTrace -module.exports.RegisterJsTapKind = __napiModule.exports.RegisterJsTapKind -module.exports.sync = __napiModule.exports.sync -module.exports.syncTraceEvent = __napiModule.exports.syncTraceEvent -module.exports.transform = __napiModule.exports.transform -module.exports.transformSync = __napiModule.exports.transformSync + diff --git a/crates/rspack_binding_api/src/raw_options/raw_builtins/raw_mf.rs b/crates/rspack_binding_api/src/raw_options/raw_builtins/raw_mf.rs index 84e4d6fc774d..292a195bcac7 100644 --- a/crates/rspack_binding_api/src/raw_options/raw_builtins/raw_mf.rs +++ b/crates/rspack_binding_api/src/raw_options/raw_builtins/raw_mf.rs @@ -116,7 +116,7 @@ pub struct RawProvideOptions { #[napi(ts_type = "string | false | undefined")] pub required_version: Option, pub strict_version: Option, - pub treeshake_strategy: Option, + pub tree_shaking_mode: Option, } impl From for (String, ProvideOptions) { @@ -131,7 +131,7 @@ impl From for (String, ProvideOptions) { singleton: value.singleton, required_version: value.required_version.map(|v| RawVersionWrapper(v).into()), strict_version: value.strict_version, - treeshake_strategy: value.treeshake_strategy, + tree_shaking_mode: value.tree_shaking_mode, }, ) } @@ -207,7 +207,7 @@ impl From for ConsumeSharedPluginOptions { #[napi(object)] pub struct RawOptimizeSharedConfig { pub share_key: String, - pub treeshake: bool, + pub tree_shaking: bool, pub used_exports: Option>, } @@ -215,7 +215,7 @@ impl From for OptimizeSharedConfig { fn from(value: RawOptimizeSharedConfig) -> Self { Self { share_key: value.share_key, - treeshake: value.treeshake, + tree_shaking: value.tree_shaking, used_exports: value.used_exports.unwrap_or_default(), } } @@ -225,7 +225,7 @@ impl From for OptimizeSharedConfig { #[napi(object)] pub struct RawSharedUsedExportsOptimizerPluginOptions { pub shared: Vec, - pub inject_used_exports: Option, + pub inject_tree_shaking_used_exports: Option, pub manifest_file_name: Option, pub stats_file_name: Option, } @@ -238,7 +238,7 @@ impl From for SharedUsedExportsOptim .into_iter() .map(|config| config.into()) .collect(), - inject_used_exports: value.inject_used_exports.unwrap_or(true), + inject_tree_shaking_used_exports: value.inject_tree_shaking_used_exports.unwrap_or(true), manifest_file_name: value .manifest_file_name .and_then(|s| if s.trim().is_empty() { None } else { Some(s) }), @@ -263,7 +263,7 @@ pub struct RawConsumeOptions { pub strict_version: bool, pub singleton: bool, pub eager: bool, - pub treeshake_strategy: Option, + pub tree_shaking_mode: Option, } impl From for (String, ConsumeOptions) { @@ -280,7 +280,7 @@ impl From for (String, ConsumeOptions) { strict_version: value.strict_version, singleton: value.singleton, eager: value.eager, - treeshake_strategy: value.treeshake_strategy, + tree_shaking_mode: value.tree_shaking_mode, }, ) } @@ -351,7 +351,7 @@ pub struct RawManifestSharedOption { pub struct RawStatsBuildInfo { pub build_version: String, pub build_name: Option, - // only appear when enable treeshake + // only appear when enable tree_shaking pub target: Option>, pub plugins: Option>, } diff --git a/crates/rspack_plugin_mf/src/sharing/consume_shared_module.rs b/crates/rspack_plugin_mf/src/sharing/consume_shared_module.rs index 5dfab6b123b4..18c05bfd0cbc 100644 --- a/crates/rspack_plugin_mf/src/sharing/consume_shared_module.rs +++ b/crates/rspack_plugin_mf/src/sharing/consume_shared_module.rs @@ -236,7 +236,7 @@ impl Module for ConsumeSharedModule { singleton: self.options.singleton, eager: self.options.eager, fallback: factory, - treeshake_strategy: self.options.treeshake_strategy.clone(), + tree_shaking_mode: self.options.tree_shaking_mode.clone(), }); Ok(code_generation_result) } diff --git a/crates/rspack_plugin_mf/src/sharing/consume_shared_plugin.rs b/crates/rspack_plugin_mf/src/sharing/consume_shared_plugin.rs index cf6f61a6cca8..63873f5b7981 100644 --- a/crates/rspack_plugin_mf/src/sharing/consume_shared_plugin.rs +++ b/crates/rspack_plugin_mf/src/sharing/consume_shared_plugin.rs @@ -36,7 +36,7 @@ pub struct ConsumeOptions { pub strict_version: bool, pub singleton: bool, pub eager: bool, - pub treeshake_strategy: Option, + pub tree_shaking_mode: Option, } #[cacheable] @@ -369,7 +369,7 @@ impl ConsumeSharedPlugin { strict_version: config.strict_version, singleton: config.singleton, eager: config.eager, - treeshake_strategy: config.treeshake_strategy.clone(), + tree_shaking_mode: config.tree_shaking_mode.clone(), }, ) } @@ -440,7 +440,7 @@ async fn factorize(&self, data: &mut ModuleFactoryCreateData) -> Result() { module_id_to_consume_data_mapping.insert(id, format!( - "{{ shareScope: {}, shareKey: {}, import: {}, requiredVersion: {}, strictVersion: {}, singleton: {}, eager: {}, fallback: {}, treeshakeStrategy: {} }}", + "{{ shareScope: {}, shareKey: {}, import: {}, requiredVersion: {}, strictVersion: {}, singleton: {}, eager: {}, fallback: {}, treeShakingMode: {} }}", json_stringify(&data.share_scope), json_stringify(&data.share_key), json_stringify(&data.import), @@ -98,7 +98,7 @@ impl RuntimeModule for ConsumeSharedRuntimeModule { json_stringify(&data.singleton), json_stringify(&data.eager), data.fallback.as_deref().unwrap_or("undefined"), - json_stringify(&data.treeshake_strategy), + json_stringify(&data.tree_shaking_mode), )); } }; @@ -219,5 +219,5 @@ pub struct CodeGenerationDataConsumeShared { pub singleton: bool, pub eager: bool, pub fallback: Option, - pub treeshake_strategy: Option, + pub tree_shaking_mode: Option, } diff --git a/crates/rspack_plugin_mf/src/sharing/provide_shared_dependency.rs b/crates/rspack_plugin_mf/src/sharing/provide_shared_dependency.rs index 902201d11d98..b11ae5324644 100644 --- a/crates/rspack_plugin_mf/src/sharing/provide_shared_dependency.rs +++ b/crates/rspack_plugin_mf/src/sharing/provide_shared_dependency.rs @@ -19,7 +19,7 @@ pub struct ProvideSharedDependency { pub singleton: Option, pub required_version: Option, pub strict_version: Option, - pub treeshake_strategy: Option, + pub tree_shaking_mode: Option, resource_identifier: ResourceIdentifier, factorize_info: FactorizeInfo, } @@ -35,7 +35,7 @@ impl ProvideSharedDependency { singleton: Option, required_version: Option, strict_version: Option, - treeshake_strategy: Option, + tree_shaking_mode: Option, ) -> Self { let resource_identifier = format!( "provide module ({}) {} as {} @ {} {}", @@ -56,7 +56,7 @@ impl ProvideSharedDependency { singleton, required_version, strict_version, - treeshake_strategy, + tree_shaking_mode, resource_identifier, factorize_info: Default::default(), } diff --git a/crates/rspack_plugin_mf/src/sharing/provide_shared_module.rs b/crates/rspack_plugin_mf/src/sharing/provide_shared_module.rs index bdf8e33c6c06..3210a3d020b2 100644 --- a/crates/rspack_plugin_mf/src/sharing/provide_shared_module.rs +++ b/crates/rspack_plugin_mf/src/sharing/provide_shared_module.rs @@ -40,7 +40,7 @@ pub struct ProvideSharedModule { singleton: Option, required_version: Option, strict_version: Option, - treeshake_strategy: Option, + tree_shaking_mode: Option, factory_meta: Option, build_info: BuildInfo, build_meta: BuildMeta, @@ -57,7 +57,7 @@ impl ProvideSharedModule { singleton: Option, required_version: Option, strict_version: Option, - treeshake_strategy: Option, + tree_shaking_mode: Option, ) -> Self { let identifier = format!( "provide shared module ({}) {}@{} = {}", @@ -77,7 +77,7 @@ impl ProvideSharedModule { singleton, required_version, strict_version, - treeshake_strategy, + tree_shaking_mode, factory_meta: None, build_info: BuildInfo { strict: true, @@ -212,7 +212,7 @@ impl Module for ProvideSharedModule { singleton: self.singleton, strict_version: self.strict_version, required_version: self.required_version.clone(), - treeshake_strategy: self.treeshake_strategy.clone(), + tree_shaking_mode: self.tree_shaking_mode.clone(), }), }], }); diff --git a/crates/rspack_plugin_mf/src/sharing/provide_shared_module_factory.rs b/crates/rspack_plugin_mf/src/sharing/provide_shared_module_factory.rs index 17475237bd17..990f37787363 100644 --- a/crates/rspack_plugin_mf/src/sharing/provide_shared_module_factory.rs +++ b/crates/rspack_plugin_mf/src/sharing/provide_shared_module_factory.rs @@ -31,7 +31,7 @@ impl ModuleFactory for ProvideSharedModuleFactory { dep.singleton, dep.required_version.clone(), dep.strict_version, - dep.treeshake_strategy.clone(), + dep.tree_shaking_mode.clone(), ) .boxed(), )) diff --git a/crates/rspack_plugin_mf/src/sharing/provide_shared_plugin.rs b/crates/rspack_plugin_mf/src/sharing/provide_shared_plugin.rs index 1b20fa0753e3..f233cfdcb61d 100644 --- a/crates/rspack_plugin_mf/src/sharing/provide_shared_plugin.rs +++ b/crates/rspack_plugin_mf/src/sharing/provide_shared_plugin.rs @@ -35,7 +35,7 @@ pub struct ProvideOptions { pub singleton: Option, pub required_version: Option, pub strict_version: Option, - pub treeshake_strategy: Option, + pub tree_shaking_mode: Option, } #[derive(Debug, Clone)] @@ -47,7 +47,7 @@ pub struct VersionedProvideOptions { pub singleton: Option, pub required_version: Option, pub strict_version: Option, - pub treeshake_strategy: Option, + pub tree_shaking_mode: Option, } impl ProvideOptions { @@ -60,7 +60,7 @@ impl ProvideOptions { singleton: self.singleton, required_version: self.required_version.clone(), strict_version: self.strict_version, - treeshake_strategy: self.treeshake_strategy.clone(), + tree_shaking_mode: self.tree_shaking_mode.clone(), } } } @@ -112,7 +112,7 @@ impl ProvideSharedPlugin { singleton: Option, required_version: Option, strict_version: Option, - treeshake_strategy: Option, + tree_shaking_mode: Option, resource: &str, resource_data: &ResourceData, mut add_diagnostic: impl FnMut(Diagnostic), @@ -130,7 +130,7 @@ impl ProvideSharedPlugin { singleton, strict_version, required_version, - treeshake_strategy: treeshake_strategy.clone(), + tree_shaking_mode: tree_shaking_mode.clone(), }, ); } else if let Some(description) = resource_data.description() { @@ -148,7 +148,7 @@ impl ProvideSharedPlugin { singleton, strict_version, required_version, - treeshake_strategy: treeshake_strategy.clone(), + tree_shaking_mode: tree_shaking_mode.clone(), }, ); } else { @@ -219,7 +219,7 @@ async fn finish_make(&self, compilation: &mut Compilation) -> Result<()> { config.singleton, config.required_version.clone(), config.strict_version, - config.treeshake_strategy.clone(), + config.tree_shaking_mode.clone(), )) as BoxDependency, EntryOptions { name: None, @@ -263,7 +263,7 @@ async fn normal_module_factory_module( config.singleton, config.required_version.clone(), config.strict_version, - config.treeshake_strategy.clone(), + config.tree_shaking_mode.clone(), resource, resource_data, |d| data.diagnostics.push(d), @@ -284,7 +284,7 @@ async fn normal_module_factory_module( config.singleton, config.required_version.clone(), config.strict_version, - config.treeshake_strategy.clone(), + config.tree_shaking_mode.clone(), resource, resource_data, |d| data.diagnostics.push(d), diff --git a/crates/rspack_plugin_mf/src/sharing/share_runtime_module.rs b/crates/rspack_plugin_mf/src/sharing/share_runtime_module.rs index 2a40b328bd92..612f4cd7ec50 100644 --- a/crates/rspack_plugin_mf/src/sharing/share_runtime_module.rs +++ b/crates/rspack_plugin_mf/src/sharing/share_runtime_module.rs @@ -88,12 +88,12 @@ impl RuntimeModule for ShareRuntimeModule { DataInitInfo::ExternalModuleId(Some(id)) => json_stringify(&id), DataInitInfo::ProvideSharedInfo(info) => { let mut stage = format!( - "{{ name: {}, version: {}, factory: {}, eager: {}, treeshakeStrategy: {}", + "{{ name: {}, version: {}, factory: {}, eager: {}, treeShakingMode: {}", json_stringify(&info.name), json_stringify(&info.version.to_string()), info.factory, if info.eager { "1" } else { "0" }, - json_stringify(&info.treeshake_strategy), + json_stringify(&info.tree_shaking_mode), ); if self.enhanced { if let Some(singleton) = info.singleton { @@ -183,5 +183,5 @@ pub struct ProvideSharedInfo { pub singleton: Option, pub required_version: Option, pub strict_version: Option, - pub treeshake_strategy: Option, + pub tree_shaking_mode: Option, } diff --git a/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_plugin.rs b/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_plugin.rs index 1c8992af3f89..d9a1dfd067d3 100644 --- a/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_plugin.rs +++ b/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_plugin.rs @@ -25,14 +25,14 @@ use crate::manifest::StatsRoot; #[derive(Debug, Clone)] pub struct OptimizeSharedConfig { pub share_key: String, - pub treeshake: bool, + pub tree_shaking: bool, pub used_exports: Vec, } #[derive(Debug, Clone)] pub struct SharedUsedExportsOptimizerPluginOptions { pub shared: Vec, - pub inject_used_exports: bool, + pub inject_tree_shaking_used_exports: bool, pub stats_file_name: Option, pub manifest_file_name: Option, } @@ -47,7 +47,7 @@ struct SharedEntryData { pub struct SharedUsedExportsOptimizerPlugin { shared_map: FxHashMap, shared_referenced_exports: Arc>>>, - inject_used_exports: bool, + inject_tree_shaking_used_exports: bool, stats_file_name: Option, manifest_file_name: Option, } @@ -55,8 +55,8 @@ pub struct SharedUsedExportsOptimizerPlugin { impl SharedUsedExportsOptimizerPlugin { pub fn new(options: SharedUsedExportsOptimizerPluginOptions) -> Self { let mut shared_map = FxHashMap::default(); - let inject_used_exports = options.inject_used_exports; - for config in options.shared.into_iter().filter(|c| c.treeshake) { + let inject_tree_shaking_used_exports = options.inject_tree_shaking_used_exports; + for config in options.shared.into_iter().filter(|c| c.tree_shaking) { let atoms = config .used_exports .into_iter() @@ -77,7 +77,7 @@ impl SharedUsedExportsOptimizerPlugin { Self::new_inner( shared_map, shared_referenced_exports, - inject_used_exports, + inject_tree_shaking_used_exports, options.stats_file_name, options.manifest_file_name, ) @@ -244,7 +244,7 @@ async fn optimize_dependencies( .get(&share_key) .cloned() }; - // Check if this share key is in our shared map and has treeshake enabled + // Check if this share key is in our shared map and has tree_shaking enabled if !self.shared_map.contains_key(&share_key) { continue; } @@ -526,7 +526,7 @@ impl Plugin for SharedUsedExportsOptimizerPlugin { .compilation_hooks .process_assets .tap(process_assets::new(self)); - if self.inject_used_exports { + if self.inject_tree_shaking_used_exports { ctx .compilation_hooks .additional_tree_runtime_requirements diff --git a/packages/rspack/etc/core.api.md b/packages/rspack/etc/core.api.md index ebab0844849f..047c36132e46 100644 --- a/packages/rspack/etc/core.api.md +++ b/packages/rspack/etc/core.api.md @@ -1372,7 +1372,7 @@ export type ConsumesConfig = { shareScope?: string; singleton?: boolean; strictVersion?: boolean; - treeshakeStrategy?: 'server' | 'infer'; + treeShakingMode?: 'server-calc' | 'runtime-infer'; }; // @public (undocumented) @@ -1391,7 +1391,7 @@ class ConsumeSharedPlugin extends RspackBuiltinPlugin { packageName: string | undefined; singleton: boolean; eager: boolean; - treeshakeStrategy: "server" | "infer" | undefined; + treeShakingMode: "server-calc" | "runtime-infer" | undefined; }][]; enhanced: boolean; }; @@ -4890,7 +4890,7 @@ export interface ModuleFederationPluginOptions extends Omit config[1].treeshake, + const enableTreeShaking = Object.values(normalizedShared).some( + (config) => config[1].treeShaking, ); - if (enableTreeshake) { + if (enableTreeShaking) { statsBuildInfo.target = Array.isArray(compiler.options.target) ? compiler.options.target : []; - statsBuildInfo.plugins = mfConfig.treeshakeSharedPlugins || []; + statsBuildInfo.plugins = mfConfig.treeShakingSharedPlugins || []; statsBuildInfo.excludePlugins = - mfConfig.treeshakeSharedExcludePlugins || []; + mfConfig.treeShakingSharedExcludePlugins || []; } return statsBuildInfo; @@ -101,7 +101,7 @@ function getBuildInfo( interface StatsBuildInfo { buildVersion: string; buildName?: string; - // only appear when enable treeshake + // only appear when enable tree shaking target?: string[]; excludePlugins?: string[]; plugins?: string[]; diff --git a/packages/rspack/src/container/ModuleFederationPlugin.ts b/packages/rspack/src/container/ModuleFederationPlugin.ts index 9b6dc4772a52..be65f001fed6 100644 --- a/packages/rspack/src/container/ModuleFederationPlugin.ts +++ b/packages/rspack/src/container/ModuleFederationPlugin.ts @@ -2,7 +2,7 @@ import type { Compiler } from '../Compiler'; import type { ExternalsType } from '../config'; import type { ShareFallback } from '../sharing/IndependentSharedPlugin'; import type { SharedConfig } from '../sharing/SharePlugin'; -import { TreeShakeSharedPlugin } from '../sharing/TreeShakeSharedPlugin'; +import { TreeShakingSharedPlugin } from '../sharing/TreeShakingSharedPlugin'; import { isRequiredVersion } from '../sharing/utils'; import { ModuleFederationManifestPlugin, @@ -22,15 +22,15 @@ export interface ModuleFederationPluginOptions extends Omit< implementation?: string; shareStrategy?: 'version-first' | 'loaded-first'; manifest?: ModuleFederationManifestPluginOptions; - injectUsedExports?: boolean; - treeshakeSharedDir?: string; - treeshakeSharedExcludePlugins?: string[]; - treeshakeSharedPlugins?: string[]; + injectTreeShakingUsedExports?: boolean; + treeShakingSharedDir?: string; + treeShakingSharedExcludePlugins?: string[]; + treeShakingSharedPlugins?: string[]; } export type RuntimePlugins = string[] | [string, Record][]; export class ModuleFederationPlugin { - private _treeShakeSharedPlugin?: TreeShakeSharedPlugin; + private _treeShakingSharedPlugin?: TreeShakingSharedPlugin; constructor(private _options: ModuleFederationPluginOptions) {} @@ -44,18 +44,18 @@ export class ModuleFederationPlugin { }; const sharedOptions = getSharedOptions(this._options); - const treeshakeEntries = sharedOptions.filter( - ([, config]) => config.treeshake, + const treeShakingEntries = sharedOptions.filter( + ([, config]) => config.treeShaking, ); - if (treeshakeEntries.length > 0) { - this._treeShakeSharedPlugin = new TreeShakeSharedPlugin({ + if (treeShakingEntries.length > 0) { + this._treeShakingSharedPlugin = new TreeShakingSharedPlugin({ mfConfig: this._options, reShake: false, }); - this._treeShakeSharedPlugin.apply(compiler); + this._treeShakingSharedPlugin.apply(compiler); } - // need to wait treeShakeSharedPlugin buildAssets + // need to wait treeShakingSharedPlugin buildAssets let runtimePluginApplied = false; compiler.hooks.beforeRun.tapPromise( { @@ -69,7 +69,7 @@ export class ModuleFederationPlugin { paths, this._options, compiler, - this._treeShakeSharedPlugin?.buildAssets || {}, + this._treeShakingSharedPlugin?.buildAssets, ); new ModuleFederationRuntimePlugin({ entryRuntime, @@ -88,7 +88,7 @@ export class ModuleFederationPlugin { paths, this._options, compiler, - this._treeShakeSharedPlugin?.buildAssets || {}, + this._treeShakingSharedPlugin?.buildAssets || {}, ); new ModuleFederationRuntimePlugin({ entryRuntime, @@ -256,7 +256,7 @@ function getDefaultEntryRuntime( paths: RuntimePaths, options: ModuleFederationPluginOptions, compiler: Compiler, - treeshakeShareFallbacks: ShareFallback, + treeShakingShareFallbacks?: ShareFallback, ) { const runtimePlugins = getRuntimePlugins(options); const remoteInfos = getRemoteInfos(options); @@ -293,7 +293,7 @@ function getDefaultEntryRuntime( options.shareStrategy ?? 'version-first', )}`, `const __module_federation_share_fallbacks__ = ${JSON.stringify( - treeshakeShareFallbacks, + treeShakingShareFallbacks, )}`, `const __module_federation_library_type__ = ${JSON.stringify(libraryType)}`, IS_BROWSER diff --git a/packages/rspack/src/exports.ts b/packages/rspack/src/exports.ts index dbb30fbd8cba..d65aa0db59e0 100644 --- a/packages/rspack/src/exports.ts +++ b/packages/rspack/src/exports.ts @@ -278,7 +278,7 @@ export const container = { import { ConsumeSharedPlugin } from './sharing/ConsumeSharedPlugin'; import { ProvideSharedPlugin } from './sharing/ProvideSharedPlugin'; import { SharePlugin } from './sharing/SharePlugin'; -import { TreeShakeSharedPlugin } from './sharing/TreeShakeSharedPlugin'; +import { TreeShakingSharedPlugin } from './sharing/TreeShakingSharedPlugin'; export type { ConsumeSharedPluginOptions, @@ -301,10 +301,10 @@ export type { SharedObject, SharePluginOptions, } from './sharing/SharePlugin'; -export type { TreeshakeSharedPluginOptions } from './sharing/TreeShakeSharedPlugin'; +export type { TreeshakingSharedPluginOptions } from './sharing/TreeShakingSharedPlugin'; export const sharing = { ProvideSharedPlugin, - TreeShakeSharedPlugin, + TreeShakingSharedPlugin, ConsumeSharedPlugin, SharePlugin, }; diff --git a/packages/rspack/src/runtime/moduleFederationDefaultRuntime.js b/packages/rspack/src/runtime/moduleFederationDefaultRuntime.js index 8a3a5417688b..cd3ac4cf8f81 100644 --- a/packages/rspack/src/runtime/moduleFederationDefaultRuntime.js +++ b/packages/rspack/src/runtime/moduleFederationDefaultRuntime.js @@ -83,7 +83,7 @@ module.exports = function () { }, ) : data.fallback, - treeshakeGetter: sharedFallback ? data.fallback : undefined, + treeShakingGetter: sharedFallback ? data.fallback : undefined, shareInfo: { shareConfig: { fixedDependencies: false, @@ -95,10 +95,10 @@ module.exports = function () { scope: [data.shareScope], }, shareKey: data.shareKey, - treeshake: __webpack_require__.federation.sharedFallback + treeShaking: __webpack_require__.federation.sharedFallback ? { get: data.fallback, - strategy: data.treeshakeStrategy, + mode: data.treeShakingMode, } : undefined, }; @@ -133,7 +133,7 @@ module.exports = function () { singleton, requiredVersion, strictVersion, - treeshakeStrategy, + treeShakingMode, } = stage; const shareConfig = {}; const isValidValue = function (val) { @@ -156,9 +156,9 @@ module.exports = function () { scope: [scope], shareConfig, get: factory, - treeshake: treeshakeStrategy + treeShaking: treeShakingMode ? { - strategy: treeshakeStrategy, + mode: treeShakingMode, } : undefined, }; diff --git a/packages/rspack/src/sharing/ConsumeSharedPlugin.ts b/packages/rspack/src/sharing/ConsumeSharedPlugin.ts index 1f37966f93e1..ed92eeeda526 100644 --- a/packages/rspack/src/sharing/ConsumeSharedPlugin.ts +++ b/packages/rspack/src/sharing/ConsumeSharedPlugin.ts @@ -31,10 +31,7 @@ export type ConsumesConfig = { shareScope?: string; singleton?: boolean; strictVersion?: boolean; - /** - * Tree shaking strategy for the shared module. - */ - treeshakeStrategy?: 'server' | 'infer'; + treeShakingMode?: 'server-calc' | 'runtime-infer'; }; export function normalizeConsumeShareOptions( @@ -57,7 +54,7 @@ export function normalizeConsumeShareOptions( strictVersion: false, singleton: false, eager: false, - treeshakeStrategy: undefined, + treeShakingMode: undefined, } : // key is a request/key // item is a version @@ -70,7 +67,7 @@ export function normalizeConsumeShareOptions( packageName: undefined, singleton: false, eager: false, - treeshakeStrategy: undefined, + treeShakingMode: undefined, }; return result; }, @@ -86,7 +83,7 @@ export function normalizeConsumeShareOptions( packageName: item.packageName, singleton: !!item.singleton, eager: !!item.eager, - treeshakeStrategy: item.treeshakeStrategy, + treeShakingMode: item.treeShakingMode, }), ); } diff --git a/packages/rspack/src/sharing/IndependentSharedPlugin.ts b/packages/rspack/src/sharing/IndependentSharedPlugin.ts index 38a24cbc03a0..f6d33d124b85 100644 --- a/packages/rspack/src/sharing/IndependentSharedPlugin.ts +++ b/packages/rspack/src/sharing/IndependentSharedPlugin.ts @@ -35,7 +35,7 @@ const filterPlugin = (plugin: Plugins[0], excludedPlugins: string[] = []) => { return true; } return ![ - 'TreeShakeSharedPlugin', + 'TreeShakingSharedPlugin', 'IndependentSharedPlugin', 'ModuleFederationPlugin', 'SharedUsedExportsOptimizerPlugin', @@ -52,10 +52,10 @@ export interface IndependentSharePluginOptions { library?: LibraryOptions; outputDir?: string; plugins?: Plugins; - treeshake?: boolean; + treeShaking?: boolean; manifest?: ModuleFederationManifestPluginOptions; - injectUsedExports?: boolean; - treeshakeSharedExcludePlugins?: string[]; + injectTreeShakingUsedExports?: boolean; + treeShakingSharedExcludePlugins?: string[]; } // { react: [ [ react/19.0.0/index.js , 19.0.0, react_global_name ] ] } @@ -127,34 +127,35 @@ export class IndependentSharedPlugin { sharedOptions: [string, SharedConfig][]; outputDir: string; plugins: Plugins; - treeshake?: boolean; + treeShaking?: boolean; manifest?: ModuleFederationManifestPluginOptions; buildAssets: ShareFallback = {}; - injectUsedExports?: boolean; - treeshakeSharedExcludePlugins?: string[]; + injectTreeShakingUsedExports?: boolean; + treeShakingSharedExcludePlugins?: string[]; name = 'IndependentSharedPlugin'; constructor(options: IndependentSharePluginOptions) { const { outputDir, plugins, - treeshake, + treeShaking, shared, name, manifest, - injectUsedExports, + injectTreeShakingUsedExports, library, - treeshakeSharedExcludePlugins, + treeShakingSharedExcludePlugins, } = options; this.shared = shared; this.mfName = name; this.outputDir = outputDir || 'independent-packages'; this.plugins = plugins || []; - this.treeshake = treeshake; + this.treeShaking = treeShaking; this.manifest = manifest; - this.injectUsedExports = injectUsedExports ?? true; + this.injectTreeShakingUsedExports = injectTreeShakingUsedExports ?? true; this.library = library; - this.treeshakeSharedExcludePlugins = treeshakeSharedExcludePlugins || []; + this.treeShakingSharedExcludePlugins = + treeShakingSharedExcludePlugins || []; this.sharedOptions = parseOptions( shared, (item, key) => { @@ -269,7 +270,7 @@ export class IndependentSharedPlugin { private async createIndependentCompilers(parentCompiler: Compiler) { const { sharedOptions, buildAssets, outputDir } = this; - console.log('🚀 Start creating a standalone compiler...'); + console.log('Start building shared fallback resources ...'); // collect share requests for each shareName and then build share container const shareRequestsMap: ShareRequestsMap = @@ -277,7 +278,7 @@ export class IndependentSharedPlugin { await Promise.all( sharedOptions.map(async ([shareName, shareConfig]) => { - if (!shareConfig.treeshake || shareConfig.import === false) { + if (!shareConfig.treeShaking || shareConfig.import === false) { return; } const shareRequests = shareRequestsMap[shareName].requests; @@ -293,7 +294,7 @@ export class IndependentSharedPlugin { shareName, version, request, - independentShareFileName: sharedConfig?.treeshake?.filename, + independentShareFileName: sharedConfig?.treeShaking?.filename, }, }); if (typeof shareFileName === 'string') { @@ -309,7 +310,7 @@ export class IndependentSharedPlugin { }), ); - console.log('✅ All independent packages have been compiled successfully'); + console.log('All shared fallback have been compiled successfully!'); } private async createIndependentCompiler( @@ -324,9 +325,9 @@ export class IndependentSharedPlugin { plugins, outputDir, sharedOptions, - treeshake, + treeShaking, library, - treeshakeSharedExcludePlugins, + treeShakingSharedExcludePlugins, } = this; const outputDirWithShareName = resolveOutputDir( @@ -354,7 +355,7 @@ export class IndependentSharedPlugin { if ( plugin !== undefined && typeof plugin !== 'string' && - filterPlugin(plugin, treeshakeSharedExcludePlugins) + filterPlugin(plugin, treeShakingSharedExcludePlugins) ) { finalPlugins.push(plugin); } @@ -388,11 +389,11 @@ export class IndependentSharedPlugin { }), ); - if (treeshake) { + if (treeShaking) { finalPlugins.push( new SharedUsedExportsOptimizerPlugin( sharedOptions, - this.injectUsedExports, + this.injectTreeShakingUsedExports, ), ); } @@ -451,33 +452,21 @@ export class IndependentSharedPlugin { return new Promise((resolve, reject) => { compiler.run((err: any, stats: any) => { if (err || stats?.hasErrors()) { - const target = currentShare ? currentShare.shareName : '收集依赖'; + const target = currentShare ? currentShare.shareName : 'Collect deps'; console.error( - `❌ ${target} 编译失败:`, + `${target} Compile failed:`, err || stats .toJson() .errors.map((e: Error) => e.message) .join('\n'), ); - reject(err || new Error(`${target} 编译失败`)); + reject(err || new Error(`${target} Compile failed`)); return; } currentShare && - console.log(`✅ 独立包 ${currentShare.shareName} 编译成功`); - - if (stats) { - currentShare && console.log(`📊 ${currentShare.shareName} 编译统计:`); - console.log( - stats.toString({ - colors: true, - chunks: false, - modules: false, - }), - ); - } - + console.log(`${currentShare.shareName} Compile success`); resolve(extraPlugin.getData()); }); }); diff --git a/packages/rspack/src/sharing/ProvideSharedPlugin.ts b/packages/rspack/src/sharing/ProvideSharedPlugin.ts index 4572809291e0..73d9ebb17831 100644 --- a/packages/rspack/src/sharing/ProvideSharedPlugin.ts +++ b/packages/rspack/src/sharing/ProvideSharedPlugin.ts @@ -40,7 +40,7 @@ type ProvidesEnhancedExtraConfig = { /** * Tree shaking strategy for the shared module. */ - treeshakeStrategy?: 'server' | 'infer'; + treeShakingMode?: 'server-calc' | 'runtime-infer'; }; export function normalizeProvideShareOptions( @@ -73,7 +73,7 @@ export function normalizeProvideShareOptions( singleton: enhancedItem.singleton, requiredVersion: enhancedItem.requiredVersion, strictVersion: enhancedItem.strictVersion, - treeshakeStrategy: enhancedItem.treeshakeStrategy, + treeShakingMode: enhancedItem.treeShakingMode, }; } return raw; diff --git a/packages/rspack/src/sharing/SharePlugin.ts b/packages/rspack/src/sharing/SharePlugin.ts index c62974decded..116b44570011 100644 --- a/packages/rspack/src/sharing/SharePlugin.ts +++ b/packages/rspack/src/sharing/SharePlugin.ts @@ -14,9 +14,9 @@ export type SharedItem = string; export type SharedObject = { [k: string]: SharedConfig | SharedItem; }; -export type TreeshakeConfig = { +export type TreeShakingConfig = { usedExports?: string[]; - strategy?: 'server' | 'infer'; + mode?: 'server-calc' | 'runtime-infer'; filename?: string; }; @@ -30,7 +30,7 @@ export type SharedConfig = { singleton?: boolean; strictVersion?: boolean; version?: false | string; - treeshake?: TreeshakeConfig; + treeShaking?: TreeShakingConfig; }; export type NormalizedSharedOptions = [string, SharedConfig][]; @@ -72,7 +72,7 @@ export function createProvideShareOptions( singleton: options.singleton, requiredVersion: options.requiredVersion, strictVersion: options.strictVersion, - treeshakeStrategy: options.treeshake?.strategy, + treeShakingMode: options.treeShaking?.mode, }, })); } @@ -90,7 +90,7 @@ export function createConsumeShareOptions( singleton: options.singleton, packageName: options.packageName, eager: options.eager, - treeshakeStrategy: options.treeshake?.strategy, + treeShakingMode: options.treeShaking?.mode, }, })); } diff --git a/packages/rspack/src/sharing/SharedUsedExportsOptimizerPlugin.ts b/packages/rspack/src/sharing/SharedUsedExportsOptimizerPlugin.ts index b43d136a92cc..37252d999eb4 100644 --- a/packages/rspack/src/sharing/SharedUsedExportsOptimizerPlugin.ts +++ b/packages/rspack/src/sharing/SharedUsedExportsOptimizerPlugin.ts @@ -16,24 +16,24 @@ import type { NormalizedSharedOptions } from './SharePlugin'; type OptimizeSharedConfig = { shareKey: string; - treeshake: boolean; + treeShaking: boolean; usedExports?: string[]; }; export class SharedUsedExportsOptimizerPlugin extends RspackBuiltinPlugin { name = BuiltinPluginName.SharedUsedExportsOptimizerPlugin; private sharedOptions: NormalizedSharedOptions; - private injectUsedExports: boolean; + private injectTreeShakingUsedExports: boolean; private manifestOptions: ModuleFederationManifestPluginOptions; constructor( sharedOptions: NormalizedSharedOptions, - injectUsedExports?: boolean, + injectTreeShakingUsedExports?: boolean, manifestOptions?: ModuleFederationManifestPluginOptions, ) { super(); this.sharedOptions = sharedOptions; - this.injectUsedExports = injectUsedExports ?? true; + this.injectTreeShakingUsedExports = injectTreeShakingUsedExports ?? true; this.manifestOptions = manifestOptions ?? {}; } @@ -41,8 +41,8 @@ export class SharedUsedExportsOptimizerPlugin extends RspackBuiltinPlugin { const shared: OptimizeSharedConfig[] = this.sharedOptions.map( ([shareKey, config]) => ({ shareKey, - treeshake: !!config.treeshake, - usedExports: config.treeshake?.usedExports, + treeShaking: !!config.treeShaking, + usedExports: config.treeShaking?.usedExports, }), ); const { manifestFileName, statsFileName } = getFileName( @@ -50,7 +50,7 @@ export class SharedUsedExportsOptimizerPlugin extends RspackBuiltinPlugin { ); return { shared, - injectUsedExports: this.injectUsedExports, + injectTreeShakingUsedExports: this.injectTreeShakingUsedExports, manifestFileName, statsFileName, }; diff --git a/packages/rspack/src/sharing/TreeShakeSharedPlugin.ts b/packages/rspack/src/sharing/TreeShakingSharedPlugin.ts similarity index 66% rename from packages/rspack/src/sharing/TreeShakeSharedPlugin.ts rename to packages/rspack/src/sharing/TreeShakingSharedPlugin.ts index b9ffdf9ac05d..d8cce4e89717 100644 --- a/packages/rspack/src/sharing/TreeShakeSharedPlugin.ts +++ b/packages/rspack/src/sharing/TreeShakingSharedPlugin.ts @@ -4,28 +4,28 @@ import { IndependentSharedPlugin } from './IndependentSharedPlugin'; import { SharedUsedExportsOptimizerPlugin } from './SharedUsedExportsOptimizerPlugin'; import { normalizeSharedOptions } from './SharePlugin'; -export interface TreeshakeSharedPluginOptions { +export interface TreeshakingSharedPluginOptions { mfConfig: ModuleFederationPluginOptions; reShake?: boolean; } -export class TreeShakeSharedPlugin { +export class TreeShakingSharedPlugin { mfConfig: ModuleFederationPluginOptions; outputDir: string; reShake?: boolean; private _independentSharePlugin?: IndependentSharedPlugin; - name = 'TreeShakeSharedPlugin'; - constructor(options: TreeshakeSharedPluginOptions) { + name = 'TreeShakingSharedPlugin'; + constructor(options: TreeshakingSharedPluginOptions) { const { mfConfig, reShake } = options; this.mfConfig = mfConfig; - this.outputDir = mfConfig.treeshakeSharedDir || 'independent-packages'; + this.outputDir = mfConfig.treeShakingSharedDir || 'independent-packages'; this.reShake = Boolean(reShake); } apply(compiler: Compiler) { const { mfConfig, outputDir, reShake } = this; - const { name, shared, library, treeshakeSharedPlugins } = mfConfig; + const { name, shared, library, treeShakingSharedPlugins } = mfConfig; if (!shared) { return; } @@ -36,13 +36,13 @@ export class TreeShakeSharedPlugin { if ( sharedOptions.some( - ([_, config]) => config.treeshake && config.import !== false, + ([_, config]) => config.treeShaking && config.import !== false, ) ) { if (!reShake) { new SharedUsedExportsOptimizerPlugin( sharedOptions, - mfConfig.injectUsedExports, + mfConfig.injectTreeShakingUsedExports, mfConfig.manifest, ).apply(compiler); } @@ -50,11 +50,16 @@ export class TreeShakeSharedPlugin { name: name, shared: shared, outputDir, - plugins: treeshakeSharedPlugins?.map((p) => require(p)) || [], - treeshake: reShake, + plugins: + treeShakingSharedPlugins?.map((p) => { + const _constructor = require(p); + return new _constructor(); + }) || [], + treeShaking: reShake, library, manifest: mfConfig.manifest, - treeshakeSharedExcludePlugins: mfConfig.treeshakeSharedExcludePlugins, + treeShakingSharedExcludePlugins: + mfConfig.treeShakingSharedExcludePlugins, }); this._independentSharePlugin.apply(compiler); } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e8983395aa48..8941b19f307c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -345,8 +345,8 @@ importers: packages/rspack: dependencies: '@module-federation/runtime-tools': - specifier: 0.0.0-feat-shared-treeshake-poc-20251230120553 - version: 0.0.0-feat-shared-treeshake-poc-20251230120553 + specifier: 0.0.0-feat-shared-treeshake-poc-20260112063915 + version: 0.0.0-feat-shared-treeshake-poc-20260112063915 '@rspack/binding': specifier: workspace:* version: link:../../crates/node_binding @@ -2436,42 +2436,60 @@ packages: '@microsoft/tsdoc@0.16.0': resolution: {integrity: sha512-xgAyonlVVS+q7Vc7qLW0UrJU7rSFcETRWsqdXZtjzRU8dF+6CkozTK4V4y1LwOX7j8r/vHphjDeMeGI4tNGeGA==} - '@module-federation/error-codes@0.0.0-feat-shared-treeshake-poc-20251230120553': - resolution: {integrity: sha512-MR19b/ZGgVMDyFHoDr1Wp31/ZD8VohqxXzbVXGrkanHR6ojr4In9+wMa19/lWkkS5+CYze5LY9qZukmGqIzGGw==} + '@module-federation/error-codes@0.0.0-feat-shared-treeshake-poc-20260112063915': + resolution: {integrity: sha512-4uEX/pP736lBol4kNQhBXWxgi5ZwYt5yessvex4QyPBFhgbwKUAlUXkDjq9majoDUvfwrnmR3qVcyZldyffzsQ==} '@module-federation/error-codes@0.21.6': resolution: {integrity: sha512-MLJUCQ05KnoVl8xd6xs9a5g2/8U+eWmVxg7xiBMeR0+7OjdWUbHwcwgVFatRIwSZvFgKHfWEiI7wsU1q1XbTRQ==} - '@module-federation/runtime-core@0.0.0-feat-shared-treeshake-poc-20251230120553': - resolution: {integrity: sha512-0s+q/Yiwg20VaheIj/wARc2uWXuIwS1ZTLeaUFUIKjDhgZRYn75m8lyP2YXWbjE50iADnD0PnCB/+/hHGTUZIw==} + '@module-federation/error-codes@0.22.0': + resolution: {integrity: sha512-xF9SjnEy7vTdx+xekjPCV5cIHOGCkdn3pIxo9vU7gEZMIw0SvAEdsy6Uh17xaCpm8V0FWvR0SZoK9Ik6jGOaug==} + + '@module-federation/runtime-core@0.0.0-feat-shared-treeshake-poc-20260112063915': + resolution: {integrity: sha512-tUlxVoY12LFvY3kCwiVMFtoMhJ0+/Igmca4MD3iA9e52s/regdpfucNhZHCpsg9fYmY7uJsjeLMVB45vbM0cKA==} '@module-federation/runtime-core@0.21.6': resolution: {integrity: sha512-5Hd1Y5qp5lU/aTiK66lidMlM/4ji2gr3EXAtJdreJzkY+bKcI5+21GRcliZ4RAkICmvdxQU5PHPL71XmNc7Lsw==} - '@module-federation/runtime-tools@0.0.0-feat-shared-treeshake-poc-20251230120553': - resolution: {integrity: sha512-CiabUJIymlGH/7w2/4lOA+Ga5vHefsI045mUB5Efe2lNPCwU7b/hpIoMGdvzPEaPNGP9zaEYvBTLrQQ1pBZBiw==} + '@module-federation/runtime-core@0.22.0': + resolution: {integrity: sha512-GR1TcD6/s7zqItfhC87zAp30PqzvceoeDGYTgF3Vx2TXvsfDrhP6Qw9T4vudDQL3uJRne6t7CzdT29YyVxlgIA==} + + '@module-federation/runtime-tools@0.0.0-feat-shared-treeshake-poc-20260112063915': + resolution: {integrity: sha512-WsMFP6u0ii3v4htfAF5WglAFQOz3l6wNgifU5bZJfCCBDL6xfp8yUhXQBmY26NosDYBGyZeVXB+YI4By4dH5dQ==} '@module-federation/runtime-tools@0.21.6': resolution: {integrity: sha512-fnP+ZOZTFeBGiTAnxve+axGmiYn2D60h86nUISXjXClK3LUY1krUfPgf6MaD4YDJ4i51OGXZWPekeMe16pkd8Q==} - '@module-federation/runtime@0.0.0-feat-shared-treeshake-poc-20251230120553': - resolution: {integrity: sha512-KxX3OSZzrNw6MzjTn0Ur7K0mZ/8x+/TTiyaVtLD6iAVgCi3nmnj2hAmcNtGF733Na2vTtxCJCcFZBnW3DlQzmw==} + '@module-federation/runtime-tools@0.22.0': + resolution: {integrity: sha512-4ScUJ/aUfEernb+4PbLdhM/c60VHl698Gn1gY21m9vyC1Ucn69fPCA1y2EwcCB7IItseRMoNhdcWQnzt/OPCNA==} + + '@module-federation/runtime@0.0.0-feat-shared-treeshake-poc-20260112063915': + resolution: {integrity: sha512-u4SaPkbYtMWdEmxbXhEj13nROnGBr02U6IXF8JXIvvPEHO+ryF/DXJt21HTCgVzYjf2q2kkam0pd7qd+82R/Eg==} '@module-federation/runtime@0.21.6': resolution: {integrity: sha512-+caXwaQqwTNh+CQqyb4mZmXq7iEemRDrTZQGD+zyeH454JAYnJ3s/3oDFizdH6245pk+NiqDyOOkHzzFQorKhQ==} - '@module-federation/sdk@0.0.0-feat-shared-treeshake-poc-20251230120553': - resolution: {integrity: sha512-3syc+/8Q8MNLoFPcpCRQ4uwCqv+7zsX/60WM4pqt058ZN1Y7AO4DDwxzuF+pt8vHxudcqALNa6VtDHvoPt8GPA==} + '@module-federation/runtime@0.22.0': + resolution: {integrity: sha512-38g5iPju2tPC3KHMPxRKmy4k4onNp6ypFPS1eKGsNLUkXgHsPMBFqAjDw96iEcjri91BrahG4XcdyKi97xZzlA==} + + '@module-federation/sdk@0.0.0-feat-shared-treeshake-poc-20260112063915': + resolution: {integrity: sha512-O8jgq1o8blGys+zf87ToqNsjTaRBUV9zfzcpy4S1YPCAOcW8i2alHOdqppJAXF5fGlI6x8+3jXEALGqxAUrkWQ==} '@module-federation/sdk@0.21.6': resolution: {integrity: sha512-x6hARETb8iqHVhEsQBysuWpznNZViUh84qV2yE7AD+g7uIzHKiYdoWqj10posbo5XKf/147qgWDzKZoKoEP2dw==} - '@module-federation/webpack-bundler-runtime@0.0.0-feat-shared-treeshake-poc-20251230120553': - resolution: {integrity: sha512-KOi1+Tj9xz+9DYMfFp6exgKkYkzQ2X6zkof/yBq7HXdAnF9ID5Sc30JG/5pp+y9+bCv6uzKWV96n9Nrsk/igqA==} + '@module-federation/sdk@0.22.0': + resolution: {integrity: sha512-x4aFNBKn2KVQRuNVC5A7SnrSCSqyfIWmm1DvubjbO9iKFe7ith5niw8dqSFBekYBg2Fwy+eMg4sEFNVvCAdo6g==} + + '@module-federation/webpack-bundler-runtime@0.0.0-feat-shared-treeshake-poc-20260112063915': + resolution: {integrity: sha512-ULsyc6WLtiyeZ3BegBL685cCBc5XrxjvwnGhNcsE4POY5Eev/fznBq3lsLoeycc2bHwXxaZzk0u8OYmH1Mnn9A==} '@module-federation/webpack-bundler-runtime@0.21.6': resolution: {integrity: sha512-7zIp3LrcWbhGuFDTUMLJ2FJvcwjlddqhWGxi/MW3ur1a+HaO8v5tF2nl+vElKmbG1DFLU/52l3PElVcWf/YcsQ==} + '@module-federation/webpack-bundler-runtime@0.22.0': + resolution: {integrity: sha512-aM8gCqXu+/4wBmJtVeMeeMN5guw3chf+2i6HajKtQv7SJfxV/f4IyNQJUeUQu9HfiAZHjqtMV5Lvq/Lvh8LdyA==} + '@napi-rs/cli@3.0.4': resolution: {integrity: sha512-ilbCI69DVDQcIUSUB504LM1+Nhvo0jKycWAzzPJ22YwUoWrru/w0+V5sfjPINgkshQ4Ykv+oZOJXk9Kg1ZBUvg==} engines: {node: '>= 16'} @@ -10199,35 +10217,47 @@ snapshots: '@microsoft/tsdoc@0.16.0': {} - '@module-federation/error-codes@0.0.0-feat-shared-treeshake-poc-20251230120553': {} + '@module-federation/error-codes@0.0.0-feat-shared-treeshake-poc-20260112063915': {} '@module-federation/error-codes@0.21.6': {} - '@module-federation/runtime-core@0.0.0-feat-shared-treeshake-poc-20251230120553': + '@module-federation/error-codes@0.22.0': {} + + '@module-federation/runtime-core@0.0.0-feat-shared-treeshake-poc-20260112063915': dependencies: - '@module-federation/error-codes': 0.0.0-feat-shared-treeshake-poc-20251230120553 - '@module-federation/sdk': 0.0.0-feat-shared-treeshake-poc-20251230120553 + '@module-federation/error-codes': 0.0.0-feat-shared-treeshake-poc-20260112063915 + '@module-federation/sdk': 0.0.0-feat-shared-treeshake-poc-20260112063915 '@module-federation/runtime-core@0.21.6': dependencies: '@module-federation/error-codes': 0.21.6 '@module-federation/sdk': 0.21.6 - '@module-federation/runtime-tools@0.0.0-feat-shared-treeshake-poc-20251230120553': + '@module-federation/runtime-core@0.22.0': + dependencies: + '@module-federation/error-codes': 0.22.0 + '@module-federation/sdk': 0.22.0 + + '@module-federation/runtime-tools@0.0.0-feat-shared-treeshake-poc-20260112063915': dependencies: - '@module-federation/runtime': 0.0.0-feat-shared-treeshake-poc-20251230120553 - '@module-federation/webpack-bundler-runtime': 0.0.0-feat-shared-treeshake-poc-20251230120553 + '@module-federation/runtime': 0.0.0-feat-shared-treeshake-poc-20260112063915 + '@module-federation/webpack-bundler-runtime': 0.0.0-feat-shared-treeshake-poc-20260112063915 '@module-federation/runtime-tools@0.21.6': dependencies: '@module-federation/runtime': 0.21.6 '@module-federation/webpack-bundler-runtime': 0.21.6 - '@module-federation/runtime@0.0.0-feat-shared-treeshake-poc-20251230120553': + '@module-federation/runtime-tools@0.22.0': + dependencies: + '@module-federation/runtime': 0.22.0 + '@module-federation/webpack-bundler-runtime': 0.22.0 + + '@module-federation/runtime@0.0.0-feat-shared-treeshake-poc-20260112063915': dependencies: - '@module-federation/error-codes': 0.0.0-feat-shared-treeshake-poc-20251230120553 - '@module-federation/runtime-core': 0.0.0-feat-shared-treeshake-poc-20251230120553 - '@module-federation/sdk': 0.0.0-feat-shared-treeshake-poc-20251230120553 + '@module-federation/error-codes': 0.0.0-feat-shared-treeshake-poc-20260112063915 + '@module-federation/runtime-core': 0.0.0-feat-shared-treeshake-poc-20260112063915 + '@module-federation/sdk': 0.0.0-feat-shared-treeshake-poc-20260112063915 '@module-federation/runtime@0.21.6': dependencies: @@ -10235,20 +10265,33 @@ snapshots: '@module-federation/runtime-core': 0.21.6 '@module-federation/sdk': 0.21.6 - '@module-federation/sdk@0.0.0-feat-shared-treeshake-poc-20251230120553': {} + '@module-federation/runtime@0.22.0': + dependencies: + '@module-federation/error-codes': 0.22.0 + '@module-federation/runtime-core': 0.22.0 + '@module-federation/sdk': 0.22.0 + + '@module-federation/sdk@0.0.0-feat-shared-treeshake-poc-20260112063915': {} '@module-federation/sdk@0.21.6': {} - '@module-federation/webpack-bundler-runtime@0.0.0-feat-shared-treeshake-poc-20251230120553': + '@module-federation/sdk@0.22.0': {} + + '@module-federation/webpack-bundler-runtime@0.0.0-feat-shared-treeshake-poc-20260112063915': dependencies: - '@module-federation/runtime': 0.0.0-feat-shared-treeshake-poc-20251230120553 - '@module-federation/sdk': 0.0.0-feat-shared-treeshake-poc-20251230120553 + '@module-federation/runtime': 0.0.0-feat-shared-treeshake-poc-20260112063915 + '@module-federation/sdk': 0.0.0-feat-shared-treeshake-poc-20260112063915 '@module-federation/webpack-bundler-runtime@0.21.6': dependencies: '@module-federation/runtime': 0.21.6 '@module-federation/sdk': 0.21.6 + '@module-federation/webpack-bundler-runtime@0.22.0': + dependencies: + '@module-federation/runtime': 0.22.0 + '@module-federation/sdk': 0.22.0 + '@napi-rs/cli@3.0.4(@emnapi/runtime@1.5.0)(@types/node@20.19.27)(emnapi@1.7.1(node-addon-api@7.1.1))': dependencies: '@inquirer/prompts': 7.8.6(@types/node@20.19.27) diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/App.js b/tests/rspack-test/configCases/container-1-5/tree-shaking-shared-infer-mode/App.js similarity index 76% rename from tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/App.js rename to tests/rspack-test/configCases/container-1-5/tree-shaking-shared-infer-mode/App.js index 5ba9987fe9ef..00ff133010d7 100644 --- a/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/App.js +++ b/tests/rspack-test/configCases/container-1-5/tree-shaking-shared-infer-mode/App.js @@ -5,7 +5,7 @@ import UiLibScopeSc from '@scope-sc/ui-lib'; export default () => { return `default Uilib has ${Object.keys(UiLib).join( ', ', - )} exports not treeshake, and ui-lib-es Button value is ${Button} should treeshake`; + )} exports not tree shaking, and ui-lib-es Button value is ${Button} should tree shaking`; }; export const scopeScUILib = () => { @@ -16,15 +16,15 @@ export const scopeScUILib = () => { export const dynamicUISpecificExport = async () => { const { List } = await import('ui-lib-dynamic-specific-export'); - return `dynamic Uilib has ${List} exports treeshake`; + return `dynamic Uilib has ${List} exports tree shaking`; }; export const dynamicUIDefaultExport = async () => { const uiLib = await import('ui-lib-dynamic-default-export'); - return `dynamic Uilib has ${uiLib.List} exports treeshake`; + return `dynamic Uilib has ${uiLib.List} exports tree shaking`; }; export const dynamicUISideEffectExport = async () => { const uiLibSideEffect = await import('ui-lib-side-effect'); - return `dynamic Uilib has ${uiLibSideEffect.List} exports not treeshake`; + return `dynamic Uilib has ${uiLibSideEffect.List} exports not tree shaking`; }; diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/index.js b/tests/rspack-test/configCases/container-1-5/tree-shaking-shared-infer-mode/index.js similarity index 76% rename from tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/index.js rename to tests/rspack-test/configCases/container-1-5/tree-shaking-shared-infer-mode/index.js index 42cff89ef766..5ed69631e85b 100644 --- a/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/index.js +++ b/tests/rspack-test/configCases/container-1-5/tree-shaking-shared-infer-mode/index.js @@ -2,10 +2,10 @@ const fs = __non_webpack_require__('fs'); const path = __non_webpack_require__('path'); __webpack_require__.p = 'PUBLIC_PATH'; -it('should load treeshake shared via set infer strategy', async () => { +it('should load tree shaking shared via set "runtime-infer" mode', async () => { const app = await import('./App.js'); expect(app.default()).toEqual( - 'default Uilib has Button, List, Badge exports not treeshake, and ui-lib-es Button value is Button should treeshake', + 'default Uilib has Button, List, Badge exports not tree shaking, and ui-lib-es Button value is Button should tree shaking', ); const bundlePath = path.join(__dirname, 'node_modules_ui-lib_index_js.js'); @@ -15,12 +15,12 @@ it('should load treeshake shared via set infer strategy', async () => { expect(bundleContent).toContain('List'); const uiLibShared = - __FEDERATION__.__SHARE__['treeshake_share'].default['ui-lib'][ + __FEDERATION__.__SHARE__['tree_shaking_share'].default['ui-lib'][ '1.0.0' ]; expect(uiLibShared.loaded).toEqual(undefined); - expect(uiLibShared.treeshake.loaded).toEqual(true); - expect(Object.keys(uiLibShared.treeshake.lib()).sort()).toEqual([ + expect(uiLibShared.treeShaking.loaded).toEqual(true); + expect(Object.keys(uiLibShared.treeShaking.lib()).sort()).toEqual([ 'Button', 'default', ]); @@ -43,22 +43,22 @@ it('should load treeshake shared via set infer strategy', async () => { expect(uiLibESBundleContent).not.toContain('List'); const uiLibESShared = - __FEDERATION__.__SHARE__['treeshake_share'].default['ui-lib-es'][ + __FEDERATION__.__SHARE__['tree_shaking_share'].default['ui-lib-es'][ '1.0.0' ]; expect(uiLibESShared.loaded).toEqual(undefined); - expect(uiLibESShared.treeshake.loaded).toEqual(true); + expect(uiLibESShared.treeShaking.loaded).toEqual(true); - expect(Object.keys(uiLibESShared.treeshake.lib()).sort()).toEqual(['Button']); + expect(Object.keys(uiLibESShared.treeShaking.lib()).sort()).toEqual(['Button']); const esFallback = (await uiLibESShared.get())(); expect(Object.keys(esFallback).sort()).toEqual(['Badge', 'Button', 'List']); }); -it('should treeshake ui-lib-dynamic-specific-export correctly', async () => { +it('should tree shaking ui-lib-dynamic-specific-export correctly', async () => { const { dynamicUISpecificExport } = await import('./App.js'); expect(await dynamicUISpecificExport()).toEqual( - 'dynamic Uilib has List exports treeshake', + 'dynamic Uilib has List exports tree shaking', ); const bundlePath = path.join( @@ -71,11 +71,11 @@ it('should treeshake ui-lib-dynamic-specific-export correctly', async () => { expect(bundleContent).not.toContain('Badge'); }); -// different from webpack, webpack can not treeshake dynamic import -it('should treeshake ui-lib-dynamic-default-export', async () => { +// different from webpack, webpack can not tree shaking dynamic import +it('should tree shaking ui-lib-dynamic-default-export', async () => { const { dynamicUIDefaultExport } = await import('./App.js'); expect(await dynamicUIDefaultExport()).toEqual( - 'dynamic Uilib has List exports treeshake', + 'dynamic Uilib has List exports tree shaking', ); const bundlePath = path.join( @@ -88,10 +88,10 @@ it('should treeshake ui-lib-dynamic-default-export', async () => { expect(bundleContent).not.toContain('Badge'); }); -it('should not treeshake ui-lib-side-effect if not set sideEffect:false ', async () => { +it('should not tree shaking ui-lib-side-effect if not set sideEffect:false ', async () => { const { dynamicUISideEffectExport } = await import('./App.js'); expect(await dynamicUISideEffectExport()).toEqual( - 'dynamic Uilib has List exports not treeshake', + 'dynamic Uilib has List exports not tree shaking', ); const bundlePath = path.join( @@ -123,7 +123,7 @@ it('should inject usedExports into manifest and stats if enable manifest', async ).toEqual(JSON.stringify(['Button', 'default'])); }); -it('should treeshake scope-sc ui-lib correctly', async () => { +it('should tree shaking scope-sc ui-lib correctly', async () => { const { scopeScUILib } = await import('./App.js'); expect(scopeScUILib()).toEqual('scope-sc Uilib has Button, List, Badge'); diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/@scope-sc/ui-lib/index.js b/tests/rspack-test/configCases/container-1-5/tree-shaking-shared-infer-mode/node_modules/@scope-sc/ui-lib/index.js similarity index 100% rename from tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/@scope-sc/ui-lib/index.js rename to tests/rspack-test/configCases/container-1-5/tree-shaking-shared-infer-mode/node_modules/@scope-sc/ui-lib/index.js diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/@scope-sc/ui-lib/package.json b/tests/rspack-test/configCases/container-1-5/tree-shaking-shared-infer-mode/node_modules/@scope-sc/ui-lib/package.json similarity index 100% rename from tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/@scope-sc/ui-lib/package.json rename to tests/rspack-test/configCases/container-1-5/tree-shaking-shared-infer-mode/node_modules/@scope-sc/ui-lib/package.json diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib-dynamic-default-export/index.js b/tests/rspack-test/configCases/container-1-5/tree-shaking-shared-infer-mode/node_modules/ui-lib-dynamic-default-export/index.js similarity index 100% rename from tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib-dynamic-default-export/index.js rename to tests/rspack-test/configCases/container-1-5/tree-shaking-shared-infer-mode/node_modules/ui-lib-dynamic-default-export/index.js diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib-dynamic-default-export/package.json b/tests/rspack-test/configCases/container-1-5/tree-shaking-shared-infer-mode/node_modules/ui-lib-dynamic-default-export/package.json similarity index 100% rename from tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib-dynamic-default-export/package.json rename to tests/rspack-test/configCases/container-1-5/tree-shaking-shared-infer-mode/node_modules/ui-lib-dynamic-default-export/package.json diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib-dynamic-specific-export/index.js b/tests/rspack-test/configCases/container-1-5/tree-shaking-shared-infer-mode/node_modules/ui-lib-dynamic-specific-export/index.js similarity index 100% rename from tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib-dynamic-specific-export/index.js rename to tests/rspack-test/configCases/container-1-5/tree-shaking-shared-infer-mode/node_modules/ui-lib-dynamic-specific-export/index.js diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib-dynamic-specific-export/package.json b/tests/rspack-test/configCases/container-1-5/tree-shaking-shared-infer-mode/node_modules/ui-lib-dynamic-specific-export/package.json similarity index 100% rename from tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib-dynamic-specific-export/package.json rename to tests/rspack-test/configCases/container-1-5/tree-shaking-shared-infer-mode/node_modules/ui-lib-dynamic-specific-export/package.json diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib-es/index.js b/tests/rspack-test/configCases/container-1-5/tree-shaking-shared-infer-mode/node_modules/ui-lib-es/index.js similarity index 100% rename from tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib-es/index.js rename to tests/rspack-test/configCases/container-1-5/tree-shaking-shared-infer-mode/node_modules/ui-lib-es/index.js diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib-es/package.json b/tests/rspack-test/configCases/container-1-5/tree-shaking-shared-infer-mode/node_modules/ui-lib-es/package.json similarity index 100% rename from tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib-es/package.json rename to tests/rspack-test/configCases/container-1-5/tree-shaking-shared-infer-mode/node_modules/ui-lib-es/package.json diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib-side-effect/index.js b/tests/rspack-test/configCases/container-1-5/tree-shaking-shared-infer-mode/node_modules/ui-lib-side-effect/index.js similarity index 100% rename from tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib-side-effect/index.js rename to tests/rspack-test/configCases/container-1-5/tree-shaking-shared-infer-mode/node_modules/ui-lib-side-effect/index.js diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib-side-effect/package.json b/tests/rspack-test/configCases/container-1-5/tree-shaking-shared-infer-mode/node_modules/ui-lib-side-effect/package.json similarity index 100% rename from tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib-side-effect/package.json rename to tests/rspack-test/configCases/container-1-5/tree-shaking-shared-infer-mode/node_modules/ui-lib-side-effect/package.json diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib/index.js b/tests/rspack-test/configCases/container-1-5/tree-shaking-shared-infer-mode/node_modules/ui-lib/index.js similarity index 100% rename from tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib/index.js rename to tests/rspack-test/configCases/container-1-5/tree-shaking-shared-infer-mode/node_modules/ui-lib/index.js diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib/package.json b/tests/rspack-test/configCases/container-1-5/tree-shaking-shared-infer-mode/node_modules/ui-lib/package.json similarity index 100% rename from tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/node_modules/ui-lib/package.json rename to tests/rspack-test/configCases/container-1-5/tree-shaking-shared-infer-mode/node_modules/ui-lib/package.json diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/rspack.config.js b/tests/rspack-test/configCases/container-1-5/tree-shaking-shared-infer-mode/rspack.config.js similarity index 75% rename from tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/rspack.config.js rename to tests/rspack-test/configCases/container-1-5/tree-shaking-shared-infer-mode/rspack.config.js index 2f288c5d98d2..2b5050150a72 100644 --- a/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/rspack.config.js +++ b/tests/rspack-test/configCases/container-1-5/tree-shaking-shared-infer-mode/rspack.config.js @@ -20,12 +20,12 @@ module.exports = { target: 'async-node', plugins: [ new ModuleFederationPlugin({ - name: 'treeshake_share', + name: 'tree_shaking_share', manifest: true, filename: 'remoteEntry.js', library: { type: 'commonjs-module', - name: 'treeshake_share', + name: 'tree_shaking_share', }, exposes: { './App': './App.js', @@ -34,38 +34,38 @@ module.exports = { shared: { '@scope-sc/ui-lib': { requiredVersion: '*', - treeshake: { - strategy: 'infer', + treeShaking: { + mode: 'runtime-infer', }, }, 'ui-lib': { requiredVersion: '*', - treeshake: { - strategy: 'infer', + treeShaking: { + mode: 'runtime-infer', }, }, 'ui-lib-es': { requiredVersion: '*', - treeshake: { - strategy: 'infer', + treeShaking: { + mode: 'runtime-infer', }, }, 'ui-lib-dynamic-specific-export': { requiredVersion: '*', - treeshake: { - strategy: 'infer', + treeShaking: { + mode: 'runtime-infer', }, }, 'ui-lib-dynamic-default-export': { requiredVersion: '*', - treeshake: { - strategy: 'infer', + treeShaking: { + mode: 'runtime-infer', }, }, 'ui-lib-side-effect': { requiredVersion: '*', - treeshake: { - strategy: 'infer', + treeShaking: { + mode: 'runtime-infer', }, }, }, diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/runtime-plugin.js b/tests/rspack-test/configCases/container-1-5/tree-shaking-shared-infer-mode/runtime-plugin.js similarity index 82% rename from tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/runtime-plugin.js rename to tests/rspack-test/configCases/container-1-5/tree-shaking-shared-infer-mode/runtime-plugin.js index ab2827958f6c..af15582195be 100644 --- a/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/runtime-plugin.js +++ b/tests/rspack-test/configCases/container-1-5/tree-shaking-shared-infer-mode/runtime-plugin.js @@ -1,6 +1,6 @@ // const path = require('path'); -// default strategy will use fallback asset if no server data. And the fallback will load asset via fetch + eval. +// default mode will use fallback asset if no server data. And the fallback will load asset via fetch + eval. // Cause the asset not deploy, so we need to proxy the asset to local. module.exports = function () { return { diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/test.config.js b/tests/rspack-test/configCases/container-1-5/tree-shaking-shared-infer-mode/test.config.js similarity index 100% rename from tests/rspack-test/configCases/container-1-5/treeshake-shared-infer-strategy/test.config.js rename to tests/rspack-test/configCases/container-1-5/tree-shaking-shared-infer-mode/test.config.js diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/App.js b/tests/rspack-test/configCases/container-1-5/tree-shaking-shared-server-mode/App.js similarity index 71% rename from tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/App.js rename to tests/rspack-test/configCases/container-1-5/tree-shaking-shared-server-mode/App.js index 823b48b590e9..0fcdcc8a4bef 100644 --- a/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/App.js +++ b/tests/rspack-test/configCases/container-1-5/tree-shaking-shared-server-mode/App.js @@ -4,20 +4,20 @@ import { Button } from 'ui-lib-es'; export default () => { return `default Uilib has ${Object.values(UiLib).join( ', ', - )} exports not treeshake, and ui-lib-es Button value is ${Button} should treeshake`; + )} exports not tree shaking, and ui-lib-es Button value is ${Button} should tree shaking`; }; export const dynamicUISpecificExport = async () => { const { List } = await import('ui-lib-dynamic-specific-export'); - return `dynamic Uilib has ${List} exports treeshake`; + return `dynamic Uilib has ${List} exports tree shaking`; }; export const dynamicUIDefaultExport = async () => { const uiLib = await import('ui-lib-dynamic-default-export'); - return `dynamic Uilib has ${uiLib.List} exports treeshake`; + return `dynamic Uilib has ${uiLib.List} exports tree shaking`; }; export const dynamicUISideEffectExport = async () => { const uiLibSideEffect = await import('ui-lib-side-effect'); - return `dynamic Uilib has ${uiLibSideEffect.List} exports not treeshake`; + return `dynamic Uilib has ${uiLibSideEffect.List} exports not tree shaking`; }; diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/index.js b/tests/rspack-test/configCases/container-1-5/tree-shaking-shared-server-mode/index.js similarity index 73% rename from tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/index.js rename to tests/rspack-test/configCases/container-1-5/tree-shaking-shared-server-mode/index.js index 359fa865dc16..e268319c5710 100644 --- a/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/index.js +++ b/tests/rspack-test/configCases/container-1-5/tree-shaking-shared-server-mode/index.js @@ -2,10 +2,10 @@ const fs = __non_webpack_require__('fs'); const path = __non_webpack_require__('path'); __webpack_require__.p = 'PUBLIC_PATH'; -it('should not load treeshake shared via set server strategy and no server data dispatch', async () => { +it('should not load tree shaking shared via set "server-calc" mode and no server data dispatch', async () => { const app = await import('./App.js'); expect(app.default()).toEqual( - 'default Uilib has Button, List, Badge exports not treeshake, and ui-lib-es Button value is Button should treeshake', + 'default Uilib has Button, List, Badge exports not tree shaking, and ui-lib-es Button value is Button should tree shaking', ); const bundlePath = path.join(__dirname, 'node_modules_ui-lib_index_js.js'); @@ -15,11 +15,11 @@ it('should not load treeshake shared via set server strategy and no server data expect(bundleContent).toContain('List'); const uiLibShared = - __FEDERATION__.__SHARE__['treeshake_share_server'].default['ui-lib'][ + __FEDERATION__.__SHARE__['tree_shaking_share_server'].default['ui-lib'][ '1.0.0' ]; expect(uiLibShared.loaded).toEqual(true); - expect(uiLibShared.treeshake.loaded).toEqual(undefined); + expect(uiLibShared.treeShaking.loaded).toEqual(undefined); expect(Object.keys(uiLibShared.lib()).sort()).toEqual([ 'Badge', 'Button', @@ -27,8 +27,8 @@ it('should not load treeshake shared via set server strategy and no server data 'default', ]); - const uiLibTreeshake = (await uiLibShared.treeshake.get())(); - expect(Object.keys(uiLibTreeshake).sort()).toEqual(['Button', 'default']); + const uiLibTreeShaking = (await uiLibShared.treeShaking.get())(); + expect(Object.keys(uiLibTreeShaking).sort()).toEqual(['Button', 'default']); const uiLibESBundlePath = path.join( __dirname, @@ -40,11 +40,11 @@ it('should not load treeshake shared via set server strategy and no server data expect(uiLibESBundleContent).not.toContain('List'); const uiLibESShared = - __FEDERATION__.__SHARE__['treeshake_share_server'].default[ + __FEDERATION__.__SHARE__['tree_shaking_share_server'].default[ 'ui-lib-es' ]['1.0.0']; expect(uiLibESShared.loaded).toEqual(true); - expect(uiLibESShared.treeshake.loaded).toEqual(undefined); + expect(uiLibESShared.treeShaking.loaded).toEqual(undefined); expect(Object.keys(uiLibESShared.lib()).sort()).toEqual([ 'Badge', @@ -52,14 +52,14 @@ it('should not load treeshake shared via set server strategy and no server data 'List', ]); - const esTreeshake = (await uiLibESShared.treeshake.get())(); - expect(Object.keys(esTreeshake).sort()).toEqual(['Button']); + const esTreeShaking = (await uiLibESShared.treeShaking.get())(); + expect(Object.keys(esTreeShaking).sort()).toEqual(['Button']); }); -it('should treeshake ui-lib-dynamic-specific-export correctly', async () => { +it('should tree shaking ui-lib-dynamic-specific-export correctly', async () => { const { dynamicUISpecificExport } = await import('./App.js'); expect(await dynamicUISpecificExport()).toEqual( - 'dynamic Uilib has List exports treeshake', + 'dynamic Uilib has List exports tree shaking', ); const bundlePath = path.join( @@ -72,10 +72,10 @@ it('should treeshake ui-lib-dynamic-specific-export correctly', async () => { expect(bundleContent).not.toContain('Badge'); }); -it('should treeshake ui-lib-dynamic-default-export', async () => { +it('should tree shaking ui-lib-dynamic-default-export', async () => { const { dynamicUIDefaultExport } = await import('./App.js'); expect(await dynamicUIDefaultExport()).toEqual( - 'dynamic Uilib has List exports treeshake', + 'dynamic Uilib has List exports tree shaking', ); const bundlePath = path.join( @@ -88,10 +88,10 @@ it('should treeshake ui-lib-dynamic-default-export', async () => { expect(bundleContent).not.toContain('Badge'); }); -it('should not treeshake ui-lib-side-effect if not set sideEffect:false ', async () => { +it('should not tree shaking ui-lib-side-effect if not set sideEffect:false ', async () => { const { dynamicUISideEffectExport } = await import('./App.js'); expect(await dynamicUISideEffectExport()).toEqual( - 'dynamic Uilib has List exports not treeshake', + 'dynamic Uilib has List exports not tree shaking', ); const bundlePath = path.join( diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/.federation/shared-entry.js b/tests/rspack-test/configCases/container-1-5/tree-shaking-shared-server-mode/node_modules/.federation/shared-entry.js similarity index 100% rename from tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/.federation/shared-entry.js rename to tests/rspack-test/configCases/container-1-5/tree-shaking-shared-server-mode/node_modules/.federation/shared-entry.js diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib-dynamic-default-export/index.js b/tests/rspack-test/configCases/container-1-5/tree-shaking-shared-server-mode/node_modules/ui-lib-dynamic-default-export/index.js similarity index 100% rename from tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib-dynamic-default-export/index.js rename to tests/rspack-test/configCases/container-1-5/tree-shaking-shared-server-mode/node_modules/ui-lib-dynamic-default-export/index.js diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib-dynamic-default-export/package.json b/tests/rspack-test/configCases/container-1-5/tree-shaking-shared-server-mode/node_modules/ui-lib-dynamic-default-export/package.json similarity index 100% rename from tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib-dynamic-default-export/package.json rename to tests/rspack-test/configCases/container-1-5/tree-shaking-shared-server-mode/node_modules/ui-lib-dynamic-default-export/package.json diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib-dynamic-specific-export/index.js b/tests/rspack-test/configCases/container-1-5/tree-shaking-shared-server-mode/node_modules/ui-lib-dynamic-specific-export/index.js similarity index 100% rename from tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib-dynamic-specific-export/index.js rename to tests/rspack-test/configCases/container-1-5/tree-shaking-shared-server-mode/node_modules/ui-lib-dynamic-specific-export/index.js diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib-dynamic-specific-export/package.json b/tests/rspack-test/configCases/container-1-5/tree-shaking-shared-server-mode/node_modules/ui-lib-dynamic-specific-export/package.json similarity index 100% rename from tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib-dynamic-specific-export/package.json rename to tests/rspack-test/configCases/container-1-5/tree-shaking-shared-server-mode/node_modules/ui-lib-dynamic-specific-export/package.json diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib-es/index.js b/tests/rspack-test/configCases/container-1-5/tree-shaking-shared-server-mode/node_modules/ui-lib-es/index.js similarity index 100% rename from tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib-es/index.js rename to tests/rspack-test/configCases/container-1-5/tree-shaking-shared-server-mode/node_modules/ui-lib-es/index.js diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib-es/package.json b/tests/rspack-test/configCases/container-1-5/tree-shaking-shared-server-mode/node_modules/ui-lib-es/package.json similarity index 100% rename from tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib-es/package.json rename to tests/rspack-test/configCases/container-1-5/tree-shaking-shared-server-mode/node_modules/ui-lib-es/package.json diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib-side-effect/index.js b/tests/rspack-test/configCases/container-1-5/tree-shaking-shared-server-mode/node_modules/ui-lib-side-effect/index.js similarity index 100% rename from tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib-side-effect/index.js rename to tests/rspack-test/configCases/container-1-5/tree-shaking-shared-server-mode/node_modules/ui-lib-side-effect/index.js diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib-side-effect/package.json b/tests/rspack-test/configCases/container-1-5/tree-shaking-shared-server-mode/node_modules/ui-lib-side-effect/package.json similarity index 100% rename from tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib-side-effect/package.json rename to tests/rspack-test/configCases/container-1-5/tree-shaking-shared-server-mode/node_modules/ui-lib-side-effect/package.json diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib/index.js b/tests/rspack-test/configCases/container-1-5/tree-shaking-shared-server-mode/node_modules/ui-lib/index.js similarity index 100% rename from tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib/index.js rename to tests/rspack-test/configCases/container-1-5/tree-shaking-shared-server-mode/node_modules/ui-lib/index.js diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib/package.json b/tests/rspack-test/configCases/container-1-5/tree-shaking-shared-server-mode/node_modules/ui-lib/package.json similarity index 100% rename from tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/node_modules/ui-lib/package.json rename to tests/rspack-test/configCases/container-1-5/tree-shaking-shared-server-mode/node_modules/ui-lib/package.json diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/rspack.config.js b/tests/rspack-test/configCases/container-1-5/tree-shaking-shared-server-mode/rspack.config.js similarity index 76% rename from tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/rspack.config.js rename to tests/rspack-test/configCases/container-1-5/tree-shaking-shared-server-mode/rspack.config.js index 78fae988a34e..08bea5e46ae8 100644 --- a/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/rspack.config.js +++ b/tests/rspack-test/configCases/container-1-5/tree-shaking-shared-server-mode/rspack.config.js @@ -20,12 +20,12 @@ module.exports = { target: 'async-node', plugins: [ new ModuleFederationPlugin({ - name: 'treeshake_share_server', + name: 'tree_shaking_share_server', manifest: true, filename: 'remoteEntry.js', library: { type: 'commonjs-module', - name: 'treeshake_share', + name: 'tree_shaking_share', }, exposes: { './App': './App.js', @@ -34,32 +34,32 @@ module.exports = { shared: { 'ui-lib': { requiredVersion: '*', - treeshake: { - strategy: 'server', + treeShaking: { + mode: 'server-calc', }, }, 'ui-lib-es': { requiredVersion: '*', - treeshake: { - strategy: 'server', + treeShaking: { + mode: 'server-calc', }, }, 'ui-lib-dynamic-specific-export': { requiredVersion: '*', - treeshake: { - strategy: 'server', + treeShaking: { + mode: 'server-calc', }, }, 'ui-lib-dynamic-default-export': { requiredVersion: '*', - treeshake: { - strategy: 'server', + treeShaking: { + mode: 'server-calc', }, }, 'ui-lib-side-effect': { requiredVersion: '*', - treeshake: { - strategy: 'server', + treeShaking: { + mode: 'server-calc', }, }, }, diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/runtime-plugin.js b/tests/rspack-test/configCases/container-1-5/tree-shaking-shared-server-mode/runtime-plugin.js similarity index 82% rename from tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/runtime-plugin.js rename to tests/rspack-test/configCases/container-1-5/tree-shaking-shared-server-mode/runtime-plugin.js index ab2827958f6c..af15582195be 100644 --- a/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/runtime-plugin.js +++ b/tests/rspack-test/configCases/container-1-5/tree-shaking-shared-server-mode/runtime-plugin.js @@ -1,6 +1,6 @@ // const path = require('path'); -// default strategy will use fallback asset if no server data. And the fallback will load asset via fetch + eval. +// default mode will use fallback asset if no server data. And the fallback will load asset via fetch + eval. // Cause the asset not deploy, so we need to proxy the asset to local. module.exports = function () { return { diff --git a/tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/test.config.js b/tests/rspack-test/configCases/container-1-5/tree-shaking-shared-server-mode/test.config.js similarity index 100% rename from tests/rspack-test/configCases/container-1-5/treeshake-shared-server-strategy/test.config.js rename to tests/rspack-test/configCases/container-1-5/tree-shaking-shared-server-mode/test.config.js diff --git a/tests/rspack-test/configCases/sharing/collect-share-entry-plugin/index.js b/tests/rspack-test/configCases/sharing/collect-share-entry-plugin/index.js deleted file mode 100644 index 1831496118e5..000000000000 --- a/tests/rspack-test/configCases/sharing/collect-share-entry-plugin/index.js +++ /dev/null @@ -1,14 +0,0 @@ -const fs = __non_webpack_require__("fs"); -const path = __non_webpack_require__("path"); - -it("should emit collect share entry asset with expected requests", async () => { - await import('./module'); - const assetPath = path.join(__dirname, "independent-packages/collect-shared-entries-copy.json"); - const content = JSON.parse(fs.readFileSync(assetPath, "utf-8")); - - const collectInfo = content.xreact; - expect(collectInfo).toBeDefined(); - expect(collectInfo.shareScope).toBe("default"); - expect(collectInfo.requests[0][0]).toContain("sharing/collect-share-entry-plugin/node_modules/xreact/index.js"); - expect(collectInfo.requests[0][1]).toEqual("1.0.0"); -}); diff --git a/tests/rspack-test/configCases/sharing/collect-share-entry-plugin/module.js b/tests/rspack-test/configCases/sharing/collect-share-entry-plugin/module.js deleted file mode 100644 index 70a7cb73256d..000000000000 --- a/tests/rspack-test/configCases/sharing/collect-share-entry-plugin/module.js +++ /dev/null @@ -1,3 +0,0 @@ -import "xreact"; - -export default "collect-share-entry-plugin"; diff --git a/tests/rspack-test/configCases/sharing/collect-share-entry-plugin/node_modules/xreact/index.js b/tests/rspack-test/configCases/sharing/collect-share-entry-plugin/node_modules/xreact/index.js deleted file mode 100644 index ecafa5007699..000000000000 --- a/tests/rspack-test/configCases/sharing/collect-share-entry-plugin/node_modules/xreact/index.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - default: "react-mock", - version: "1.0.0" -}; diff --git a/tests/rspack-test/configCases/sharing/collect-share-entry-plugin/node_modules/xreact/package.json b/tests/rspack-test/configCases/sharing/collect-share-entry-plugin/node_modules/xreact/package.json deleted file mode 100644 index 2b5f633e943a..000000000000 --- a/tests/rspack-test/configCases/sharing/collect-share-entry-plugin/node_modules/xreact/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "xreact", - "version": "1.0.0", - "main": "index.js" -} diff --git a/tests/rspack-test/configCases/sharing/collect-share-entry-plugin/package.json b/tests/rspack-test/configCases/sharing/collect-share-entry-plugin/package.json deleted file mode 100644 index 2f0551fad629..000000000000 --- a/tests/rspack-test/configCases/sharing/collect-share-entry-plugin/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "dependencies": { - "xreact": "1.2.3" - } -} diff --git a/tests/rspack-test/configCases/sharing/collect-share-entry-plugin/rspack.config.js b/tests/rspack-test/configCases/sharing/collect-share-entry-plugin/rspack.config.js deleted file mode 100644 index c59903ca11af..000000000000 --- a/tests/rspack-test/configCases/sharing/collect-share-entry-plugin/rspack.config.js +++ /dev/null @@ -1,39 +0,0 @@ - -const { container,sources } = require("@rspack/core"); - -/** @type {import("@rspack/core").Configuration} */ -module.exports = { - plugins: [ - new container.ModuleFederationPlugin({ - shared: { - xreact: { - import: "xreact", - shareKey: "xreact", - shareScope: "default", - version: "1.0.0", - treeshake: true - } - }, - }), - { - apply(compiler) { - compiler.hooks.thisCompilation.tap("CollectSharedEntryPlugin", (compilation) => { - compilation.hooks.processAssets.tapPromise( - { - name: "emitCollectSharedEntry", - stage: compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_SIZE - }, - async () => { - const filename = 'collect-shared-entries.json'; - const asset = compilation.getAsset(filename); - if (!asset) { - return; - } - compilation.emitAsset('collect-shared-entries-copy.json', new sources.RawSource(asset.source.source().toString())); - } - ); - }); - } - } - ] -}; diff --git a/tests/rspack-test/configCases/sharing/reshake-share/CustomPlugin.js b/tests/rspack-test/configCases/sharing/reshake-share/CustomPlugin.js new file mode 100644 index 000000000000..ea059b07e499 --- /dev/null +++ b/tests/rspack-test/configCases/sharing/reshake-share/CustomPlugin.js @@ -0,0 +1,16 @@ +class CustomPlugin { + apply(compiler) { + compiler.hooks.thisCompilation.tap('applyPlugins', (compilation) => { + compilation.hooks.processAssets.tapPromise( + { + name: 'applyPlugins', + }, + async () => { + compilation.emitAsset('apply-plugin.json', new compilation.compiler.rspack.sources.RawSource(JSON.stringify({ + reShake: true + }))) + }) + }) + } +} +module.exports = CustomPlugin; \ No newline at end of file diff --git a/tests/rspack-test/configCases/sharing/reshake-share/index.js b/tests/rspack-test/configCases/sharing/reshake-share/index.js index 0886a3c49d60..87c399c8a755 100644 --- a/tests/rspack-test/configCases/sharing/reshake-share/index.js +++ b/tests/rspack-test/configCases/sharing/reshake-share/index.js @@ -1,28 +1,33 @@ +import shared_0 from 'ui-lib'; +import shared_1 from 'ui-lib-dep'; + const fs = __non_webpack_require__("fs"); const path = __non_webpack_require__("path"); +__webpack_require__.p = 'PUBLIC_PATH'; -const treeshakeSharedDir = path.join( +const treeShakingSharedDir = path.join( __dirname, "independent-packages" ); -const customPluginAssetPath = path.join( - treeshakeSharedDir, - "apply-plugin.json" -); - const uiLibShareContainerPath = path.join( - treeshakeSharedDir, + treeShakingSharedDir, "ui_lib/1.0.0", "share-entry.js" ); const uiLibDepShareContainerPath = path.join( - treeshakeSharedDir, + treeShakingSharedDir, "ui_lib_dep/1.0.0", "share-entry.js" ); +const customPluginAssetPath = path.join( + uiLibDepShareContainerPath, + '../..', + "apply-plugin.json" +); + it("should build independent share file", () => { expect(fs.existsSync(uiLibShareContainerPath)).toBe(true); @@ -37,7 +42,8 @@ it("reshake share container should only have specify usedExports", async () => { return 'call init' } }); - const shareModules = await uiLibDepShareContainerModule.get(); + const shareModulesGetter = await uiLibDepShareContainerModule.get(); + const shareModules = shareModulesGetter(); expect(shareModules.Message).toBe('Message'); expect(shareModules.Text).not.toBeDefined(); }); @@ -55,7 +61,8 @@ it("correct handle share dep while reshake", async () => { return 'call init' } }); - const shareModules = await uiLibShareContainerModule.get(); + const shareModulesGetter = await uiLibShareContainerModule.get(); + const shareModules = shareModulesGetter(); expect(shareModules.Badge).toBe('Badge'); expect(shareModules.MessagePro).toBe('MessagePro'); }); diff --git a/tests/rspack-test/configCases/sharing/reshake-share/node_modules/ui-lib-dep/index.js b/tests/rspack-test/configCases/sharing/reshake-share/node_modules/ui-lib-dep/index.js index c6939e2c6206..996b135f366f 100644 --- a/tests/rspack-test/configCases/sharing/reshake-share/node_modules/ui-lib-dep/index.js +++ b/tests/rspack-test/configCases/sharing/reshake-share/node_modules/ui-lib-dep/index.js @@ -1,9 +1,3 @@ export const Message = 'Message'; export const Spin = 'Spin' export const Text = 'Text' - -export default { - Message, - Spin, - Text -} diff --git a/tests/rspack-test/configCases/sharing/reshake-share/node_modules/ui-lib/index.js b/tests/rspack-test/configCases/sharing/reshake-share/node_modules/ui-lib/index.js index c158056185a4..29f02fec6588 100644 --- a/tests/rspack-test/configCases/sharing/reshake-share/node_modules/ui-lib/index.js +++ b/tests/rspack-test/configCases/sharing/reshake-share/node_modules/ui-lib/index.js @@ -1,4 +1,4 @@ -import {Message,Spin} from 'ui-lib-dep'; +import { Message, Spin } from 'ui-lib-dep'; export const Button = 'Button'; export const List = 'List' @@ -6,11 +6,3 @@ export const Badge = 'Badge' export const MessagePro = `${Message}Pro`; export const SpinPro = `${Spin}Pro`; - -export default { - Button, - List, - Badge, - MessagePro, - SpinPro -} diff --git a/tests/rspack-test/configCases/sharing/reshake-share/rspack.config.js b/tests/rspack-test/configCases/sharing/reshake-share/rspack.config.js index 685193bb83ce..2da9224482b6 100644 --- a/tests/rspack-test/configCases/sharing/reshake-share/rspack.config.js +++ b/tests/rspack-test/configCases/sharing/reshake-share/rspack.config.js @@ -1,10 +1,11 @@ -const { TreeShakeSharedPlugin } = require("@rspack/core").sharing; +const { TreeShakingSharedPlugin } = require("@rspack/core").sharing; +const path = require("path"); /** @type {import("@rspack/core").Configuration} */ module.exports = { // entry:'./index.js', optimization: { - // minimize:false, + minimize: true, chunkIds: "named", moduleIds: "named" }, @@ -12,25 +13,8 @@ module.exports = { chunkFilename: "[id].js" }, plugins: [ - new TreeShakeSharedPlugin({ + new TreeShakingSharedPlugin({ reShake: true, - plugins: [ - { - apply(compiler) { - compiler.hooks.thisCompilation.tap('applyPlugins', (compilation) => { - compilation.hooks.processAssets.tapPromise( - { - name: 'applyPlugins', - }, - async () => { - compilation.emitAsset('apply-plugin.json', new compilation.compiler.rspack.sources.RawSource(JSON.stringify({ - reShake: true - }))) - }) - }) - } - } - ], mfConfig: { name: 'reshake_share', library: { @@ -38,17 +22,23 @@ module.exports = { }, shared: { 'ui-lib': { - treeshake: true, - requiredVersion: '*', - usedExports:['Badge','MessagePro'] + version:'1.0.0', + treeShaking: { + mode:'runtime-infer', + usedExports:['Badge','MessagePro'] + }, + requiredVersion: '^1.0.0', }, 'ui-lib-dep': { - treeshake: true, - requiredVersion: '*', - usedExports:['Message'] + version:'1.0.0', + treeShaking: { + mode:'runtime-infer', + usedExports:['Message'] + }, + requiredVersion: '^1.0.0', } }, - + treeShakingSharedPlugins:[path.resolve(__dirname, './CustomPlugin.js')] } }) ] diff --git a/tests/rspack-test/configCases/sharing/tree-shaking-shared/App.js b/tests/rspack-test/configCases/sharing/tree-shaking-shared/App.js new file mode 100644 index 000000000000..229f97c61803 --- /dev/null +++ b/tests/rspack-test/configCases/sharing/tree-shaking-shared/App.js @@ -0,0 +1,23 @@ +import UiLib from 'ui-lib'; +import { Button } from 'ui-lib-es'; + +export default () => { + return `default Uilib has ${Object.keys(UiLib).join( + ', ', + )} exports not tree shaking, and ui-lib-es Button value is ${Button} should tree shaking`; +}; + +export const dynamicUISpecificExport = async () => { + const { List } = await import('ui-lib-dynamic-specific-export'); + return `dynamic Uilib has ${List} exports not tree shaking`; +}; + +export const dynamicUIDefaultExport = async () => { + const uiLib = await import('ui-lib-dynamic-default-export'); + return `dynamic Uilib has ${uiLib.List} exports not tree shaking`; +}; + +export const dynamicUISideEffectExport = async () => { + const uiLibSideEffect = await import('ui-lib-side-effect'); + return `dynamic Uilib has ${uiLibSideEffect.List} exports not tree shaking`; +}; diff --git a/tests/rspack-test/configCases/sharing/tree-shaking-shared/index.js b/tests/rspack-test/configCases/sharing/tree-shaking-shared/index.js new file mode 100644 index 000000000000..147f5db16058 --- /dev/null +++ b/tests/rspack-test/configCases/sharing/tree-shaking-shared/index.js @@ -0,0 +1,122 @@ +const fs = __non_webpack_require__('fs'); +const path = __non_webpack_require__('path'); + +__webpack_require__.p = 'PUBLIC_PATH'; +it('should load tree shaking shared via set "runtime-infer" mode', async () => { + const app = await import('./App.js'); + expect(app.default()).toEqual( + 'default Uilib has Button, List, Badge exports not tree shaking, and ui-lib-es Button value is Button should tree shaking', + ); + + const bundlePath = path.join(__dirname, 'node_modules_ui-lib_index_js.js'); + const bundleContent = fs.readFileSync(bundlePath, 'utf-8'); + expect(bundleContent).toContain('Button'); + expect(bundleContent).toContain('Badge'); + expect(bundleContent).toContain('List'); + + const uiLibShared = + __FEDERATION__.__SHARE__['tree_shaking_share'].default['ui-lib'][ + '1.0.0' + ]; + expect(uiLibShared.loaded).toEqual(undefined); + expect(uiLibShared.treeShaking.loaded).toEqual(true); + expect(Object.keys(uiLibShared.treeShaking.lib()).sort()).toEqual([ + 'Button', + 'default', + ]); + + const uiLibFallback = (await uiLibShared.get())(); + expect(Object.keys(uiLibFallback).sort()).toEqual([ + 'Badge', + 'Button', + 'List', + 'default', + ]); + + const uiLibESBundlePath = path.join( + __dirname, + 'node_modules_ui-lib-es_index_js.js', + ); + const uiLibESBundleContent = fs.readFileSync(uiLibESBundlePath, 'utf-8'); + expect(uiLibESBundleContent).toContain('Button'); + expect(uiLibESBundleContent).not.toContain('Badge'); + expect(uiLibESBundleContent).not.toContain('List'); + + const uiLibESShared = + __FEDERATION__.__SHARE__['tree_shaking_share'].default['ui-lib-es'][ + '1.0.0' + ]; + expect(uiLibESShared.loaded).toEqual(undefined); + expect(uiLibESShared.treeShaking.loaded).toEqual(true); + + expect(Object.keys(uiLibESShared.treeShaking.lib()).sort()).toEqual(['Button']); + + const esFallback = (await uiLibESShared.get())(); + expect(Object.keys(esFallback).sort()).toEqual(['Badge', 'Button', 'List']); +}); + +it('should tree shaking ui-lib-dynamic-specific-export correctly', async () => { + const { dynamicUISpecificExport } = await import('./App.js'); + expect(await dynamicUISpecificExport()).toEqual( + 'dynamic Uilib has List exports not tree shaking', + ); + + const bundlePath = path.join( + __dirname, + 'node_modules_ui-lib-dynamic-specific-export_index_js.js', + ); + const bundleContent = fs.readFileSync(bundlePath, 'utf-8'); + expect(bundleContent).toContain('List'); + expect(bundleContent).not.toContain('Button'); + expect(bundleContent).not.toContain('Badge'); +}); + +it('should not tree shaking ui-lib-dynamic-default-export', async () => { + const { dynamicUIDefaultExport } = await import('./App.js'); + expect(await dynamicUIDefaultExport()).toEqual( + 'dynamic Uilib has List exports not tree shaking', + ); + + const bundlePath = path.join( + __dirname, + 'node_modules_ui-lib-dynamic-default-export_index_js.js', + ); + const bundleContent = fs.readFileSync(bundlePath, 'utf-8'); + expect(bundleContent).toContain('List'); +}); + +it('should not tree shaking ui-lib-side-effect if not set sideEffect:false ', async () => { + const { dynamicUISideEffectExport } = await import('./App.js'); + expect(await dynamicUISideEffectExport()).toEqual( + 'dynamic Uilib has List exports not tree shaking', + ); + + const bundlePath = path.join( + __dirname, + 'node_modules_ui-lib-side-effect_index_js.js', + ); + const bundleContent = fs.readFileSync(bundlePath, 'utf-8'); + expect(bundleContent).toContain('List'); + expect(bundleContent).toContain('Button'); + expect(bundleContent).toContain('Badge'); +}); + +it('should inject usedExports into entry chunk by default', async () => { + expect(__webpack_require__.federation.usedExports['ui-lib'].sort()).toEqual([ + 'Button', + 'default', + ]); +}); + +it('should inject usedExports into manifest and stats if enable manifest', async () => { + const { Button } = await import('ui-lib'); + expect(Button).toEqual('Button'); + + const statsPath = path.join(__dirname, 'mf-stats.json'); + const statsContent = JSON.parse(fs.readFileSync(statsPath, 'utf-8')); + expect( + JSON.stringify( + statsContent.shared.find((s) => s.name === 'ui-lib').usedExports.sort(), + ), + ).toEqual(JSON.stringify(['Button', 'default'])); +}); diff --git a/tests/rspack-test/configCases/sharing/treeshake-share/node_modules/ui-lib/index.js b/tests/rspack-test/configCases/sharing/tree-shaking-shared/node_modules/ui-lib-dynamic-default-export/index.js similarity index 100% rename from tests/rspack-test/configCases/sharing/treeshake-share/node_modules/ui-lib/index.js rename to tests/rspack-test/configCases/sharing/tree-shaking-shared/node_modules/ui-lib-dynamic-default-export/index.js diff --git a/tests/rspack-test/configCases/sharing/tree-shaking-shared/node_modules/ui-lib-dynamic-default-export/package.json b/tests/rspack-test/configCases/sharing/tree-shaking-shared/node_modules/ui-lib-dynamic-default-export/package.json new file mode 100644 index 000000000000..34effdfca837 --- /dev/null +++ b/tests/rspack-test/configCases/sharing/tree-shaking-shared/node_modules/ui-lib-dynamic-default-export/package.json @@ -0,0 +1,6 @@ +{ + "name": "ui-lib-dynamic-default-export", + "main": "./index.js", + "version": "1.0.0", + "sideEffects": false +} diff --git a/tests/rspack-test/configCases/sharing/tree-shaking-shared/node_modules/ui-lib-dynamic-specific-export/index.js b/tests/rspack-test/configCases/sharing/tree-shaking-shared/node_modules/ui-lib-dynamic-specific-export/index.js new file mode 100644 index 000000000000..6d4fe4c20ea5 --- /dev/null +++ b/tests/rspack-test/configCases/sharing/tree-shaking-shared/node_modules/ui-lib-dynamic-specific-export/index.js @@ -0,0 +1,3 @@ +export const Button = 'Button'; +export const List = 'List' +export const Badge = 'Badge' diff --git a/tests/rspack-test/configCases/sharing/tree-shaking-shared/node_modules/ui-lib-dynamic-specific-export/package.json b/tests/rspack-test/configCases/sharing/tree-shaking-shared/node_modules/ui-lib-dynamic-specific-export/package.json new file mode 100644 index 000000000000..e1e4830eb438 --- /dev/null +++ b/tests/rspack-test/configCases/sharing/tree-shaking-shared/node_modules/ui-lib-dynamic-specific-export/package.json @@ -0,0 +1,6 @@ +{ + "name": "ui-lib-dynamic-specific-export", + "main": "./index.js", + "version": "1.0.0", + "sideEffects": false +} diff --git a/tests/rspack-test/configCases/sharing/tree-shaking-shared/node_modules/ui-lib-es/index.js b/tests/rspack-test/configCases/sharing/tree-shaking-shared/node_modules/ui-lib-es/index.js new file mode 100644 index 000000000000..6d4fe4c20ea5 --- /dev/null +++ b/tests/rspack-test/configCases/sharing/tree-shaking-shared/node_modules/ui-lib-es/index.js @@ -0,0 +1,3 @@ +export const Button = 'Button'; +export const List = 'List' +export const Badge = 'Badge' diff --git a/tests/rspack-test/configCases/sharing/treeshake-share/node_modules/ui-lib2/package.json b/tests/rspack-test/configCases/sharing/tree-shaking-shared/node_modules/ui-lib-es/package.json similarity index 76% rename from tests/rspack-test/configCases/sharing/treeshake-share/node_modules/ui-lib2/package.json rename to tests/rspack-test/configCases/sharing/tree-shaking-shared/node_modules/ui-lib-es/package.json index 1299fb07efbe..4e05f3fb8558 100644 --- a/tests/rspack-test/configCases/sharing/treeshake-share/node_modules/ui-lib2/package.json +++ b/tests/rspack-test/configCases/sharing/tree-shaking-shared/node_modules/ui-lib-es/package.json @@ -1,5 +1,5 @@ { - "name": "ui-lib2", + "name": "ui-lib-es", "main": "./index.js", "version": "1.0.0", "sideEffects": false diff --git a/tests/rspack-test/configCases/sharing/treeshake-share/node_modules/ui-lib-side-effect/index.js b/tests/rspack-test/configCases/sharing/tree-shaking-shared/node_modules/ui-lib-side-effect/index.js similarity index 100% rename from tests/rspack-test/configCases/sharing/treeshake-share/node_modules/ui-lib-side-effect/index.js rename to tests/rspack-test/configCases/sharing/tree-shaking-shared/node_modules/ui-lib-side-effect/index.js diff --git a/tests/rspack-test/configCases/sharing/treeshake-share/node_modules/ui-lib-side-effect/package.json b/tests/rspack-test/configCases/sharing/tree-shaking-shared/node_modules/ui-lib-side-effect/package.json similarity index 100% rename from tests/rspack-test/configCases/sharing/treeshake-share/node_modules/ui-lib-side-effect/package.json rename to tests/rspack-test/configCases/sharing/tree-shaking-shared/node_modules/ui-lib-side-effect/package.json diff --git a/tests/rspack-test/configCases/sharing/treeshake-share/node_modules/ui-lib2/index.js b/tests/rspack-test/configCases/sharing/tree-shaking-shared/node_modules/ui-lib/index.js similarity index 100% rename from tests/rspack-test/configCases/sharing/treeshake-share/node_modules/ui-lib2/index.js rename to tests/rspack-test/configCases/sharing/tree-shaking-shared/node_modules/ui-lib/index.js diff --git a/tests/rspack-test/configCases/sharing/treeshake-share/node_modules/ui-lib/package.json b/tests/rspack-test/configCases/sharing/tree-shaking-shared/node_modules/ui-lib/package.json similarity index 100% rename from tests/rspack-test/configCases/sharing/treeshake-share/node_modules/ui-lib/package.json rename to tests/rspack-test/configCases/sharing/tree-shaking-shared/node_modules/ui-lib/package.json diff --git a/tests/rspack-test/configCases/sharing/tree-shaking-shared/rspack.config.js b/tests/rspack-test/configCases/sharing/tree-shaking-shared/rspack.config.js new file mode 100644 index 000000000000..8aae02817a36 --- /dev/null +++ b/tests/rspack-test/configCases/sharing/tree-shaking-shared/rspack.config.js @@ -0,0 +1,59 @@ +const { container } = require("@rspack/core"); + +const { ModuleFederationPlugin } = container; + +/** @type {import("@rspack/core").Configuration} */ +module.exports = { + target:'async-node', + optimization:{ + minimize: true, + chunkIds:'named', + moduleIds: 'named' + }, + output: { + chunkFilename: "[id].js" + }, + plugins: [ + new ModuleFederationPlugin({ + name:'tree_shaking_share', + manifest: true, + runtimePlugins: [require.resolve('./runtime-plugin.js')], + library: { + type: 'commonjs-module', + name: 'tree_shaking_share', + }, + shared: { + 'ui-lib': { + requiredVersion: '*', + treeShaking: { + mode: 'runtime-infer', + }, + }, + 'ui-lib-es': { + requiredVersion: '*', + treeShaking: { + mode: 'runtime-infer', + }, + }, + 'ui-lib-dynamic-specific-export': { + requiredVersion: '*', + treeShaking: { + mode: 'runtime-infer', + }, + }, + 'ui-lib-dynamic-default-export': { + requiredVersion: '*', + treeShaking: { + mode: 'runtime-infer', + }, + }, + 'ui-lib-side-effect': { + requiredVersion: '*', + treeShaking: { + mode: 'runtime-infer', + }, + }, + }, + }) + ] +}; diff --git a/tests/rspack-test/configCases/sharing/tree-shaking-shared/runtime-plugin.js b/tests/rspack-test/configCases/sharing/tree-shaking-shared/runtime-plugin.js new file mode 100644 index 000000000000..af15582195be --- /dev/null +++ b/tests/rspack-test/configCases/sharing/tree-shaking-shared/runtime-plugin.js @@ -0,0 +1,18 @@ +// const path = require('path'); + +// default mode will use fallback asset if no server data. And the fallback will load asset via fetch + eval. +// Cause the asset not deploy, so we need to proxy the asset to local. +module.exports = function () { + return { + name: 'proxy-shared-asset', + loadEntry: ({ remoteInfo }) => { + const { entry, entryGlobalName } = remoteInfo; + if (entry.includes('PUBLIC_PATH')) { + const relativePath = entry.replace('PUBLIC_PATH', './'); + globalThis[entryGlobalName] = + __non_webpack_require__(relativePath)[entryGlobalName]; + return globalThis[entryGlobalName]; + } + }, + }; +}; diff --git a/tests/rspack-test/configCases/sharing/treeshake-share/index.js b/tests/rspack-test/configCases/sharing/treeshake-share/index.js deleted file mode 100644 index c65b698326b3..000000000000 --- a/tests/rspack-test/configCases/sharing/treeshake-share/index.js +++ /dev/null @@ -1,74 +0,0 @@ -const fs = __non_webpack_require__("fs"); -const path = __non_webpack_require__("path"); - -it("should treeshake ui-lib correctly", async () => { - const { Button } = await import("ui-lib"); - expect(Button).toEqual('Button'); - - const bundlePath = path.join( - __dirname, - "node_modules_ui-lib_index_js.js" - ); - const bundleContent = fs.readFileSync(bundlePath, "utf-8"); - expect(bundleContent).toContain("Button"); - expect(bundleContent).not.toContain("List"); -}); - -it("should treeshake ui-lib2 correctly", async () => { - const uiLib2 = await import("ui-lib2"); - expect(uiLib2.List).toEqual('List'); - - const bundlePath = path.join( - __dirname, - "node_modules_ui-lib2_index_js.js" - ); - const bundleContent = fs.readFileSync(bundlePath, "utf-8"); - expect(bundleContent).toContain("List"); - expect(bundleContent).not.toContain("Button"); - expect(bundleContent).not.toContain("Badge"); -}); - -it("should not treeshake ui-lib-side-effect if not set sideEffect:false ", async () => { - const uiLibSideEffect = await import("ui-lib-side-effect"); - expect(uiLibSideEffect.List).toEqual('List'); - - const bundlePath = path.join( - __dirname, - "node_modules_ui-lib-side-effect_index_js.js" - ); - const bundleContent = fs.readFileSync(bundlePath, "utf-8"); - expect(bundleContent).toContain("List"); - expect(bundleContent).toContain("Button"); - expect(bundleContent).toContain("Badge"); -}); - -it("should inject usedExports into entry chunk by default", async () => { - expect(__webpack_require__.federation.usedExports['ui-lib']['main'].sort()).toEqual([ 'Badge', 'Button' ]) -}); - -it("should inject usedExports into manifest and stats if enable manifest", async () => { - const { Button } = await import("ui-lib"); - expect(Button).toEqual('Button'); - - const manifestPath = path.join( - __dirname, - "mf-manifest.json" - ); - const manifestContent = JSON.parse(fs.readFileSync(manifestPath, "utf-8")); - expect(JSON.stringify(manifestContent.shared.find(s=>s.name === 'ui-lib').usedExports.sort())).toEqual(JSON.stringify([ - "Badge", - "Button" - ])); - - const statsPath = path.join( - __dirname, - "mf-stats.json" - ); - const statsContent = JSON.parse(fs.readFileSync(statsPath, "utf-8")); - expect(JSON.stringify(statsContent.shared.find(s=>s.name === 'ui-lib').usedExports.sort())).toEqual(JSON.stringify([ - "Badge", - "Button" - ])); -}); - -// it("should ") diff --git a/tests/rspack-test/configCases/sharing/treeshake-share/rspack.config.js b/tests/rspack-test/configCases/sharing/treeshake-share/rspack.config.js deleted file mode 100644 index deba8c91a473..000000000000 --- a/tests/rspack-test/configCases/sharing/treeshake-share/rspack.config.js +++ /dev/null @@ -1,36 +0,0 @@ -const { container } = require("@rspack/core"); - -const { ModuleFederationPlugin } = container; - -/** @type {import("@rspack/core").Configuration} */ -module.exports = { - optimization:{ - minimize: false, - chunkIds:'named', - moduleIds: 'named' - }, - output: { - chunkFilename: "[id].js" - }, - plugins: [ - new ModuleFederationPlugin({ - name:'treeshake_share', - manifest: true, - shared: { - 'ui-lib': { - requiredVersion:'*', - treeshake:true, - usedExports: ['Badge'] - }, - 'ui-lib2': { - requiredVersion:'*', - treeshake:true, - }, - 'ui-lib-side-effect': { - requiredVersion:'*', - treeshake:true, - } - } - }) - ] -}; diff --git a/tests/rspack-test/configCases/sri/mf/rspack.config.js b/tests/rspack-test/configCases/sri/mf/rspack.config.js index aaea5d7779d8..659ea28b29ed 100644 --- a/tests/rspack-test/configCases/sri/mf/rspack.config.js +++ b/tests/rspack-test/configCases/sri/mf/rspack.config.js @@ -5,6 +5,9 @@ module.exports = { optimization: { moduleIds: "named" }, + performance: { + hints: false + }, plugins: [ new SubresourceIntegrityPlugin(), new container.ModuleFederationPlugin({ diff --git a/tests/rspack-test/hotCases/sharing/share-plugin/__snapshots__/web/1.snap.txt b/tests/rspack-test/hotCases/sharing/share-plugin/__snapshots__/web/1.snap.txt index 702633a21734..4f512e4029c8 100644 --- a/tests/rspack-test/hotCases/sharing/share-plugin/__snapshots__/web/1.snap.txt +++ b/tests/rspack-test/hotCases/sharing/share-plugin/__snapshots__/web/1.snap.txt @@ -7,7 +7,7 @@ - Bundle: bundle.js - Bundle: common_js_2.chunk.CURRENT_HASH.js - Manifest: main.LAST_HASH.hot-update.json, size: 28 -- Update: main.LAST_HASH.hot-update.js, size: 42292 +- Update: main.LAST_HASH.hot-update.js, size: 42338 ## Manifest @@ -101,7 +101,7 @@ __webpack_require__.h = () => ("CURRENT_HASH") // webpack/runtime/consumes_loading (() => { -__webpack_require__.consumesLoadingData = { chunkMapping: {"main":["webpack/sharing/consume/default/common/./common?1"],"webpack_sharing_consume_default_common2_common_2":["webpack/sharing/consume/default/common2/./common?2"]}, moduleIdToConsumeDataMapping: {"webpack/sharing/consume/default/common2/./common?2": { shareScope: "default", shareKey: "common2", import: "./common?2", requiredVersion: "1.1.1", strictVersion: true, singleton: false, eager: false, fallback: () => (__webpack_require__.e("common_js_2").then(() => (() => (__webpack_require__("./common.js?2"))))) }, "webpack/sharing/consume/default/common/./common?1": { shareScope: "default", shareKey: "common", import: "./common?1", requiredVersion: "1.1.1", strictVersion: true, singleton: false, eager: true, fallback: () => (() => (__webpack_require__("./common.js?1"))) }}, initialConsumes: ["webpack/sharing/consume/default/common/./common?1"] }; +__webpack_require__.consumesLoadingData = { chunkMapping: {"main":["webpack/sharing/consume/default/common/./common?1"],"webpack_sharing_consume_default_common2_common_2":["webpack/sharing/consume/default/common2/./common?2"]}, moduleIdToConsumeDataMapping: {"webpack/sharing/consume/default/common2/./common?2": { shareScope: "default", shareKey: "common2", import: "./common?2", requiredVersion: "1.1.1", strictVersion: true, singleton: false, eager: false, fallback: () => (__webpack_require__.e("common_js_2").then(() => (() => (__webpack_require__("./common.js?2"))))), treeShakingMode: null }, "webpack/sharing/consume/default/common/./common?1": { shareScope: "default", shareKey: "common", import: "./common?1", requiredVersion: "1.1.1", strictVersion: true, singleton: false, eager: true, fallback: () => (() => (__webpack_require__("./common.js?1"))), treeShakingMode: null }}, initialConsumes: ["webpack/sharing/consume/default/common/./common?1"] }; var splitAndConvert = function(str) { return str.split(".").map(function(item) { return +item == item ? +item : item; diff --git a/website/docs/en/plugins/webpack/tree-shake-shared-plugin.mdx b/website/docs/en/plugins/webpack/tree-shake-shared-plugin.mdx index a2be9b12ba07..8b1145ca57af 100644 --- a/website/docs/en/plugins/webpack/tree-shake-shared-plugin.mdx +++ b/website/docs/en/plugins/webpack/tree-shake-shared-plugin.mdx @@ -1,6 +1,6 @@ import { Stability, ApiMeta } from '@components/ApiMeta'; -# TreeShakeSharedPlugin +# TreeShakingSharedPlugin @@ -18,16 +18,16 @@ import { Stability, ApiMeta } from '@components/ApiMeta'; ```js // rspack.config.js -const { TreeShakeSharedPlugin } = require('@rspack/core'); +const { TreeShakingSharedPlugin } = require('@rspack/core'); module.exports = { plugins: [ - new TreeShakeSharedPlugin({ + new TreeShakingSharedPlugin({ reShake: true, mfConfig: { name: 'app', shared: { - 'lodash-es': { treeshake: true }, + 'lodash-es': { treeShaking: { mode: 'server-calc' } }, }, library: { type: 'var', name: 'App' }, manifest: true, @@ -42,4 +42,4 @@ module.exports = { - Normalizes `shared` into `[shareName, SharedConfig][]`. - Registers `SharedUsedExportsOptimizerPlugin` when `reShake` is `false` to inject used-exports from the stats manifest. -- Triggers independent compilation for shared entries with `treeshake: true`, and writes the produced assets back to the `stats/manifest` (fallback fields). +- Triggers independent compilation for shared entries with `tree shaking: true`, and writes the produced assets back to the `stats/manifest` (fallback fields). diff --git a/website/docs/zh/plugins/webpack/tree-shake-shared-plugin.mdx b/website/docs/zh/plugins/webpack/tree-shake-shared-plugin.mdx index ac06117fbfeb..ebb90326d966 100644 --- a/website/docs/zh/plugins/webpack/tree-shake-shared-plugin.mdx +++ b/website/docs/zh/plugins/webpack/tree-shake-shared-plugin.mdx @@ -1,6 +1,6 @@ import { Stability, ApiMeta } from '@components/ApiMeta'; -# TreeShakeSharedPlugin +# TreeShakingSharedPlugin @@ -12,22 +12,22 @@ import { Stability, ApiMeta } from '@components/ApiMeta'; - `mfConfig`:`ModuleFederationPluginOptions`,传入模块联邦插件所需要的配置项。 - `plugins`:额外插件列表,可在独立编译中复用。 -- `reShake`:是否在独立编译阶段执行二次摇树优化(二次摇树通常在部署平台确定了完整的依赖信息后重新触发的一次全新构建,提高共享依赖 treeshake 命中的准确率)。 +- `reShake`:是否在独立编译阶段执行二次摇树优化(二次摇树通常在部署平台确定了完整的依赖信息后重新触发的一次全新构建,提高共享依赖 tree shaking 命中的准确率)。 **使用示例** ```js // rspack.config.js -const { TreeShakeSharedPlugin } = require('@rspack/core'); +const { TreeShakingSharedPlugin } = require('@rspack/core'); module.exports = { plugins: [ - new TreeShakeSharedPlugin({ + new TreeShakingSharedPlugin({ reShake: true, mfConfig: { name: 'app', shared: { - 'lodash-es': { treeshake: true }, + 'lodash-es': { treeShaking: true }, }, library: { type: 'var', name: 'App' }, manifest: true, @@ -42,4 +42,4 @@ module.exports = { - 读取 `shared` 配置后标准化为 `[shareName, SharedConfig][]`。 - 当 `reShake` 为 `false` 时,注册 `SharedUsedExportsOptimizerPlugin`,基于 stats 清单注入已用导出集合。 -- 对 `treeshake` 的共享包触发独立编译,产出回写到 stats/manifest 中的 fallback 字段。 +- 对 `tree shaking` 的共享包触发独立编译,产出回写到 stats/manifest 中的 fallback 字段。 From b21d2ec24029d6d75dbb361988308845b07142c3 Mon Sep 17 00:00:00 2001 From: harpsealjs Date: Mon, 12 Jan 2026 17:38:29 +0800 Subject: [PATCH 39/87] revert: "feat: add warning when requireAlias is disabled" (#12702) Revert "feat: add warning when requireAlias is disabled (#12700)" This reverts commit eb5635c6f248853df96245c9d0a710340e41d6ae. --- .../src/parser_plugin/amd/amd_plugin.rs | 7 +------ .../common_js_imports_parse_plugin.rs | 16 ++-------------- .../src/parser_plugin/define_plugin/parser.rs | 2 +- .../src/parser_plugin/drive.rs | 4 ++-- .../src/parser_plugin/provide_plugin/parser.rs | 4 ++-- .../src/parser_plugin/trait.rs | 2 +- .../src/parser_plugin/url_plugin.rs | 7 +------ .../src/visitors/dependency/parser/walk.rs | 10 +++------- .../parsing/renaming-disabled/warnings.js | 4 ---- 9 files changed, 13 insertions(+), 43 deletions(-) delete mode 100644 tests/rspack-test/configCases/parsing/renaming-disabled/warnings.js diff --git a/crates/rspack_plugin_javascript/src/parser_plugin/amd/amd_plugin.rs b/crates/rspack_plugin_javascript/src/parser_plugin/amd/amd_plugin.rs index 27ea6b959b5a..fbe83a8ab2c2 100644 --- a/crates/rspack_plugin_javascript/src/parser_plugin/amd/amd_plugin.rs +++ b/crates/rspack_plugin_javascript/src/parser_plugin/amd/amd_plugin.rs @@ -184,12 +184,7 @@ impl JavascriptParserPlugin for AMDParserPlugin { None } - fn can_rename( - &self, - _parser: &mut JavascriptParser, - _expr: &Expr, - for_name: &str, - ) -> Option { + fn can_rename(&self, _parser: &mut JavascriptParser, for_name: &str) -> Option { if for_name == DEFINE { return Some(true); } diff --git a/crates/rspack_plugin_javascript/src/parser_plugin/common_js_imports_parse_plugin.rs b/crates/rspack_plugin_javascript/src/parser_plugin/common_js_imports_parse_plugin.rs index e03a48abf5c7..2102bb8ad4f4 100644 --- a/crates/rspack_plugin_javascript/src/parser_plugin/common_js_imports_parse_plugin.rs +++ b/crates/rspack_plugin_javascript/src/parser_plugin/common_js_imports_parse_plugin.rs @@ -402,21 +402,9 @@ impl CommonJsImportsParserPlugin { } impl JavascriptParserPlugin for CommonJsImportsParserPlugin { - fn can_rename(&self, parser: &mut JavascriptParser, expr: &Expr, for_name: &str) -> Option { + fn can_rename(&self, parser: &mut JavascriptParser, for_name: &str) -> Option { if for_name == expr_name::REQUIRE { - let require_alias = parser.javascript_options.require_alias.unwrap_or(true); - if !require_alias { - let mut warning = create_traceable_error( - "Critical dependency".into(), - "please enable 'module.parser.javascript.requireAlias' to analyze require alias" - .to_string(), - parser.source.to_owned(), - expr.span().into(), - ); - warning.severity = Severity::Warning; - parser.add_warning(warning.into()); - } - Some(require_alias) + Some(parser.javascript_options.require_alias.unwrap_or(true)) } else { None } diff --git a/crates/rspack_plugin_javascript/src/parser_plugin/define_plugin/parser.rs b/crates/rspack_plugin_javascript/src/parser_plugin/define_plugin/parser.rs index 6ec6ad017eb0..2a330a5cceee 100644 --- a/crates/rspack_plugin_javascript/src/parser_plugin/define_plugin/parser.rs +++ b/crates/rspack_plugin_javascript/src/parser_plugin/define_plugin/parser.rs @@ -52,7 +52,7 @@ impl DefineParserPlugin { } impl JavascriptParserPlugin for DefineParserPlugin { - fn can_rename(&self, parser: &mut JavascriptParser, _expr: &Expr, str: &str) -> Option { + fn can_rename(&self, parser: &mut JavascriptParser, str: &str) -> Option { if let Some(first_key) = self.walk_data.can_rename.get(str) { self.add_value_dependency(parser, str); if let Some(first_key) = first_key diff --git a/crates/rspack_plugin_javascript/src/parser_plugin/drive.rs b/crates/rspack_plugin_javascript/src/parser_plugin/drive.rs index 4420badb42c6..2424925e32eb 100644 --- a/crates/rspack_plugin_javascript/src/parser_plugin/drive.rs +++ b/crates/rspack_plugin_javascript/src/parser_plugin/drive.rs @@ -579,9 +579,9 @@ impl JavascriptParserPlugin for JavaScriptParserPluginDrive { None } - fn can_rename(&self, parser: &mut JavascriptParser, expr: &Expr, str: &str) -> Option { + fn can_rename(&self, parser: &mut JavascriptParser, str: &str) -> Option { for plugin in &self.plugins { - let res = plugin.can_rename(parser, expr, str); + let res = plugin.can_rename(parser, str); // `SyncBailHook` if res.is_some() { return res; diff --git a/crates/rspack_plugin_javascript/src/parser_plugin/provide_plugin/parser.rs b/crates/rspack_plugin_javascript/src/parser_plugin/provide_plugin/parser.rs index b6c82e5a7551..a65e35304492 100644 --- a/crates/rspack_plugin_javascript/src/parser_plugin/provide_plugin/parser.rs +++ b/crates/rspack_plugin_javascript/src/parser_plugin/provide_plugin/parser.rs @@ -4,7 +4,7 @@ use cow_utils::CowUtils; use itertools::Itertools; use rspack_core::DependencyRange; use rustc_hash::FxHashSet as HashSet; -use swc_core::{atoms::Atom, common::Spanned, ecma::ast::Expr}; +use swc_core::{atoms::Atom, common::Spanned}; use super::{super::JavascriptParserPlugin, ProvideValue, VALUE_DEP_PREFIX}; use crate::{dependency::ProvideDependency, visitors::JavascriptParser}; @@ -62,7 +62,7 @@ impl ProvideParserPlugin { } impl JavascriptParserPlugin for ProvideParserPlugin { - fn can_rename(&self, _parser: &mut JavascriptParser, _expr: &Expr, str: &str) -> Option { + fn can_rename(&self, _parser: &mut JavascriptParser, str: &str) -> Option { self.names.contains(str).then_some(true) } diff --git a/crates/rspack_plugin_javascript/src/parser_plugin/trait.rs b/crates/rspack_plugin_javascript/src/parser_plugin/trait.rs index b788569e7a79..e6c281f85db7 100644 --- a/crates/rspack_plugin_javascript/src/parser_plugin/trait.rs +++ b/crates/rspack_plugin_javascript/src/parser_plugin/trait.rs @@ -38,7 +38,7 @@ pub trait JavascriptParserPlugin { /// The return value will have no effect. fn top_level_for_of_await_stmt(&self, _parser: &mut JavascriptParser, _stmt: &ForOfStmt) {} - fn can_rename(&self, _parser: &mut JavascriptParser, _expr: &Expr, _str: &str) -> Option { + fn can_rename(&self, _parser: &mut JavascriptParser, _str: &str) -> Option { None } diff --git a/crates/rspack_plugin_javascript/src/parser_plugin/url_plugin.rs b/crates/rspack_plugin_javascript/src/parser_plugin/url_plugin.rs index ee8d932e37dc..70e89ff3c003 100644 --- a/crates/rspack_plugin_javascript/src/parser_plugin/url_plugin.rs +++ b/crates/rspack_plugin_javascript/src/parser_plugin/url_plugin.rs @@ -104,12 +104,7 @@ pub struct URLPlugin { } impl JavascriptParserPlugin for URLPlugin { - fn can_rename( - &self, - _parser: &mut JavascriptParser, - _expr: &Expr, - for_name: &str, - ) -> Option { + fn can_rename(&self, _parser: &mut JavascriptParser, for_name: &str) -> Option { (for_name == "URL").then_some(true) } diff --git a/crates/rspack_plugin_javascript/src/visitors/dependency/parser/walk.rs b/crates/rspack_plugin_javascript/src/visitors/dependency/parser/walk.rs index c05c4c472cc3..734f7d8ede8a 100644 --- a/crates/rspack_plugin_javascript/src/visitors/dependency/parser/walk.rs +++ b/crates/rspack_plugin_javascript/src/visitors/dependency/parser/walk.rs @@ -375,7 +375,7 @@ impl JavascriptParser<'_> { { let drive = self.plugin_drive.clone(); if drive - .can_rename(self, init, &renamed_identifier) + .can_rename(self, &renamed_identifier) .unwrap_or_default() { if !drive @@ -930,9 +930,7 @@ impl JavascriptParser<'_> { if let Some(rename_identifier) = parser.get_rename_identifier(expr) && let drive = parser.plugin_drive.clone() && rename_identifier - .call_hooks_name(parser, |this, for_name| { - drive.can_rename(this, expr, for_name) - }) + .call_hooks_name(parser, |this, for_name| drive.can_rename(this, for_name)) .unwrap_or_default() && !rename_identifier .call_hooks_name(parser, |this, for_name| drive.rename(this, expr, for_name)) @@ -1259,9 +1257,7 @@ impl JavascriptParser<'_> { if let Some(rename_identifier) = self.get_rename_identifier(&expr.right) && let drive = self.plugin_drive.clone() && rename_identifier - .call_hooks_name(self, |this, for_name| { - drive.can_rename(this, &expr.right, for_name) - }) + .call_hooks_name(self, |this, for_name| drive.can_rename(this, for_name)) .unwrap_or_default() { if !rename_identifier diff --git a/tests/rspack-test/configCases/parsing/renaming-disabled/warnings.js b/tests/rspack-test/configCases/parsing/renaming-disabled/warnings.js deleted file mode 100644 index 01ec4f489bf9..000000000000 --- a/tests/rspack-test/configCases/parsing/renaming-disabled/warnings.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = [ - [/Critical dependency: please enable 'module.parser.javascript.requireAlias' to analyze require alias/], - [/Critical dependency: please enable 'module.parser.javascript.requireAlias' to analyze require alias/] -] \ No newline at end of file From ec24006b19bdd59628ece584744935f42fd8d647 Mon Sep 17 00:00:00 2001 From: 9aoy <9aoyuao@gmail.com> Date: Mon, 12 Jan 2026 17:46:42 +0800 Subject: [PATCH 40/87] feat: use rspack-vue-loader to support Vue hot update (#12698) feat: use rspack-vue-loader to support hotupdate --- .../template-vue-js/package.json | 2 +- .../template-vue-js/rspack.config.mjs | 4 +- .../template-vue-ts/package.json | 2 +- .../template-vue-ts/rspack.config.ts | 4 +- pnpm-lock.yaml | 64 +++++++++---------- tests/e2e/cases/vue3/rspack.config.js | 4 +- tests/e2e/package.json | 2 +- website/docs/en/guide/migration/webpack.mdx | 2 +- website/docs/en/guide/tech/vue.mdx | 6 +- website/docs/zh/guide/migration/webpack.mdx | 2 +- website/docs/zh/guide/tech/vue.mdx | 6 +- 11 files changed, 46 insertions(+), 52 deletions(-) diff --git a/packages/create-rspack/template-vue-js/package.json b/packages/create-rspack/template-vue-js/package.json index d4b8f17fa061..ad213a956b8a 100644 --- a/packages/create-rspack/template-vue-js/package.json +++ b/packages/create-rspack/template-vue-js/package.json @@ -13,6 +13,6 @@ "devDependencies": { "@rspack/cli": "workspace:*", "@rspack/core": "workspace:*", - "vue-loader": "^17.4.2" + "rspack-vue-loader": "^17.4.5" } } diff --git a/packages/create-rspack/template-vue-js/rspack.config.mjs b/packages/create-rspack/template-vue-js/rspack.config.mjs index 6520a45a3169..71ddc927a469 100644 --- a/packages/create-rspack/template-vue-js/rspack.config.mjs +++ b/packages/create-rspack/template-vue-js/rspack.config.mjs @@ -1,7 +1,7 @@ // @ts-check import { defineConfig } from '@rspack/cli'; import { rspack } from '@rspack/core'; -import { VueLoaderPlugin } from 'vue-loader'; +import { VueLoaderPlugin } from 'rspack-vue-loader'; // Target browsers, see: https://github.com/browserslist/browserslist const targets = ['last 2 versions', '> 0.2%', 'not dead', 'Firefox ESR']; @@ -17,7 +17,7 @@ export default defineConfig({ rules: [ { test: /\.vue$/, - loader: 'vue-loader', + loader: 'rspack-vue-loader', options: { experimentalInlineMatchResource: true, }, diff --git a/packages/create-rspack/template-vue-ts/package.json b/packages/create-rspack/template-vue-ts/package.json index 4c8dd11137df..782d7af1ace5 100644 --- a/packages/create-rspack/template-vue-ts/package.json +++ b/packages/create-rspack/template-vue-ts/package.json @@ -14,6 +14,6 @@ "@rspack/cli": "workspace:*", "@rspack/core": "workspace:*", "typescript": "^5.9.3", - "vue-loader": "^17.4.2" + "rspack-vue-loader": "^17.4.5" } } diff --git a/packages/create-rspack/template-vue-ts/rspack.config.ts b/packages/create-rspack/template-vue-ts/rspack.config.ts index e6bca03f4594..844caa0afbc3 100644 --- a/packages/create-rspack/template-vue-ts/rspack.config.ts +++ b/packages/create-rspack/template-vue-ts/rspack.config.ts @@ -4,7 +4,7 @@ import { rspack, type SwcLoaderOptions, } from '@rspack/core'; -import { VueLoaderPlugin } from 'vue-loader'; +import { VueLoaderPlugin } from 'rspack-vue-loader'; // Target browsers, see: https://github.com/browserslist/browserslist const targets = ['last 2 versions', '> 0.2%', 'not dead', 'Firefox ESR']; @@ -20,7 +20,7 @@ export default defineConfig({ rules: [ { test: /\.vue$/, - loader: 'vue-loader', + loader: 'rspack-vue-loader', options: { experimentalInlineMatchResource: true, }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 257445961ef0..787fb12e404f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -319,9 +319,9 @@ importers: '@rspack/core': specifier: workspace:* version: link:../../rspack - vue-loader: - specifier: ^17.4.2 - version: 17.4.2(vue@3.5.26(typescript@5.9.3))(webpack@5.102.1) + rspack-vue-loader: + specifier: ^17.4.5 + version: 17.4.5(vue@3.5.26(typescript@5.9.3))(webpack@5.102.1) packages/create-rspack/template-vue-ts: dependencies: @@ -335,12 +335,12 @@ importers: '@rspack/core': specifier: workspace:* version: link:../../rspack + rspack-vue-loader: + specifier: ^17.4.5 + version: 17.4.5(vue@3.5.26(typescript@5.9.3))(webpack@5.102.1) typescript: specifier: ^5.9.3 version: 5.9.3 - vue-loader: - specifier: ^17.4.2 - version: 17.4.2(vue@3.5.26(typescript@5.9.3))(webpack@5.102.1) packages/rspack: dependencies: @@ -690,6 +690,9 @@ importers: react-refresh: specifier: ^0.18.0 version: 0.18.0 + rspack-vue-loader: + specifier: ^17.4.5 + version: 17.4.5(vue@3.5.26(typescript@5.9.3))(webpack@5.102.1) tailwindcss: specifier: ^3.4.19 version: 3.4.19(ts-node@10.9.2(@types/node@20.19.27)(typescript@5.9.3)) @@ -699,9 +702,6 @@ importers: vue: specifier: ^3.5.26 version: 3.5.26(typescript@5.9.3) - vue-loader: - specifier: ^17.4.2 - version: 17.4.2(vue@3.5.26(typescript@5.9.3))(webpack@5.102.1) ws: specifier: ^8.18.3 version: 8.18.3 @@ -5772,9 +5772,6 @@ packages: resolution: {integrity: sha512-Bb33KbowVTIj5s7Ked1OsqHUeCpz//tPwR+E2zJgJKo9Z5XolZ9b6bdUgjmYlwnWhoOQKoTd1TYToZGn5mAYOg==} engines: {node: '>= 0.8'} - hash-sum@2.0.0: - resolution: {integrity: sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==} - hash.js@1.1.7: resolution: {integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==} @@ -7582,6 +7579,18 @@ packages: '@rsbuild/core': optional: true + rspack-vue-loader@17.4.5: + resolution: {integrity: sha512-i88hGa4mySkwiP7HqRICIAhomcMdkNCZ5tQGcxkcUWmDfC2QfeQegFBEKY4RdbuxJ3p1Ocj/Ul6Sh4yl6L7mDg==} + peerDependencies: + '@vue/compiler-sfc': '*' + vue: '*' + webpack: ^5.0.0 + peerDependenciesMeta: + '@vue/compiler-sfc': + optional: true + vue: + optional: true + rspress-plugin-font-open-sans@1.0.3: resolution: {integrity: sha512-17i7uUqvyy5k51ggZJ5xoP9duqC2W76GcBviIu400VXXAQEZx3JzZWPcGz9gGmVaFHAkH19NtZK0EYKfneX4rw==} peerDependencies: @@ -8537,18 +8546,6 @@ packages: vscode-uri@3.1.0: resolution: {integrity: sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==} - vue-loader@17.4.2: - resolution: {integrity: sha512-yTKOA4R/VN4jqjw4y5HrynFL8AK0Z3/Jt7eOJXEitsm0GMRHDBjCfCiuTiLP7OESvsZYo2pATCWhDqxC5ZrM6w==} - peerDependencies: - '@vue/compiler-sfc': '*' - vue: '*' - webpack: ^4.1.0 || ^5.0.0-0 - peerDependenciesMeta: - '@vue/compiler-sfc': - optional: true - vue: - optional: true - vue@3.5.26: resolution: {integrity: sha512-SJ/NTccVyAoNUJmkM9KUqPcYlY+u8OVL1X5EW9RIs3ch5H2uERxyyIUI4MRxVCSOiEcupX9xNGde1tL9ZKpimA==} peerDependencies: @@ -13775,8 +13772,6 @@ snapshots: safe-buffer: 5.2.1 to-buffer: 1.2.2 - hash-sum@2.0.0: {} - hash.js@1.1.7: dependencies: inherits: 2.0.4 @@ -16096,6 +16091,14 @@ snapshots: optionalDependencies: '@rsbuild/core': 1.7.2 + rspack-vue-loader@17.4.5(vue@3.5.26(typescript@5.9.3))(webpack@5.102.1): + dependencies: + chalk: 4.1.2 + watchpack: 2.4.4 + webpack: 5.102.1 + optionalDependencies: + vue: 3.5.26(typescript@5.9.3) + rspress-plugin-font-open-sans@1.0.3(@rspress/core@2.0.0-rc.4(@types/react@19.2.7)): dependencies: '@rspress/core': 2.0.0-rc.4(@types/react@19.2.7) @@ -17084,15 +17087,6 @@ snapshots: vscode-uri@3.1.0: {} - vue-loader@17.4.2(vue@3.5.26(typescript@5.9.3))(webpack@5.102.1): - dependencies: - chalk: 4.1.2 - hash-sum: 2.0.0 - watchpack: 2.4.4 - webpack: 5.102.1 - optionalDependencies: - vue: 3.5.26(typescript@5.9.3) - vue@3.5.26(typescript@5.9.3): dependencies: '@vue/compiler-dom': 3.5.26 diff --git a/tests/e2e/cases/vue3/rspack.config.js b/tests/e2e/cases/vue3/rspack.config.js index c0ec2af72a12..1412af1a740d 100644 --- a/tests/e2e/cases/vue3/rspack.config.js +++ b/tests/e2e/cases/vue3/rspack.config.js @@ -1,5 +1,5 @@ const { DefinePlugin, HtmlRspackPlugin } = require('@rspack/core'); -const { VueLoaderPlugin } = require('vue-loader'); +const { VueLoaderPlugin } = require('rspack-vue-loader'); /** @type { import('@rspack/core').RspackOptions } */ module.exports = { @@ -26,7 +26,7 @@ module.exports = { rules: [ { test: /\.vue$/, - loader: 'vue-loader', + loader: 'rspack-vue-loader', options: { experimentalInlineMatchResource: true, }, diff --git a/tests/e2e/package.json b/tests/e2e/package.json index 91aec6b99d9e..544df3c9b94e 100644 --- a/tests/e2e/package.json +++ b/tests/e2e/package.json @@ -26,7 +26,7 @@ "typescript": "^5.9.3", "tailwindcss": "^3.4.19", "vue": "^3.5.26", - "vue-loader": "^17.4.2", + "rspack-vue-loader": "^17.4.5", "css-loader": "^7.1.2", "ws": "^8.18.3" } diff --git a/website/docs/en/guide/migration/webpack.mdx b/website/docs/en/guide/migration/webpack.mdx index 446cb84a00a3..1df5511a1651 100644 --- a/website/docs/en/guide/migration/webpack.mdx +++ b/website/docs/en/guide/migration/webpack.mdx @@ -22,7 +22,7 @@ Now you can remove the webpack-related dependencies from your project: :::tip -In some cases, you will still need to keep `webpack` as a dev dependency, such as when using [vue-loader](https://github.com/vuejs/vue-loader). +In some cases, you will still need to keep `webpack` as a dev dependency, such as when using [vue-loader](https://github.com/vuejs/vue-loader) (you can use [rspack-vue-loader](https://github.com/rstackjs/rspack-vue-loader) instead). This is because these packages directly `import` subpaths of webpack and couple with webpack. If you encounter this issue, you can provide feedback to the maintainers of these plugins, asking them if they can make `webpack` an optional dependency. ::: diff --git a/website/docs/en/guide/tech/vue.mdx b/website/docs/en/guide/tech/vue.mdx index 4a6aab6db717..7d97e57da1c1 100644 --- a/website/docs/en/guide/tech/vue.mdx +++ b/website/docs/en/guide/tech/vue.mdx @@ -11,11 +11,11 @@ Rspack provides two solutions to support Vue: ## Vue 3 -Currently, Vue 3 is supported by Rspack. Please make sure your [vue-loader](https://github.com/vuejs/vue-loader) version is >= 17.2.2 and configure as follows: +Currently, Vue 3 is supported by Rspack. Please make sure your [rspack-vue-loader](https://github.com/rstackjs/rspack-vue-loader) version is >= 17.2.2 and configure as follows: ```js title="rspack.config.mjs" import { defineConfig } from '@rspack/cli'; -import { VueLoaderPlugin } from 'vue-loader'; +import { VueLoaderPlugin } from 'rspack-vue-loader'; export default defineConfig({ plugins: [new VueLoaderPlugin()], @@ -23,7 +23,7 @@ export default defineConfig({ rules: [ { test: /\.vue$/, - loader: 'vue-loader', + loader: 'rspack-vue-loader', options: { // Note, for the majority of features to be available, make sure this option is `true` experimentalInlineMatchResource: true, diff --git a/website/docs/zh/guide/migration/webpack.mdx b/website/docs/zh/guide/migration/webpack.mdx index fc254de445a1..5e30285d0d44 100644 --- a/website/docs/zh/guide/migration/webpack.mdx +++ b/website/docs/zh/guide/migration/webpack.mdx @@ -21,7 +21,7 @@ Rspack 的配置是基于 webpack 的设计实现的,以此你能够非常轻 :::tip -在个别情况下,你仍然需要保留 `webpack` 作为开发依赖,例如使用 [vue-loader](https://github.com/vuejs/vue-loader) 时。 +在个别情况下,你仍然需要保留 `webpack` 作为开发依赖,例如使用 [vue-loader](https://github.com/vuejs/vue-loader) 时 (你可以使用 [rspack-vue-loader](https://github.com/rstackjs/rspack-vue-loader) 替代)。 这是因为这些库直接 `import` 了 webpack 的子路径,与 webpack 产生了耦合。如果你遇到了这种情况,可以向这些插件的维护者反馈,询问他们能否将 `webpack` 作为可选依赖。 ::: diff --git a/website/docs/zh/guide/tech/vue.mdx b/website/docs/zh/guide/tech/vue.mdx index 9c30bdd4cc03..e56b98d96e75 100644 --- a/website/docs/zh/guide/tech/vue.mdx +++ b/website/docs/zh/guide/tech/vue.mdx @@ -11,11 +11,11 @@ Rspack 提供两种方案来支持 Vue: ## Vue 3 -目前,Rspack 已经完成了对 Vue 3 的支持,请确保你的 [vue-loader](https://github.com/vuejs/vue-loader) 版本 >= 17.2.2,并进行如下配置: +目前,Rspack 已经完成了对 Vue 3 的支持,请确保你的 [rspack-vue-loader](https://github.com/rstackjs/rspack-vue-loader) 版本 >= 17.2.2,并进行如下配置: ```js title="rspack.config.mjs" import { defineConfig } from '@rspack/cli'; -import { VueLoaderPlugin } from 'vue-loader'; +import { VueLoaderPlugin } from 'rspack-vue-loader'; export default defineConfig({ plugins: [new VueLoaderPlugin()], @@ -23,7 +23,7 @@ export default defineConfig({ rules: [ { test: /\.vue$/, - loader: 'vue-loader', + loader: 'rspack-vue-loader', options: { // 注意,为了绝大多数功能的可用性,请确保该选项为 `true` experimentalInlineMatchResource: true, From 2fb1f1cf75141ce8d1050165156a32f4f51dd042 Mon Sep 17 00:00:00 2001 From: "zhanghang.heal" Date: Mon, 12 Jan 2026 20:30:30 +0800 Subject: [PATCH 41/87] chore: update artificat --- crates/node_binding/rspack.wasi-browser.js | 61 +++++++++++++++++++++- crates/node_binding/rspack.wasi.cjs | 61 +++++++++++++++++++++- 2 files changed, 120 insertions(+), 2 deletions(-) diff --git a/crates/node_binding/rspack.wasi-browser.js b/crates/node_binding/rspack.wasi-browser.js index ee65959b37bc..e3e5c0a99d48 100644 --- a/crates/node_binding/rspack.wasi-browser.js +++ b/crates/node_binding/rspack.wasi-browser.js @@ -63,4 +63,63 @@ const { }, }) export default __napiModule.exports - +export const Assets = __napiModule.exports.Assets +export const AsyncDependenciesBlock = __napiModule.exports.AsyncDependenciesBlock +export const Chunk = __napiModule.exports.Chunk +export const ChunkGraph = __napiModule.exports.ChunkGraph +export const ChunkGroup = __napiModule.exports.ChunkGroup +export const Chunks = __napiModule.exports.Chunks +export const CodeGenerationResult = __napiModule.exports.CodeGenerationResult +export const CodeGenerationResults = __napiModule.exports.CodeGenerationResults +export const ConcatenatedModule = __napiModule.exports.ConcatenatedModule +export const ContextModule = __napiModule.exports.ContextModule +export const Dependency = __napiModule.exports.Dependency +export const Diagnostics = __napiModule.exports.Diagnostics +export const EntryDataDto = __napiModule.exports.EntryDataDto +export const EntryDataDTO = __napiModule.exports.EntryDataDTO +export const EntryDependency = __napiModule.exports.EntryDependency +export const EntryOptionsDto = __napiModule.exports.EntryOptionsDto +export const EntryOptionsDTO = __napiModule.exports.EntryOptionsDTO +export const ExternalModule = __napiModule.exports.ExternalModule +export const JsCompilation = __napiModule.exports.JsCompilation +export const JsCompiler = __napiModule.exports.JsCompiler +export const JsContextModuleFactoryAfterResolveData = __napiModule.exports.JsContextModuleFactoryAfterResolveData +export const JsContextModuleFactoryBeforeResolveData = __napiModule.exports.JsContextModuleFactoryBeforeResolveData +export const JsDependencies = __napiModule.exports.JsDependencies +export const JsEntries = __napiModule.exports.JsEntries +export const JsExportsInfo = __napiModule.exports.JsExportsInfo +export const JsModuleGraph = __napiModule.exports.JsModuleGraph +export const JsResolver = __napiModule.exports.JsResolver +export const JsResolverFactory = __napiModule.exports.JsResolverFactory +export const JsStats = __napiModule.exports.JsStats +export const KnownBuildInfo = __napiModule.exports.KnownBuildInfo +export const Module = __napiModule.exports.Module +export const ModuleGraphConnection = __napiModule.exports.ModuleGraphConnection +export const NativeWatcher = __napiModule.exports.NativeWatcher +export const NativeWatchResult = __napiModule.exports.NativeWatchResult +export const NormalModule = __napiModule.exports.NormalModule +export const RawExternalItemFnCtx = __napiModule.exports.RawExternalItemFnCtx +export const ReadonlyResourceData = __napiModule.exports.ReadonlyResourceData +export const ResolverFactory = __napiModule.exports.ResolverFactory +export const Sources = __napiModule.exports.Sources +export const VirtualFileStore = __napiModule.exports.VirtualFileStore +export const JsVirtualFileStore = __napiModule.exports.JsVirtualFileStore +export const async = __napiModule.exports.async +export const BuiltinPluginName = __napiModule.exports.BuiltinPluginName +export const cleanupGlobalTrace = __napiModule.exports.cleanupGlobalTrace +export const EnforceExtension = __napiModule.exports.EnforceExtension +export const EXPECTED_RSPACK_CORE_VERSION = __napiModule.exports.EXPECTED_RSPACK_CORE_VERSION +export const formatDiagnostic = __napiModule.exports.formatDiagnostic +export const JsLoaderState = __napiModule.exports.JsLoaderState +export const JsRspackSeverity = __napiModule.exports.JsRspackSeverity +export const loadBrowserslist = __napiModule.exports.loadBrowserslist +export const minify = __napiModule.exports.minify +export const minifySync = __napiModule.exports.minifySync +export const RawJavascriptParserCommonjsExports = __napiModule.exports.RawJavascriptParserCommonjsExports +export const RawRuleSetConditionType = __napiModule.exports.RawRuleSetConditionType +export const registerGlobalTrace = __napiModule.exports.registerGlobalTrace +export const RegisterJsTapKind = __napiModule.exports.RegisterJsTapKind +export const sync = __napiModule.exports.sync +export const syncTraceEvent = __napiModule.exports.syncTraceEvent +export const transform = __napiModule.exports.transform +export const transformSync = __napiModule.exports.transformSync diff --git a/crates/node_binding/rspack.wasi.cjs b/crates/node_binding/rspack.wasi.cjs index 1ad96db4aac4..a251ce4d0d7d 100644 --- a/crates/node_binding/rspack.wasi.cjs +++ b/crates/node_binding/rspack.wasi.cjs @@ -108,4 +108,63 @@ const { instance: __napiInstance, module: __wasiModule, napiModule: __napiModule }, }) module.exports = __napiModule.exports - +module.exports.Assets = __napiModule.exports.Assets +module.exports.AsyncDependenciesBlock = __napiModule.exports.AsyncDependenciesBlock +module.exports.Chunk = __napiModule.exports.Chunk +module.exports.ChunkGraph = __napiModule.exports.ChunkGraph +module.exports.ChunkGroup = __napiModule.exports.ChunkGroup +module.exports.Chunks = __napiModule.exports.Chunks +module.exports.CodeGenerationResult = __napiModule.exports.CodeGenerationResult +module.exports.CodeGenerationResults = __napiModule.exports.CodeGenerationResults +module.exports.ConcatenatedModule = __napiModule.exports.ConcatenatedModule +module.exports.ContextModule = __napiModule.exports.ContextModule +module.exports.Dependency = __napiModule.exports.Dependency +module.exports.Diagnostics = __napiModule.exports.Diagnostics +module.exports.EntryDataDto = __napiModule.exports.EntryDataDto +module.exports.EntryDataDTO = __napiModule.exports.EntryDataDTO +module.exports.EntryDependency = __napiModule.exports.EntryDependency +module.exports.EntryOptionsDto = __napiModule.exports.EntryOptionsDto +module.exports.EntryOptionsDTO = __napiModule.exports.EntryOptionsDTO +module.exports.ExternalModule = __napiModule.exports.ExternalModule +module.exports.JsCompilation = __napiModule.exports.JsCompilation +module.exports.JsCompiler = __napiModule.exports.JsCompiler +module.exports.JsContextModuleFactoryAfterResolveData = __napiModule.exports.JsContextModuleFactoryAfterResolveData +module.exports.JsContextModuleFactoryBeforeResolveData = __napiModule.exports.JsContextModuleFactoryBeforeResolveData +module.exports.JsDependencies = __napiModule.exports.JsDependencies +module.exports.JsEntries = __napiModule.exports.JsEntries +module.exports.JsExportsInfo = __napiModule.exports.JsExportsInfo +module.exports.JsModuleGraph = __napiModule.exports.JsModuleGraph +module.exports.JsResolver = __napiModule.exports.JsResolver +module.exports.JsResolverFactory = __napiModule.exports.JsResolverFactory +module.exports.JsStats = __napiModule.exports.JsStats +module.exports.KnownBuildInfo = __napiModule.exports.KnownBuildInfo +module.exports.Module = __napiModule.exports.Module +module.exports.ModuleGraphConnection = __napiModule.exports.ModuleGraphConnection +module.exports.NativeWatcher = __napiModule.exports.NativeWatcher +module.exports.NativeWatchResult = __napiModule.exports.NativeWatchResult +module.exports.NormalModule = __napiModule.exports.NormalModule +module.exports.RawExternalItemFnCtx = __napiModule.exports.RawExternalItemFnCtx +module.exports.ReadonlyResourceData = __napiModule.exports.ReadonlyResourceData +module.exports.ResolverFactory = __napiModule.exports.ResolverFactory +module.exports.Sources = __napiModule.exports.Sources +module.exports.VirtualFileStore = __napiModule.exports.VirtualFileStore +module.exports.JsVirtualFileStore = __napiModule.exports.JsVirtualFileStore +module.exports.async = __napiModule.exports.async +module.exports.BuiltinPluginName = __napiModule.exports.BuiltinPluginName +module.exports.cleanupGlobalTrace = __napiModule.exports.cleanupGlobalTrace +module.exports.EnforceExtension = __napiModule.exports.EnforceExtension +module.exports.EXPECTED_RSPACK_CORE_VERSION = __napiModule.exports.EXPECTED_RSPACK_CORE_VERSION +module.exports.formatDiagnostic = __napiModule.exports.formatDiagnostic +module.exports.JsLoaderState = __napiModule.exports.JsLoaderState +module.exports.JsRspackSeverity = __napiModule.exports.JsRspackSeverity +module.exports.loadBrowserslist = __napiModule.exports.loadBrowserslist +module.exports.minify = __napiModule.exports.minify +module.exports.minifySync = __napiModule.exports.minifySync +module.exports.RawJavascriptParserCommonjsExports = __napiModule.exports.RawJavascriptParserCommonjsExports +module.exports.RawRuleSetConditionType = __napiModule.exports.RawRuleSetConditionType +module.exports.registerGlobalTrace = __napiModule.exports.registerGlobalTrace +module.exports.RegisterJsTapKind = __napiModule.exports.RegisterJsTapKind +module.exports.sync = __napiModule.exports.sync +module.exports.syncTraceEvent = __napiModule.exports.syncTraceEvent +module.exports.transform = __napiModule.exports.transform +module.exports.transformSync = __napiModule.exports.transformSync From 31ce58a95323e13197baa29194b83c0e87a89f90 Mon Sep 17 00:00:00 2001 From: "zhanghang.heal" Date: Mon, 12 Jan 2026 21:03:20 +0800 Subject: [PATCH 42/87] chore: replace async processAssets hooks with sync versions --- packages/rspack/src/container/ModuleFederationPlugin.ts | 8 ++++---- packages/rspack/src/sharing/CollectSharedEntryPlugin.ts | 4 ++-- packages/rspack/src/sharing/IndependentSharedPlugin.ts | 8 ++++---- packages/rspack/src/sharing/SharedContainerPlugin.ts | 4 ++-- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/rspack/src/container/ModuleFederationPlugin.ts b/packages/rspack/src/container/ModuleFederationPlugin.ts index be65f001fed6..23cec8dad615 100644 --- a/packages/rspack/src/container/ModuleFederationPlugin.ts +++ b/packages/rspack/src/container/ModuleFederationPlugin.ts @@ -57,12 +57,12 @@ export class ModuleFederationPlugin { // need to wait treeShakingSharedPlugin buildAssets let runtimePluginApplied = false; - compiler.hooks.beforeRun.tapPromise( + compiler.hooks.beforeRun.tap( { name: 'ModuleFederationPlugin', stage: 100, }, - async () => { + () => { if (runtimePluginApplied) return; runtimePluginApplied = true; const entryRuntime = getDefaultEntryRuntime( @@ -76,12 +76,12 @@ export class ModuleFederationPlugin { }).apply(compiler); }, ); - compiler.hooks.watchRun.tapPromise( + compiler.hooks.watchRun.tap( { name: 'ModuleFederationPlugin', stage: 100, }, - async () => { + () => { if (runtimePluginApplied) return; runtimePluginApplied = true; const entryRuntime = getDefaultEntryRuntime( diff --git a/packages/rspack/src/sharing/CollectSharedEntryPlugin.ts b/packages/rspack/src/sharing/CollectSharedEntryPlugin.ts index 208220f0f711..45f712e1440c 100644 --- a/packages/rspack/src/sharing/CollectSharedEntryPlugin.ts +++ b/packages/rspack/src/sharing/CollectSharedEntryPlugin.ts @@ -55,13 +55,13 @@ export class CollectSharedEntryPlugin extends RspackBuiltinPlugin { compiler.hooks.thisCompilation.tap( 'Collect shared entry', (compilation) => { - compilation.hooks.processAssets.tapPromise( + compilation.hooks.processAssets.tap( { name: 'CollectSharedEntry', stage: compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_INLINE, }, - async () => { + () => { compilation.getAssets().forEach((asset) => { if (asset.name === SHARE_ENTRY_ASSET) { this._collectedEntries = JSON.parse( diff --git a/packages/rspack/src/sharing/IndependentSharedPlugin.ts b/packages/rspack/src/sharing/IndependentSharedPlugin.ts index f6d33d124b85..cd0e71001462 100644 --- a/packages/rspack/src/sharing/IndependentSharedPlugin.ts +++ b/packages/rspack/src/sharing/IndependentSharedPlugin.ts @@ -94,12 +94,12 @@ class VirtualEntryPlugin { compiler.hooks.thisCompilation.tap( 'RemoveVirtualEntryAsset', (compilation) => { - compilation.hooks.processAssets.tapPromise( + compilation.hooks.processAssets.tap( { name: 'RemoveVirtualEntryAsset', stage: compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE, }, - async () => { + () => { try { const chunk = compilation.namedChunks.get(VIRTUAL_ENTRY_NAME); @@ -211,13 +211,13 @@ export class IndependentSharedPlugin { compiler.hooks.compilation.tap( 'IndependentSharedPlugin', (compilation) => { - compilation.hooks.processAssets.tapPromise( + compilation.hooks.processAssets.tap( { name: 'injectBuildAssets', stage: (compilation.constructor as any) .PROCESS_ASSETS_STAGE_OPTIMIZE_TRANSFER, }, - async () => { + () => { const { statsFileName, manifestFileName } = getFileName(manifest); const injectBuildAssetsIntoStatsOrManifest = ( filename: string, diff --git a/packages/rspack/src/sharing/SharedContainerPlugin.ts b/packages/rspack/src/sharing/SharedContainerPlugin.ts index e39a48978339..b0e89adb430b 100644 --- a/packages/rspack/src/sharing/SharedContainerPlugin.ts +++ b/packages/rspack/src/sharing/SharedContainerPlugin.ts @@ -75,11 +75,11 @@ export class SharedContainerPlugin extends RspackBuiltinPlugin { compiler.hooks.thisCompilation.tap( this.name, (compilation: Compilation) => { - compilation.hooks.processAssets.tapPromise( + compilation.hooks.processAssets.tap( { name: 'getShareContainerFile', }, - async () => { + () => { const remoteEntryPoint = compilation.entrypoints.get(shareName); assert( remoteEntryPoint, From d02192f06788a0472d7872c1bf9a9d38a9d2692c Mon Sep 17 00:00:00 2001 From: neverland Date: Tue, 13 Jan 2026 11:45:25 +0800 Subject: [PATCH 43/87] fix: `environments.importMetaDirnameAndFilename` not work (#12708) fix: `environments.importMetaDirnameAndFilename` should work --- .../src/parser_plugin/node_stuff_plugin.rs | 3 +-- packages/rspack/etc/core.api.md | 1 + packages/rspack/src/config/adapter.ts | 4 ++++ .../src/config/browserslistTargetHandler.ts | 5 +++++ packages/rspack/src/config/defaults.ts | 7 +++++++ packages/rspack/src/config/target.ts | 7 +++++++ packages/rspack/src/config/types.ts | 3 +++ .../rspack.config.js | 1 + .../browserslist-config-env/rspack.config.js | 1 + .../rspack.config.js | 1 + .../browserslist-config/rspack.config.js | 1 + .../browserslist-env/rspack.config.js | 1 + .../browserslist-extends/rspack.config.js | 1 + .../rspack.config.js | 1 + .../browserslist-query/rspack.config.js | 1 + .../ecmaVersion/browserslist/rspack.config.js | 1 + .../index.js | 15 ++++++++++++++ .../rspack.config.js | 20 +++++++++++++++++++ .../test.config.js | 20 +++++++++++++++++++ .../filename-and-dirname/rspack.config.js | 2 +- .../rspack-test/defaultsCases/default/base.js | 2 ++ website/docs/en/config/output.mdx | 2 ++ website/docs/zh/config/output.mdx | 2 ++ 23 files changed, 99 insertions(+), 3 deletions(-) create mode 100644 tests/rspack-test/configCases/node/filename-and-dirname-node-module-meta-dirname-and-filename/index.js create mode 100644 tests/rspack-test/configCases/node/filename-and-dirname-node-module-meta-dirname-and-filename/rspack.config.js create mode 100644 tests/rspack-test/configCases/node/filename-and-dirname-node-module-meta-dirname-and-filename/test.config.js diff --git a/crates/rspack_plugin_javascript/src/parser_plugin/node_stuff_plugin.rs b/crates/rspack_plugin_javascript/src/parser_plugin/node_stuff_plugin.rs index 8b78fc01ce0f..2ea5d325221d 100644 --- a/crates/rspack_plugin_javascript/src/parser_plugin/node_stuff_plugin.rs +++ b/crates/rspack_plugin_javascript/src/parser_plugin/node_stuff_plugin.rs @@ -281,7 +281,6 @@ impl NodeStuffPlugin { } /// Get the member replacement value for import.meta.filename/dirname - /// Returns None if the property should be preserved as-is, Some(replacement) otherwise fn get_import_meta_member_replacement( parser: &mut JavascriptParser, property: NodeMetaProperty, @@ -331,7 +330,7 @@ impl NodeStuffPlugin { .unwrap_or(false) { // Keep as import.meta.filename/dirname - runtime supports it - return None; + return Some(property.import_meta_name().to_string()); } Self::add_node_module_dependencies(parser, property); return Some(property.node_module_runtime_expr().to_string()); diff --git a/packages/rspack/etc/core.api.md b/packages/rspack/etc/core.api.md index bbabb4b3c281..6a5f826ee08b 100644 --- a/packages/rspack/etc/core.api.md +++ b/packages/rspack/etc/core.api.md @@ -2262,6 +2262,7 @@ export type Environment = { document?: boolean; dynamicImport?: boolean; dynamicImportInWorker?: boolean; + importMetaDirnameAndFilename?: boolean; forOf?: boolean; globalThis?: boolean; methodShorthand?: boolean; diff --git a/packages/rspack/src/config/adapter.ts b/packages/rspack/src/config/adapter.ts index e14a5e9516e6..b5e882c346d7 100644 --- a/packages/rspack/src/config/adapter.ts +++ b/packages/rspack/src/config/adapter.ts @@ -131,11 +131,15 @@ function getRawOutputEnvironment( destructuring: Boolean(environment.destructuring), document: Boolean(environment.document), dynamicImport: Boolean(environment.dynamicImport), + dynamicImportInWorker: Boolean(environment.dynamicImportInWorker), forOf: Boolean(environment.forOf), globalThis: Boolean(environment.globalThis), module: Boolean(environment.module), optionalChaining: Boolean(environment.optionalChaining), templateLiteral: Boolean(environment.templateLiteral), + importMetaDirnameAndFilename: Boolean( + environment.importMetaDirnameAndFilename, + ), }; } diff --git a/packages/rspack/src/config/browserslistTargetHandler.ts b/packages/rspack/src/config/browserslistTargetHandler.ts index 325b2d878cf8..b2b47cb38ea5 100644 --- a/packages/rspack/src/config/browserslistTargetHandler.ts +++ b/packages/rspack/src/config/browserslistTargetHandler.ts @@ -317,6 +317,11 @@ export const resolve = ( rawChecker({ node: [14, 18], }), + importMetaDirnameAndFilename: + nodeProperty && + rawChecker({ + node: [22, 16], + }), require: nodeProperty, }; }; diff --git a/packages/rspack/src/config/defaults.ts b/packages/rspack/src/config/defaults.ts index 85788f39886a..0831460bedcd 100644 --- a/packages/rspack/src/config/defaults.ts +++ b/packages/rspack/src/config/defaults.ts @@ -676,6 +676,13 @@ const applyOutputDefaults = ( 'nodePrefixForCoreModules', () => tp && optimistic(tp.nodePrefixForCoreModules), ); + F( + environment, + 'importMetaDirnameAndFilename', + () => + // No optimistic, because it is new + tp?.importMetaDirnameAndFilename, + ); F(environment, 'templateLiteral', () => tp && optimistic(tp.templateLiteral)); F(environment, 'dynamicImport', () => conditionallyOptimistic(tp?.dynamicImport, output.module), diff --git a/packages/rspack/src/config/target.ts b/packages/rspack/src/config/target.ts index dd82981024ff..54344a076680 100644 --- a/packages/rspack/src/config/target.ts +++ b/packages/rspack/src/config/target.ts @@ -63,6 +63,8 @@ export type ApiTargetProperties = { importScripts: boolean | null; /** has importScripts available when creating a worker */ importScriptsInWorker: boolean | null; + /** node.js allows to use `import.meta.dirname` and `import.meta.filename` */ + importMetaDirnameAndFilename: boolean | null; /** has fetch function available for WebAssembly */ fetchWasm: boolean | null; /** has global variable available */ @@ -235,6 +237,9 @@ You can also more options via the 'target' option: 'browserslist' / 'browserslis nodeBuiltins: true, // v16.0.0, v14.18.0 nodePrefixForCoreModules: +major < 15 ? v(14, 18) : v(16), + // Added in: v21.2.0, v20.11.0, but Node.js will output experimental warning, we don't want it + // v24.0.0, v22.16.0 - This property is no longer experimental. + importMetaDirnameAndFilename: v(22, 16), global: true, document: false, fetchWasm: false, @@ -281,6 +286,8 @@ You can also more options via the 'target' option: 'browserslist' / 'browserslis // 15.0.0 - Node.js v16.5 // 14.0.0 - Mode.js v14.17, but prefixes only since v14.18 nodePrefixForCoreModules: v(15), + // 37.0.0 - Node.js v22.16 + importMetaDirnameAndFilename: v(37), require: true, document: context === 'renderer', diff --git a/packages/rspack/src/config/types.ts b/packages/rspack/src/config/types.ts index 6c0f7b4bf59c..a40ee1172401 100644 --- a/packages/rspack/src/config/types.ts +++ b/packages/rspack/src/config/types.ts @@ -415,6 +415,9 @@ export type Environment = { /** The environment supports an async import() when creating a worker, only for web targets at the moment. */ dynamicImportInWorker?: boolean; + /** The environment supports `import.meta.dirname` and `import.meta.filename`. */ + importMetaDirnameAndFilename?: boolean; + /** The environment supports 'for of' iteration ('for (const x of array) { ... }'). */ forOf?: boolean; diff --git a/tests/rspack-test/configCases/ecmaVersion/browserslist-config-env-extends/rspack.config.js b/tests/rspack-test/configCases/ecmaVersion/browserslist-config-env-extends/rspack.config.js index de79550e9a66..e63be3a689d0 100644 --- a/tests/rspack-test/configCases/ecmaVersion/browserslist-config-env-extends/rspack.config.js +++ b/tests/rspack-test/configCases/ecmaVersion/browserslist-config-env-extends/rspack.config.js @@ -20,6 +20,7 @@ module.exports = { dynamicImportInWorker: false, forOf: false, globalThis: false, + importMetaDirnameAndFilename: false, methodShorthand: false, module: false, nodePrefixForCoreModules: false, diff --git a/tests/rspack-test/configCases/ecmaVersion/browserslist-config-env/rspack.config.js b/tests/rspack-test/configCases/ecmaVersion/browserslist-config-env/rspack.config.js index aee6f92cc110..f0b24661ecd5 100644 --- a/tests/rspack-test/configCases/ecmaVersion/browserslist-config-env/rspack.config.js +++ b/tests/rspack-test/configCases/ecmaVersion/browserslist-config-env/rspack.config.js @@ -18,6 +18,7 @@ module.exports = { dynamicImportInWorker: false, forOf: false, globalThis: false, + importMetaDirnameAndFilename: false, methodShorthand: false, module: false, nodePrefixForCoreModules: false, diff --git a/tests/rspack-test/configCases/ecmaVersion/browserslist-config-extends/rspack.config.js b/tests/rspack-test/configCases/ecmaVersion/browserslist-config-extends/rspack.config.js index d909b6d2439c..2e366b954b89 100644 --- a/tests/rspack-test/configCases/ecmaVersion/browserslist-config-extends/rspack.config.js +++ b/tests/rspack-test/configCases/ecmaVersion/browserslist-config-extends/rspack.config.js @@ -20,6 +20,7 @@ module.exports = { dynamicImportInWorker: false, forOf: false, globalThis: false, + importMetaDirnameAndFilename: false, methodShorthand: false, module: false, nodePrefixForCoreModules: false, diff --git a/tests/rspack-test/configCases/ecmaVersion/browserslist-config/rspack.config.js b/tests/rspack-test/configCases/ecmaVersion/browserslist-config/rspack.config.js index cff7528f113c..b00db18a7bdf 100644 --- a/tests/rspack-test/configCases/ecmaVersion/browserslist-config/rspack.config.js +++ b/tests/rspack-test/configCases/ecmaVersion/browserslist-config/rspack.config.js @@ -18,6 +18,7 @@ module.exports = { dynamicImportInWorker: false, forOf: false, globalThis: false, + importMetaDirnameAndFilename: false, methodShorthand: false, module: false, nodePrefixForCoreModules: false, diff --git a/tests/rspack-test/configCases/ecmaVersion/browserslist-env/rspack.config.js b/tests/rspack-test/configCases/ecmaVersion/browserslist-env/rspack.config.js index 1d64b70727d3..54e7429720b6 100644 --- a/tests/rspack-test/configCases/ecmaVersion/browserslist-env/rspack.config.js +++ b/tests/rspack-test/configCases/ecmaVersion/browserslist-env/rspack.config.js @@ -18,6 +18,7 @@ module.exports = { dynamicImportInWorker: false, forOf: false, globalThis: false, + importMetaDirnameAndFilename: false, methodShorthand: false, module: false, nodePrefixForCoreModules: false, diff --git a/tests/rspack-test/configCases/ecmaVersion/browserslist-extends/rspack.config.js b/tests/rspack-test/configCases/ecmaVersion/browserslist-extends/rspack.config.js index 4f792c91ab00..faf23d9ced29 100644 --- a/tests/rspack-test/configCases/ecmaVersion/browserslist-extends/rspack.config.js +++ b/tests/rspack-test/configCases/ecmaVersion/browserslist-extends/rspack.config.js @@ -18,6 +18,7 @@ module.exports = { dynamicImportInWorker: false, forOf: false, globalThis: false, + importMetaDirnameAndFilename: false, methodShorthand: false, module: false, nodePrefixForCoreModules: false, diff --git a/tests/rspack-test/configCases/ecmaVersion/browserslist-query-with-config-file/rspack.config.js b/tests/rspack-test/configCases/ecmaVersion/browserslist-query-with-config-file/rspack.config.js index 2a9c8fcb2748..409938a8eb76 100644 --- a/tests/rspack-test/configCases/ecmaVersion/browserslist-query-with-config-file/rspack.config.js +++ b/tests/rspack-test/configCases/ecmaVersion/browserslist-query-with-config-file/rspack.config.js @@ -18,6 +18,7 @@ module.exports = { dynamicImportInWorker: false, forOf: true, globalThis: true, + importMetaDirnameAndFilename: false, methodShorthand: true, module: true, nodePrefixForCoreModules: true, diff --git a/tests/rspack-test/configCases/ecmaVersion/browserslist-query/rspack.config.js b/tests/rspack-test/configCases/ecmaVersion/browserslist-query/rspack.config.js index ee38e453e89b..540445b67dc0 100644 --- a/tests/rspack-test/configCases/ecmaVersion/browserslist-query/rspack.config.js +++ b/tests/rspack-test/configCases/ecmaVersion/browserslist-query/rspack.config.js @@ -16,6 +16,7 @@ module.exports = { dynamicImportInWorker: false, forOf: false, globalThis: false, + importMetaDirnameAndFilename: false, methodShorthand: false, module: false, nodePrefixForCoreModules: false, diff --git a/tests/rspack-test/configCases/ecmaVersion/browserslist/rspack.config.js b/tests/rspack-test/configCases/ecmaVersion/browserslist/rspack.config.js index 10393169139d..3d76506ffe8d 100644 --- a/tests/rspack-test/configCases/ecmaVersion/browserslist/rspack.config.js +++ b/tests/rspack-test/configCases/ecmaVersion/browserslist/rspack.config.js @@ -16,6 +16,7 @@ module.exports = { dynamicImportInWorker: false, forOf: true, globalThis: true, + importMetaDirnameAndFilename: false, methodShorthand: true, module: true, nodePrefixForCoreModules: true, diff --git a/tests/rspack-test/configCases/node/filename-and-dirname-node-module-meta-dirname-and-filename/index.js b/tests/rspack-test/configCases/node/filename-and-dirname-node-module-meta-dirname-and-filename/index.js new file mode 100644 index 000000000000..0efc24ace34e --- /dev/null +++ b/tests/rspack-test/configCases/node/filename-and-dirname-node-module-meta-dirname-and-filename/index.js @@ -0,0 +1,15 @@ +import path from "path"; +import fs from "fs"; + +it("should use custom name", () => { + expect(__dirname).toBe(__STATS__.outputPath); + + const bundleFile = path.join(__STATS__.outputPath, "./bundle0.mjs"); + + expect(__filename).toBe(bundleFile); + + const content = fs.readFileSync(bundleFile, "utf8"); + + expect(content.includes("custom.dirname")).toBe(true); + expect(content.includes("custom.filename")).toBe(true); +}); diff --git a/tests/rspack-test/configCases/node/filename-and-dirname-node-module-meta-dirname-and-filename/rspack.config.js b/tests/rspack-test/configCases/node/filename-and-dirname-node-module-meta-dirname-and-filename/rspack.config.js new file mode 100644 index 000000000000..7b15e7c135b4 --- /dev/null +++ b/tests/rspack-test/configCases/node/filename-and-dirname-node-module-meta-dirname-and-filename/rspack.config.js @@ -0,0 +1,20 @@ +"use strict"; + +/** @type {import("@rspack/core").Configuration} */ +module.exports = { + target: "node", + experiments: { + outputModule: true + }, + output: { + module: true, + importMetaName: "custom", + environment: { + importMetaDirnameAndFilename: true + } + }, + node: { + __filename: "node-module", + __dirname: "node-module" + } +}; diff --git a/tests/rspack-test/configCases/node/filename-and-dirname-node-module-meta-dirname-and-filename/test.config.js b/tests/rspack-test/configCases/node/filename-and-dirname-node-module-meta-dirname-and-filename/test.config.js new file mode 100644 index 000000000000..9a1340356b95 --- /dev/null +++ b/tests/rspack-test/configCases/node/filename-and-dirname-node-module-meta-dirname-and-filename/test.config.js @@ -0,0 +1,20 @@ +"use strict"; + +const path = require("path"); +const { pathToFileURL } = require("url"); + +let counter = 0; + +module.exports = { + moduleScope(scope, _stats, options) { + const bundleFilename = path.join( + options.output.path, + `bundle${counter++}.mjs` + ); + scope.custom = { + url: pathToFileURL(bundleFilename).toString(), + dirname: path.dirname(bundleFilename), + filename: bundleFilename + }; + } +}; diff --git a/tests/rspack-test/configCases/node/filename-and-dirname/rspack.config.js b/tests/rspack-test/configCases/node/filename-and-dirname/rspack.config.js index 4c27b552ee1a..54080c471089 100644 --- a/tests/rspack-test/configCases/node/filename-and-dirname/rspack.config.js +++ b/tests/rspack-test/configCases/node/filename-and-dirname/rspack.config.js @@ -28,7 +28,7 @@ config.push( })) ); -// // ES modules +// ES modules config.push( ...values.map((value) => ({ target: "node", diff --git a/tests/rspack-test/defaultsCases/default/base.js b/tests/rspack-test/defaultsCases/default/base.js index 7a071595afe0..fd55eed78936 100644 --- a/tests/rspack-test/defaultsCases/default/base.js +++ b/tests/rspack-test/defaultsCases/default/base.js @@ -86,6 +86,7 @@ module.exports = { dynamicImportInWorker: undefined, forOf: true, globalThis: undefined, + importMetaDirnameAndFilename: undefined, methodShorthand: true, module: undefined, nodePrefixForCoreModules: true, @@ -337,6 +338,7 @@ module.exports = { dynamicImportInWorker: undefined, forOf: true, globalThis: undefined, + importMetaDirnameAndFilename: undefined, methodShorthand: true, module: undefined, nodePrefixForCoreModules: true, diff --git a/website/docs/en/config/output.mdx b/website/docs/en/config/output.mdx index afa3dd66a86d..88a36f62c44e 100644 --- a/website/docs/en/config/output.mdx +++ b/website/docs/en/config/output.mdx @@ -426,6 +426,8 @@ type Environment = { dynamicImport?: boolean; /** The environment supports an async import() when creating a worker, only for web targets at the moment. */ dynamicImportInWorker?: boolean; + /** The environment supports `import.meta.dirname` and `import.meta.filename`. */ + importMetaDirnameAndFilename?: boolean; /** The environment supports 'for of' iteration ('for (const x of array) { ... }'). */ forOf?: boolean; /** The environment supports 'globalThis'. */ diff --git a/website/docs/zh/config/output.mdx b/website/docs/zh/config/output.mdx index 10f55aedaaba..a57f7bc404a9 100644 --- a/website/docs/zh/config/output.mdx +++ b/website/docs/zh/config/output.mdx @@ -422,6 +422,8 @@ type Environment = { dynamicImport?: boolean; /** The environment supports an async import() when creating a worker, only for web targets at the moment. */ dynamicImportInWorker?: boolean; + /** The environment supports `import.meta.dirname` and `import.meta.filename`. */ + importMetaDirnameAndFilename?: boolean; /** The environment supports 'for of' iteration ('for (const x of array) { ... }'). */ forOf?: boolean; /** The environment supports 'globalThis'. */ From 6256796a998c4f2249ca8997217ae0268972afdb Mon Sep 17 00:00:00 2001 From: Cong-Cong Pan Date: Tue, 13 Jan 2026 13:00:09 +0800 Subject: [PATCH 44/87] fix: dynamic entry panic when disable build cache (#12696) --- Cargo.lock | 1 + crates/rspack_plugin_dynamic_entry/Cargo.toml | 15 ++-- crates/rspack_plugin_dynamic_entry/src/lib.rs | 83 ++++++++++++------- .../dynamic-entries-no-cache/0/index0.js | 0 .../dynamic-entries-no-cache/1/index0.js | 0 .../dynamic-entries-no-cache/1/index1.js | 0 .../dynamic-entries-no-cache/rspack.config.js | 39 +++++++++ .../dynamic-entries-no-cache/test.config.js | 5 ++ 8 files changed, 105 insertions(+), 38 deletions(-) create mode 100644 tests/rspack-test/watchCases/entries/dynamic-entries-no-cache/0/index0.js create mode 100644 tests/rspack-test/watchCases/entries/dynamic-entries-no-cache/1/index0.js create mode 100644 tests/rspack-test/watchCases/entries/dynamic-entries-no-cache/1/index1.js create mode 100644 tests/rspack-test/watchCases/entries/dynamic-entries-no-cache/rspack.config.js create mode 100644 tests/rspack-test/watchCases/entries/dynamic-entries-no-cache/test.config.js diff --git a/Cargo.lock b/Cargo.lock index 06b936ad9344..c64bdfd42439 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4331,6 +4331,7 @@ dependencies = [ name = "rspack_plugin_dynamic_entry" version = "0.7.1" dependencies = [ + "atomic_refcell", "derive_more", "futures", "rspack_core", diff --git a/crates/rspack_plugin_dynamic_entry/Cargo.toml b/crates/rspack_plugin_dynamic_entry/Cargo.toml index 013e0d787871..0cc00a1aa575 100644 --- a/crates/rspack_plugin_dynamic_entry/Cargo.toml +++ b/crates/rspack_plugin_dynamic_entry/Cargo.toml @@ -8,13 +8,14 @@ version.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -derive_more = { workspace = true, features = ["debug"] } -futures = { workspace = true } -rspack_core = { workspace = true } -rspack_error = { workspace = true } -rspack_hook = { workspace = true } -rspack_util = { workspace = true } -tracing = { workspace = true } +atomic_refcell = { workspace = true } +derive_more = { workspace = true, features = ["debug"] } +futures = { workspace = true } +rspack_core = { workspace = true } +rspack_error = { workspace = true } +rspack_hook = { workspace = true } +rspack_util = { workspace = true } +tracing = { workspace = true } [package.metadata.cargo-shear] ignored = ["tracing"] diff --git a/crates/rspack_plugin_dynamic_entry/src/lib.rs b/crates/rspack_plugin_dynamic_entry/src/lib.rs index b4687c2c5c83..78c00abb9a43 100644 --- a/crates/rspack_plugin_dynamic_entry/src/lib.rs +++ b/crates/rspack_plugin_dynamic_entry/src/lib.rs @@ -1,10 +1,12 @@ use std::sync::Arc; +use atomic_refcell::AtomicRefCell; use derive_more::Debug; -use futures::{future::BoxFuture, lock::Mutex}; +use futures::future::BoxFuture; use rspack_core::{ BoxDependency, Compilation, CompilationParams, CompilerCompilation, CompilerMake, Context, DependencyId, DependencyType, EntryDependency, EntryOptions, Plugin, + incremental::IncrementalPasses, internal, }; use rspack_error::Result; use rspack_hook::{plugin, plugin_hook}; @@ -31,7 +33,7 @@ pub struct DynamicEntryPlugin { entry: EntryDynamic, // Need "cache" the dependency to tell incremental that this entry dependency is not changed // so it can be reused and skip the module make - imported_dependencies: Mutex, FxHashMap>>, + imported_dependencies: AtomicRefCell, FxHashMap>>, } impl DynamicEntryPlugin { @@ -55,45 +57,64 @@ async fn make(&self, compilation: &mut Compilation) -> Result<()> { let entry_fn = &self.entry; let decs = entry_fn().await?; - let mut imported_dependencies = self.imported_dependencies.lock().await; - let mut next_imported_dependencies: FxHashMap, FxHashMap> = - Default::default(); + if compilation + .incremental + .mutations_readable(IncrementalPasses::MAKE) + { + let mut imported_dependencies = self.imported_dependencies.borrow_mut(); + let mut next_imported_dependencies: FxHashMap, FxHashMap> = + Default::default(); - for EntryDynamicResult { import, options } in decs { - for entry in import { - let module_graph = compilation.get_module_graph(); + for EntryDynamicResult { import, options } in decs { + for entry in import { + let module_graph = compilation.get_module_graph(); - let entry_dependency: BoxDependency = if let Some(map) = - imported_dependencies.get(entry.as_str()) - && let Some(dependency_id) = map.get(&options) - { - let dependency = module_graph.dependency_by_id(dependency_id); - next_imported_dependencies - .entry(entry.into()) - .or_default() - .insert(options.clone(), *dependency_id); - dependency.clone() - } else { - let dependency: BoxDependency = Box::new(EntryDependency::new( + let entry_dependency: BoxDependency = if let Some(map) = + imported_dependencies.get(entry.as_str()) + && let Some(dependency_id) = map.get(&options) + && let Some(dependency) = internal::try_dependency_by_id(module_graph, dependency_id) + { + next_imported_dependencies + .entry(entry.into()) + .or_default() + .insert(options.clone(), *dependency_id); + dependency.clone() + } else { + let dependency: BoxDependency = Box::new(EntryDependency::new( + entry.clone(), + self.context.clone(), + options.layer.clone(), + false, + )); + next_imported_dependencies + .entry(entry.into()) + .or_default() + .insert(options.clone(), *dependency.id()); + dependency + }; + compilation + .add_entry(entry_dependency, options.clone()) + .await?; + } + } + + *imported_dependencies = next_imported_dependencies; + } else { + for EntryDynamicResult { import, options } in decs { + for entry in import { + let entry_dependency: BoxDependency = Box::new(EntryDependency::new( entry.clone(), self.context.clone(), options.layer.clone(), false, )); - next_imported_dependencies - .entry(entry.into()) - .or_default() - .insert(options.clone(), *dependency.id()); - dependency - }; - compilation - .add_entry(entry_dependency, options.clone()) - .await?; + compilation + .add_entry(entry_dependency, options.clone()) + .await?; + } } } - *imported_dependencies = next_imported_dependencies; - Ok(()) } diff --git a/tests/rspack-test/watchCases/entries/dynamic-entries-no-cache/0/index0.js b/tests/rspack-test/watchCases/entries/dynamic-entries-no-cache/0/index0.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/tests/rspack-test/watchCases/entries/dynamic-entries-no-cache/1/index0.js b/tests/rspack-test/watchCases/entries/dynamic-entries-no-cache/1/index0.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/tests/rspack-test/watchCases/entries/dynamic-entries-no-cache/1/index1.js b/tests/rspack-test/watchCases/entries/dynamic-entries-no-cache/1/index1.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/tests/rspack-test/watchCases/entries/dynamic-entries-no-cache/rspack.config.js b/tests/rspack-test/watchCases/entries/dynamic-entries-no-cache/rspack.config.js new file mode 100644 index 000000000000..8e2dbba337d2 --- /dev/null +++ b/tests/rspack-test/watchCases/entries/dynamic-entries-no-cache/rspack.config.js @@ -0,0 +1,39 @@ +const path = require("path"); +const fs = require("fs"); +const rspack = require("@rspack/core"); + +let compiler; +let step = 0; +let entries; + +/** @type {import("@rspack/core").Configuration} */ +module.exports = { + entry: async () => { + const context = compiler.context; + if (step === 0) { + const files = await fs.promises.readdir(context); + entries = files.filter(f => f.startsWith("index")); + entries.sort(); + } else if (step === 1) { + } else { + throw new Error(`unreachable step: ${step}`); + } + return entries.reduce((acc, e, i) => { + acc[`bundle${i}`] = path.resolve(context, e); + return acc; + }, {}); + }, + output: { + filename: "[name].js" + }, + cache: false, + plugins: [ + new rspack.experiments.RemoveDuplicateModulesPlugin(), + function (c) { + compiler = c; + c.hooks.done.tap("test", () => { + step += 1; + }); + } + ] +}; diff --git a/tests/rspack-test/watchCases/entries/dynamic-entries-no-cache/test.config.js b/tests/rspack-test/watchCases/entries/dynamic-entries-no-cache/test.config.js new file mode 100644 index 000000000000..a03685b4d451 --- /dev/null +++ b/tests/rspack-test/watchCases/entries/dynamic-entries-no-cache/test.config.js @@ -0,0 +1,5 @@ +module.exports = { + findBundle() { + return []; + } +}; From a6892fefc24173887bc250bdfe58425828dec36a Mon Sep 17 00:00:00 2001 From: Agney Menon Date: Tue, 13 Jan 2026 10:54:50 +0530 Subject: [PATCH 45/87] fix(context-replacement): only apply changes when regex matches (#12657) fix(ContextReplacementPlugin): only apply changes when regex matches The plugin was applying transformations (recursive, regExp, critical) to all require.context() calls regardless of whether the configured regex pattern matched the request. This fix ensures all transformations only apply when the regex successfully matches. Closes #12656 --- .../src/context_replacement.rs | 8 ++++---- .../non-matching-regex/assets/file1.js | 1 + .../non-matching-regex/assets/file2.js | 1 + .../non-matching-regex/index.js | 14 ++++++++++++++ .../non-matching-regex/rspack.config.js | 15 +++++++++++++++ 5 files changed, 35 insertions(+), 4 deletions(-) create mode 100644 tests/rspack-test/configCases/context-replacement/non-matching-regex/assets/file1.js create mode 100644 tests/rspack-test/configCases/context-replacement/non-matching-regex/assets/file2.js create mode 100644 tests/rspack-test/configCases/context-replacement/non-matching-regex/index.js create mode 100644 tests/rspack-test/configCases/context-replacement/non-matching-regex/rspack.config.js diff --git a/crates/rspack_plugin_module_replacement/src/context_replacement.rs b/crates/rspack_plugin_module_replacement/src/context_replacement.rs index f4816416c76b..321cea7fa960 100644 --- a/crates/rspack_plugin_module_replacement/src/context_replacement.rs +++ b/crates/rspack_plugin_module_replacement/src/context_replacement.rs @@ -43,10 +43,10 @@ impl ContextReplacementPlugin { #[plugin_hook(ContextModuleFactoryBeforeResolve for ContextReplacementPlugin)] async fn cmf_before_resolve(&self, mut result: BeforeResolveResult) -> Result { - if let BeforeResolveResult::Data(data) = &mut result { - if self.resource_reg_exp.test(&data.request) - && let Some(new_content_resource) = &self.new_content_resource - { + if let BeforeResolveResult::Data(data) = &mut result + && self.resource_reg_exp.test(&data.request) + { + if let Some(new_content_resource) = &self.new_content_resource { data.request = new_content_resource.clone(); } if let Some(new_content_recursive) = self.new_content_recursive { diff --git a/tests/rspack-test/configCases/context-replacement/non-matching-regex/assets/file1.js b/tests/rspack-test/configCases/context-replacement/non-matching-regex/assets/file1.js new file mode 100644 index 000000000000..f96da5a947c2 --- /dev/null +++ b/tests/rspack-test/configCases/context-replacement/non-matching-regex/assets/file1.js @@ -0,0 +1 @@ +module.exports = "asset1"; diff --git a/tests/rspack-test/configCases/context-replacement/non-matching-regex/assets/file2.js b/tests/rspack-test/configCases/context-replacement/non-matching-regex/assets/file2.js new file mode 100644 index 000000000000..517649cc29f7 --- /dev/null +++ b/tests/rspack-test/configCases/context-replacement/non-matching-regex/assets/file2.js @@ -0,0 +1 @@ +module.exports = "asset2"; diff --git a/tests/rspack-test/configCases/context-replacement/non-matching-regex/index.js b/tests/rspack-test/configCases/context-replacement/non-matching-regex/index.js new file mode 100644 index 000000000000..9652aec0e0a4 --- /dev/null +++ b/tests/rspack-test/configCases/context-replacement/non-matching-regex/index.js @@ -0,0 +1,14 @@ +it("should not affect contexts that don't match the regex", function () { + // This context does NOT match /components$/ so should not be affected + var assetsContext = require.context("./assets", false, /\.js$/); + var assetKeys = assetsContext.keys(); + + // Should find the asset files since the plugin shouldn't affect this context + expect(assetKeys.length).toBe(2); + expect(assetKeys).toContain("./file1.js"); + expect(assetKeys).toContain("./file2.js"); + + // Verify we can actually load the files + expect(assetsContext("./file1.js")).toBe("asset1"); + expect(assetsContext("./file2.js")).toBe("asset2"); +}); diff --git a/tests/rspack-test/configCases/context-replacement/non-matching-regex/rspack.config.js b/tests/rspack-test/configCases/context-replacement/non-matching-regex/rspack.config.js new file mode 100644 index 000000000000..9710a9d6b552 --- /dev/null +++ b/tests/rspack-test/configCases/context-replacement/non-matching-regex/rspack.config.js @@ -0,0 +1,15 @@ +var webpack = require("@rspack/core"); + +/** @type {import("@rspack/core").Configuration} */ +module.exports = { + plugins: [ + // This plugin should only affect contexts matching /components$/ + // and should NOT affect the "assets" context + new webpack.ContextReplacementPlugin( + /components$/, + "./replaced-components", + true, + /^replaced$/ + ) + ] +}; From cad7e7a35c8a1f0d3636f4a23ed8c53c7d17f685 Mon Sep 17 00:00:00 2001 From: "zhanghang.heal" Date: Tue, 13 Jan 2026 13:42:01 +0800 Subject: [PATCH 46/87] docs: add missed doc --- ...ree-shake-shared-plugin.mdx => tree-shaking-shared-plugin.mdx} | 0 ...ree-shake-shared-plugin.mdx => tree-shaking-shared-plugin.mdx} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename website/docs/en/plugins/webpack/{tree-shake-shared-plugin.mdx => tree-shaking-shared-plugin.mdx} (100%) rename website/docs/zh/plugins/webpack/{tree-shake-shared-plugin.mdx => tree-shaking-shared-plugin.mdx} (100%) diff --git a/website/docs/en/plugins/webpack/tree-shake-shared-plugin.mdx b/website/docs/en/plugins/webpack/tree-shaking-shared-plugin.mdx similarity index 100% rename from website/docs/en/plugins/webpack/tree-shake-shared-plugin.mdx rename to website/docs/en/plugins/webpack/tree-shaking-shared-plugin.mdx diff --git a/website/docs/zh/plugins/webpack/tree-shake-shared-plugin.mdx b/website/docs/zh/plugins/webpack/tree-shaking-shared-plugin.mdx similarity index 100% rename from website/docs/zh/plugins/webpack/tree-shake-shared-plugin.mdx rename to website/docs/zh/plugins/webpack/tree-shaking-shared-plugin.mdx From 823686ae9c27f9986fe2f4de8e40faa081c1ac85 Mon Sep 17 00:00:00 2001 From: "zhanghang.heal" Date: Tue, 13 Jan 2026 13:53:59 +0800 Subject: [PATCH 47/87] fix: remove ueless dep --- crates/rspack_plugin_javascript/Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/rspack_plugin_javascript/Cargo.toml b/crates/rspack_plugin_javascript/Cargo.toml index 3ce0b59616a6..f18f9826d984 100644 --- a/crates/rspack_plugin_javascript/Cargo.toml +++ b/crates/rspack_plugin_javascript/Cargo.toml @@ -13,7 +13,6 @@ bitflags = { workspace = true } cow-utils = { workspace = true } either = { workspace = true } fast-glob = { workspace = true } -futures = { workspace = true } indexmap = { workspace = true } itertools = { workspace = true } num-bigint = { workspace = true } From 3d67873f3f5c8fa8f9603c261e9dc830574e9383 Mon Sep 17 00:00:00 2001 From: "zhanghang.heal" Date: Tue, 13 Jan 2026 15:52:27 +0800 Subject: [PATCH 48/87] chore: update lock file --- Cargo.lock | 1 - 1 file changed, 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index d4266f61f0ec..c64bdfd42439 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4500,7 +4500,6 @@ dependencies = [ "cow-utils", "either", "fast-glob", - "futures", "indexmap", "itertools 0.14.0", "num-bigint", From a47337bf63ad292842deaac0964f6ecdff3cf8bc Mon Sep 17 00:00:00 2001 From: Hanric Date: Tue, 13 Jan 2026 16:05:47 +0800 Subject: [PATCH 49/87] fix(mf): handle missing chunk gracefully and improve expose chunk name logic (#12709) --- crates/rspack_plugin_mf/src/manifest/asset.rs | 4 +++- crates/rspack_plugin_mf/src/manifest/mod.rs | 18 ++++++++++++++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/crates/rspack_plugin_mf/src/manifest/asset.rs b/crates/rspack_plugin_mf/src/manifest/asset.rs index 6bdd65eb066f..661589d11bb9 100644 --- a/crates/rspack_plugin_mf/src/manifest/asset.rs +++ b/crates/rspack_plugin_mf/src/manifest/asset.rs @@ -17,7 +17,9 @@ pub fn collect_assets_from_chunk( let mut js_async = HashSet::::default(); let mut css_sync = HashSet::::default(); let mut css_async = HashSet::::default(); - let chunk = compilation.chunk_by_ukey.expect_get(chunk_key); + let Some(chunk) = compilation.chunk_by_ukey.get(chunk_key) else { + return empty_assets_group(); + }; for file in chunk.files() { if file.ends_with(".css") { diff --git a/crates/rspack_plugin_mf/src/manifest/mod.rs b/crates/rspack_plugin_mf/src/manifest/mod.rs index 3a37a2dd2193..1f31d60b3de5 100644 --- a/crates/rspack_plugin_mf/src/manifest/mod.rs +++ b/crates/rspack_plugin_mf/src/manifest/mod.rs @@ -249,7 +249,8 @@ async fn process_assets(&self, compilation: &mut Compilation) -> Result<()> { .downcast_ref::() { container_entry_module = Some(module_identifier); - for (expose_key, options) in container_entry.exposes() { + let blocks = module.get_blocks(); + for (index, (expose_key, options)) in container_entry.exposes().iter().enumerate() { let expose_name = expose_key.trim_start_matches("./").to_string(); let Some(import) = options.import.iter().find(|request| !request.is_empty()) else { continue; @@ -266,7 +267,20 @@ async fn process_assets(&self, compilation: &mut Compilation) -> Result<()> { requires: Vec::new(), assets: StatsAssetsGroup::default(), }); - if let Some(n) = &options.name + + if let Some(block_id) = blocks.get(index) + && let Some(chunk_group) = compilation + .chunk_graph + .get_block_chunk_group(block_id, &compilation.chunk_group_by_ukey) + && let Some(chunk_key) = chunk_group.chunks.first() + && let Some(chunk) = compilation.chunk_by_ukey.get(chunk_key) + && let Some(name) = chunk.name() + { + expose_chunk_names.insert(expose_file_key.clone(), name.to_string()); + } + + if !expose_chunk_names.contains_key(&expose_file_key) + && let Some(n) = &options.name && !n.is_empty() { expose_chunk_names.insert(expose_file_key, n.clone()); From 368f3679dd3e76a0cb0df15450b0ffb0e5d61162 Mon Sep 17 00:00:00 2001 From: 9aoy <9aoyuao@gmail.com> Date: Tue, 13 Jan 2026 16:05:59 +0800 Subject: [PATCH 50/87] fix(type): runtimeModule.source (#12713) * fix(type): runtimeModule.source * fix: lint * fix: lint --- packages/rspack/etc/core.api.md | 3 +++ packages/rspack/src/RuntimeModule.ts | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/packages/rspack/etc/core.api.md b/packages/rspack/etc/core.api.md index 6a5f826ee08b..a7e532863cbb 100644 --- a/packages/rspack/etc/core.api.md +++ b/packages/rspack/etc/core.api.md @@ -53,6 +53,7 @@ import { JsRsdoctorChunkGraph } from '@rspack/binding'; import { JsRsdoctorModuleGraph } from '@rspack/binding'; import { JsRsdoctorModuleIdsPatch } from '@rspack/binding'; import { JsRsdoctorModuleSourcesPatch } from '@rspack/binding'; +import type { JsSource } from '@rspack/binding'; import type { JsStats } from '@rspack/binding'; import type { JsStatsCompilation } from '@rspack/binding'; import type { JsStatsError } from '@rspack/binding'; @@ -7200,6 +7201,8 @@ export class RuntimeModule { // (undocumented) shouldIsolate(): boolean; // (undocumented) + get source(): JsSource | undefined; + // (undocumented) get stage(): RuntimeModuleStage; // (undocumented) static STAGE_ATTACH: RuntimeModuleStage; diff --git a/packages/rspack/src/RuntimeModule.ts b/packages/rspack/src/RuntimeModule.ts index c349b3cae727..067418b20d40 100644 --- a/packages/rspack/src/RuntimeModule.ts +++ b/packages/rspack/src/RuntimeModule.ts @@ -49,6 +49,10 @@ export class RuntimeModule { this.chunkGraph = chunkGraph; } + get source(): JsSource | undefined { + return undefined; + } + get name(): string { return this._name; } From 26c87d78b7baaa38f3122a69657ed565f74df8e6 Mon Sep 17 00:00:00 2001 From: Fy <1114550440@qq.com> Date: Tue, 13 Jan 2026 17:54:58 +0800 Subject: [PATCH 51/87] chore: release 1.7.2 (#12710) Release 0.7.2 rspack@0.7.2 rspack_allocator@0.7.2 rspack_binding_api@0.7.2 rspack_binding_build@0.7.2 rspack_binding_builder@0.7.2 rspack_binding_builder_macros@0.7.2 rspack_browser@0.7.2 rspack_browserslist@0.7.2 rspack_cacheable@0.7.2 rspack_cacheable_macros@0.7.2 rspack_collections@0.7.2 rspack_core@0.7.2 rspack_error@0.7.2 rspack_fs@0.7.2 rspack_futures@0.7.2 rspack_hash@0.7.2 rspack_hook@0.7.2 rspack_ids@0.7.2 rspack_javascript_compiler@0.7.2 rspack_loader_lightningcss@0.7.2 rspack_loader_preact_refresh@0.7.2 rspack_loader_react_refresh@0.7.2 rspack_loader_runner@0.7.2 rspack_loader_swc@0.7.2 rspack_loader_testing@0.7.2 rspack_location@0.7.2 rspack_macros@0.7.2 rspack_napi@0.7.2 rspack_napi_macros@0.7.2 rspack_paths@0.7.2 rspack_plugin_asset@0.7.2 rspack_plugin_banner@0.7.2 rspack_plugin_case_sensitive@0.7.2 rspack_plugin_circular_dependencies@0.7.2 rspack_plugin_copy@0.7.2 rspack_plugin_css@0.7.2 rspack_plugin_css_chunking@0.7.2 rspack_plugin_devtool@0.7.2 rspack_plugin_dll@0.7.2 rspack_plugin_dynamic_entry@0.7.2 rspack_plugin_ensure_chunk_conditions@0.7.2 rspack_plugin_entry@0.7.2 rspack_plugin_esm_library@0.7.2 rspack_plugin_externals@0.7.2 rspack_plugin_extract_css@0.7.2 rspack_plugin_hmr@0.7.2 rspack_plugin_html@0.7.2 rspack_plugin_ignore@0.7.2 rspack_plugin_javascript@0.7.2 rspack_plugin_json@0.7.2 rspack_plugin_lazy_compilation@0.7.2 rspack_plugin_library@0.7.2 rspack_plugin_lightning_css_minimizer@0.7.2 rspack_plugin_limit_chunk_count@0.7.2 rspack_plugin_merge_duplicate_chunks@0.7.2 rspack_plugin_mf@0.7.2 rspack_plugin_module_info_header@0.7.2 rspack_plugin_module_replacement@0.7.2 rspack_plugin_no_emit_on_errors@0.7.2 rspack_plugin_progress@0.7.2 rspack_plugin_real_content_hash@0.7.2 rspack_plugin_remove_duplicate_modules@0.7.2 rspack_plugin_remove_empty_chunks@0.7.2 rspack_plugin_rsdoctor@0.7.2 rspack_plugin_rslib@0.7.2 rspack_plugin_rstest@0.7.2 rspack_plugin_runtime@0.7.2 rspack_plugin_runtime_chunk@0.7.2 rspack_plugin_schemes@0.7.2 rspack_plugin_size_limits@0.7.2 rspack_plugin_split_chunks@0.7.2 rspack_plugin_sri@0.7.2 rspack_plugin_swc_js_minimizer@0.7.2 rspack_plugin_wasm@0.7.2 rspack_plugin_web_worker_template@0.7.2 rspack_plugin_worker@0.7.2 rspack_regex@0.7.2 rspack_storage@0.7.2 rspack_swc_plugin_import@0.7.2 rspack_swc_plugin_ts_collector@0.7.2 rspack_tasks@0.7.2 rspack_tracing@0.7.2 rspack_tracing_perfetto@0.7.2 rspack_util@0.7.2 rspack_watcher@0.7.2 rspack_workspace@0.7.2 Generated by cargo-workspaces --- Cargo.lock | 184 +++++++++++------------ Cargo.toml | 174 ++++++++++----------- crates/node_binding/package.json | 2 +- crates/rspack_workspace/src/generated.rs | 4 +- npm/darwin-arm64/package.json | 2 +- npm/darwin-x64/package.json | 2 +- npm/linux-arm64-gnu/package.json | 2 +- npm/linux-arm64-musl/package.json | 2 +- npm/linux-x64-gnu/package.json | 2 +- npm/linux-x64-musl/package.json | 2 +- npm/wasm32-wasi/package.json | 2 +- npm/win32-arm64-msvc/package.json | 2 +- npm/win32-ia32-msvc/package.json | 2 +- npm/win32-x64-msvc/package.json | 2 +- package.json | 2 +- packages/create-rspack/package.json | 2 +- packages/rspack-browser/package.json | 2 +- packages/rspack-cli/package.json | 2 +- packages/rspack-test-tools/package.json | 2 +- packages/rspack/package.json | 2 +- 20 files changed, 198 insertions(+), 198 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c64bdfd42439..2b67d404c6a2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3453,7 +3453,7 @@ dependencies = [ [[package]] name = "rspack" -version = "0.7.1" +version = "0.7.2" dependencies = [ "bitflags 2.9.1", "derive_more", @@ -3539,7 +3539,7 @@ dependencies = [ [[package]] name = "rspack_allocator" -version = "0.7.1" +version = "0.7.2" dependencies = [ "mimalloc-rspack", "sftrace-setup", @@ -3548,7 +3548,7 @@ dependencies = [ [[package]] name = "rspack_benchmark" -version = "0.7.1" +version = "0.7.2" dependencies = [ "criterion2", "rspack", @@ -3564,7 +3564,7 @@ dependencies = [ [[package]] name = "rspack_binding_api" -version = "0.7.1" +version = "0.7.2" dependencies = [ "anyhow", "async-trait", @@ -3670,21 +3670,21 @@ dependencies = [ [[package]] name = "rspack_binding_build" -version = "0.7.1" +version = "0.7.2" dependencies = [ "napi-build", ] [[package]] name = "rspack_binding_builder" -version = "0.7.1" +version = "0.7.2" dependencies = [ "rspack_binding_api", ] [[package]] name = "rspack_binding_builder_macros" -version = "0.7.1" +version = "0.7.2" dependencies = [ "proc-macro2", "quote", @@ -3694,7 +3694,7 @@ dependencies = [ [[package]] name = "rspack_binding_builder_testing" -version = "0.7.1" +version = "0.7.2" dependencies = [ "napi", "napi-derive", @@ -3708,11 +3708,11 @@ dependencies = [ [[package]] name = "rspack_browser" -version = "0.7.1" +version = "0.7.2" [[package]] name = "rspack_browserslist" -version = "0.7.1" +version = "0.7.2" dependencies = [ "browserslist-rs", "lightningcss", @@ -3721,7 +3721,7 @@ dependencies = [ [[package]] name = "rspack_cacheable" -version = "0.7.1" +version = "0.7.2" dependencies = [ "camino", "dashmap 6.1.0", @@ -3747,7 +3747,7 @@ dependencies = [ [[package]] name = "rspack_cacheable_macros" -version = "0.7.1" +version = "0.7.2" dependencies = [ "quote", "syn 2.0.113", @@ -3755,7 +3755,7 @@ dependencies = [ [[package]] name = "rspack_cacheable_test" -version = "0.7.1" +version = "0.7.2" dependencies = [ "camino", "dashmap 6.1.0", @@ -3774,7 +3774,7 @@ dependencies = [ [[package]] name = "rspack_collections" -version = "0.7.1" +version = "0.7.2" dependencies = [ "dashmap 6.1.0", "hashlink", @@ -3788,7 +3788,7 @@ dependencies = [ [[package]] name = "rspack_core" -version = "0.7.1" +version = "0.7.2" dependencies = [ "anymap3", "async-recursion", @@ -3867,7 +3867,7 @@ dependencies = [ [[package]] name = "rspack_error" -version = "0.7.1" +version = "0.7.2" dependencies = [ "anyhow", "miette", @@ -3884,7 +3884,7 @@ dependencies = [ [[package]] name = "rspack_fs" -version = "0.7.1" +version = "0.7.2" dependencies = [ "async-trait", "cfg-if", @@ -3899,7 +3899,7 @@ dependencies = [ [[package]] name = "rspack_futures" -version = "0.7.1" +version = "0.7.2" dependencies = [ "rspack_tasks", "tokio", @@ -3907,7 +3907,7 @@ dependencies = [ [[package]] name = "rspack_hash" -version = "0.7.1" +version = "0.7.2" dependencies = [ "md4", "rspack_cacheable", @@ -3918,7 +3918,7 @@ dependencies = [ [[package]] name = "rspack_hook" -version = "0.7.1" +version = "0.7.2" dependencies = [ "async-trait", "rspack_error", @@ -3929,7 +3929,7 @@ dependencies = [ [[package]] name = "rspack_ids" -version = "0.7.1" +version = "0.7.2" dependencies = [ "itertools 0.14.0", "rayon", @@ -3944,7 +3944,7 @@ dependencies = [ [[package]] name = "rspack_javascript_compiler" -version = "0.7.1" +version = "0.7.2" dependencies = [ "anyhow", "base64", @@ -3968,7 +3968,7 @@ dependencies = [ [[package]] name = "rspack_loader_lightningcss" -version = "0.7.1" +version = "0.7.2" dependencies = [ "async-trait", "derive_more", @@ -3988,7 +3988,7 @@ dependencies = [ [[package]] name = "rspack_loader_preact_refresh" -version = "0.7.1" +version = "0.7.2" dependencies = [ "async-trait", "rspack_cacheable", @@ -4001,7 +4001,7 @@ dependencies = [ [[package]] name = "rspack_loader_react_refresh" -version = "0.7.1" +version = "0.7.2" dependencies = [ "async-trait", "rspack_cacheable", @@ -4014,7 +4014,7 @@ dependencies = [ [[package]] name = "rspack_loader_runner" -version = "0.7.1" +version = "0.7.2" dependencies = [ "anymap3", "async-trait", @@ -4037,7 +4037,7 @@ dependencies = [ [[package]] name = "rspack_loader_swc" -version = "0.7.1" +version = "0.7.2" dependencies = [ "async-trait", "either", @@ -4065,7 +4065,7 @@ dependencies = [ [[package]] name = "rspack_loader_testing" -version = "0.7.1" +version = "0.7.2" dependencies = [ "async-trait", "rspack_cacheable", @@ -4077,7 +4077,7 @@ dependencies = [ [[package]] name = "rspack_location" -version = "0.7.1" +version = "0.7.2" dependencies = [ "itoa", "rspack_cacheable", @@ -4085,7 +4085,7 @@ dependencies = [ [[package]] name = "rspack_macros" -version = "0.7.1" +version = "0.7.2" dependencies = [ "proc-macro2", "quote", @@ -4094,7 +4094,7 @@ dependencies = [ [[package]] name = "rspack_macros_test" -version = "0.7.1" +version = "0.7.2" dependencies = [ "async-trait", "rspack_cacheable", @@ -4112,7 +4112,7 @@ dependencies = [ [[package]] name = "rspack_napi" -version = "0.7.1" +version = "0.7.2" dependencies = [ "napi", "oneshot", @@ -4124,7 +4124,7 @@ dependencies = [ [[package]] name = "rspack_napi_macros" -version = "0.7.1" +version = "0.7.2" dependencies = [ "proc-macro2", "quote", @@ -4133,7 +4133,7 @@ dependencies = [ [[package]] name = "rspack_node" -version = "0.7.1" +version = "0.7.2" dependencies = [ "napi-derive", "rspack_binding_api", @@ -4143,7 +4143,7 @@ dependencies = [ [[package]] name = "rspack_paths" -version = "0.7.1" +version = "0.7.2" dependencies = [ "camino", "dashmap 6.1.0", @@ -4155,7 +4155,7 @@ dependencies = [ [[package]] name = "rspack_plugin_asset" -version = "0.7.1" +version = "0.7.2" dependencies = [ "async-trait", "mime_guess", @@ -4173,7 +4173,7 @@ dependencies = [ [[package]] name = "rspack_plugin_banner" -version = "0.7.1" +version = "0.7.2" dependencies = [ "cow-utils", "futures", @@ -4187,7 +4187,7 @@ dependencies = [ [[package]] name = "rspack_plugin_case_sensitive" -version = "0.7.1" +version = "0.7.2" dependencies = [ "cow-utils", "itertools 0.14.0", @@ -4201,7 +4201,7 @@ dependencies = [ [[package]] name = "rspack_plugin_circular_dependencies" -version = "0.7.1" +version = "0.7.2" dependencies = [ "cow-utils", "derive_more", @@ -4218,7 +4218,7 @@ dependencies = [ [[package]] name = "rspack_plugin_copy" -version = "0.7.1" +version = "0.7.2" dependencies = [ "dashmap 6.1.0", "derive_more", @@ -4238,7 +4238,7 @@ dependencies = [ [[package]] name = "rspack_plugin_css" -version = "0.7.1" +version = "0.7.2" dependencies = [ "async-trait", "atomic_refcell", @@ -4266,7 +4266,7 @@ dependencies = [ [[package]] name = "rspack_plugin_css_chunking" -version = "0.7.1" +version = "0.7.2" dependencies = [ "indexmap", "rspack_collections", @@ -4281,7 +4281,7 @@ dependencies = [ [[package]] name = "rspack_plugin_devtool" -version = "0.7.1" +version = "0.7.2" dependencies = [ "cow-utils", "dashmap 6.1.0", @@ -4309,7 +4309,7 @@ dependencies = [ [[package]] name = "rspack_plugin_dll" -version = "0.7.1" +version = "0.7.2" dependencies = [ "async-trait", "rspack_cacheable", @@ -4329,7 +4329,7 @@ dependencies = [ [[package]] name = "rspack_plugin_dynamic_entry" -version = "0.7.1" +version = "0.7.2" dependencies = [ "atomic_refcell", "derive_more", @@ -4343,7 +4343,7 @@ dependencies = [ [[package]] name = "rspack_plugin_ensure_chunk_conditions" -version = "0.7.1" +version = "0.7.2" dependencies = [ "rspack_core", "rspack_error", @@ -4354,7 +4354,7 @@ dependencies = [ [[package]] name = "rspack_plugin_entry" -version = "0.7.1" +version = "0.7.2" dependencies = [ "rspack_core", "rspack_error", @@ -4364,7 +4364,7 @@ dependencies = [ [[package]] name = "rspack_plugin_esm_library" -version = "0.7.1" +version = "0.7.2" dependencies = [ "async-trait", "atomic_refcell", @@ -4391,7 +4391,7 @@ dependencies = [ [[package]] name = "rspack_plugin_externals" -version = "0.7.1" +version = "0.7.2" dependencies = [ "regex", "rspack_core", @@ -4404,7 +4404,7 @@ dependencies = [ [[package]] name = "rspack_plugin_extract_css" -version = "0.7.1" +version = "0.7.2" dependencies = [ "async-trait", "cow-utils", @@ -4430,7 +4430,7 @@ dependencies = [ [[package]] name = "rspack_plugin_hmr" -version = "0.7.1" +version = "0.7.2" dependencies = [ "async-trait", "rspack_cacheable", @@ -4450,7 +4450,7 @@ dependencies = [ [[package]] name = "rspack_plugin_html" -version = "0.7.1" +version = "0.7.2" dependencies = [ "anyhow", "atomic_refcell", @@ -4479,7 +4479,7 @@ dependencies = [ [[package]] name = "rspack_plugin_ignore" -version = "0.7.1" +version = "0.7.2" dependencies = [ "derive_more", "futures", @@ -4492,7 +4492,7 @@ dependencies = [ [[package]] name = "rspack_plugin_javascript" -version = "0.7.1" +version = "0.7.2" dependencies = [ "anymap3", "async-trait", @@ -4533,7 +4533,7 @@ dependencies = [ [[package]] name = "rspack_plugin_json" -version = "0.7.1" +version = "0.7.2" dependencies = [ "async-trait", "cow-utils", @@ -4547,7 +4547,7 @@ dependencies = [ [[package]] name = "rspack_plugin_lazy_compilation" -version = "0.7.1" +version = "0.7.2" dependencies = [ "async-trait", "rspack_cacheable", @@ -4567,7 +4567,7 @@ dependencies = [ [[package]] name = "rspack_plugin_library" -version = "0.7.1" +version = "0.7.2" dependencies = [ "futures", "regex", @@ -4586,7 +4586,7 @@ dependencies = [ [[package]] name = "rspack_plugin_lightning_css_minimizer" -version = "0.7.1" +version = "0.7.2" dependencies = [ "lightningcss", "parcel_sourcemap", @@ -4604,7 +4604,7 @@ dependencies = [ [[package]] name = "rspack_plugin_limit_chunk_count" -version = "0.7.1" +version = "0.7.2" dependencies = [ "rspack_collections", "rspack_core", @@ -4615,7 +4615,7 @@ dependencies = [ [[package]] name = "rspack_plugin_merge_duplicate_chunks" -version = "0.7.1" +version = "0.7.2" dependencies = [ "rayon", "rspack_collections", @@ -4628,7 +4628,7 @@ dependencies = [ [[package]] name = "rspack_plugin_mf" -version = "0.7.1" +version = "0.7.2" dependencies = [ "async-trait", "camino", @@ -4655,7 +4655,7 @@ dependencies = [ [[package]] name = "rspack_plugin_module_info_header" -version = "0.7.1" +version = "0.7.2" dependencies = [ "regex", "rspack_cacheable", @@ -4671,7 +4671,7 @@ dependencies = [ [[package]] name = "rspack_plugin_module_replacement" -version = "0.7.1" +version = "0.7.2" dependencies = [ "derive_more", "futures", @@ -4686,7 +4686,7 @@ dependencies = [ [[package]] name = "rspack_plugin_no_emit_on_errors" -version = "0.7.1" +version = "0.7.2" dependencies = [ "rspack_core", "rspack_error", @@ -4696,7 +4696,7 @@ dependencies = [ [[package]] name = "rspack_plugin_progress" -version = "0.7.1" +version = "0.7.2" dependencies = [ "futures", "indicatif", @@ -4710,7 +4710,7 @@ dependencies = [ [[package]] name = "rspack_plugin_real_content_hash" -version = "0.7.1" +version = "0.7.2" dependencies = [ "aho-corasick", "atomic_refcell", @@ -4731,7 +4731,7 @@ dependencies = [ [[package]] name = "rspack_plugin_remove_duplicate_modules" -version = "0.7.1" +version = "0.7.2" dependencies = [ "rspack_collections", "rspack_core", @@ -4743,7 +4743,7 @@ dependencies = [ [[package]] name = "rspack_plugin_remove_empty_chunks" -version = "0.7.1" +version = "0.7.2" dependencies = [ "rspack_collections", "rspack_core", @@ -4754,7 +4754,7 @@ dependencies = [ [[package]] name = "rspack_plugin_rsdoctor" -version = "0.7.1" +version = "0.7.2" dependencies = [ "atomic_refcell", "futures", @@ -4775,7 +4775,7 @@ dependencies = [ [[package]] name = "rspack_plugin_rslib" -version = "0.7.1" +version = "0.7.2" dependencies = [ "async-trait", "rspack_cacheable", @@ -4793,7 +4793,7 @@ dependencies = [ [[package]] name = "rspack_plugin_rstest" -version = "0.7.1" +version = "0.7.2" dependencies = [ "camino", "regex", @@ -4809,7 +4809,7 @@ dependencies = [ [[package]] name = "rspack_plugin_runtime" -version = "0.7.1" +version = "0.7.2" dependencies = [ "async-trait", "atomic_refcell", @@ -4833,7 +4833,7 @@ dependencies = [ [[package]] name = "rspack_plugin_runtime_chunk" -version = "0.7.1" +version = "0.7.2" dependencies = [ "futures", "rspack_core", @@ -4844,7 +4844,7 @@ dependencies = [ [[package]] name = "rspack_plugin_schemes" -version = "0.7.1" +version = "0.7.2" dependencies = [ "anyhow", "async-trait", @@ -4869,7 +4869,7 @@ dependencies = [ [[package]] name = "rspack_plugin_size_limits" -version = "0.7.1" +version = "0.7.2" dependencies = [ "derive_more", "futures", @@ -4883,7 +4883,7 @@ dependencies = [ [[package]] name = "rspack_plugin_split_chunks" -version = "0.7.1" +version = "0.7.2" dependencies = [ "dashmap 6.1.0", "derive_more", @@ -4905,7 +4905,7 @@ dependencies = [ [[package]] name = "rspack_plugin_sri" -version = "0.7.1" +version = "0.7.2" dependencies = [ "async-trait", "cow-utils", @@ -4939,7 +4939,7 @@ dependencies = [ [[package]] name = "rspack_plugin_swc_js_minimizer" -version = "0.7.1" +version = "0.7.2" dependencies = [ "cow-utils", "once_cell", @@ -4962,7 +4962,7 @@ dependencies = [ [[package]] name = "rspack_plugin_wasm" -version = "0.7.1" +version = "0.7.2" dependencies = [ "async-trait", "cow-utils", @@ -4982,7 +4982,7 @@ dependencies = [ [[package]] name = "rspack_plugin_web_worker_template" -version = "0.7.1" +version = "0.7.2" dependencies = [ "rspack_core", "rspack_plugin_runtime", @@ -4990,7 +4990,7 @@ dependencies = [ [[package]] name = "rspack_plugin_worker" -version = "0.7.1" +version = "0.7.2" dependencies = [ "rspack_core", "rspack_error", @@ -5000,7 +5000,7 @@ dependencies = [ [[package]] name = "rspack_regex" -version = "0.7.1" +version = "0.7.2" dependencies = [ "cow-utils", "napi", @@ -5051,7 +5051,7 @@ dependencies = [ [[package]] name = "rspack_storage" -version = "0.7.1" +version = "0.7.2" dependencies = [ "async-trait", "cow-utils", @@ -5069,7 +5069,7 @@ dependencies = [ [[package]] name = "rspack_swc_plugin_import" -version = "0.7.1" +version = "0.7.2" dependencies = [ "cow-utils", "heck", @@ -5080,7 +5080,7 @@ dependencies = [ [[package]] name = "rspack_swc_plugin_ts_collector" -version = "0.7.1" +version = "0.7.2" dependencies = [ "glob", "rspack_javascript_compiler", @@ -5091,14 +5091,14 @@ dependencies = [ [[package]] name = "rspack_tasks" -version = "0.7.1" +version = "0.7.2" dependencies = [ "tokio", ] [[package]] name = "rspack_tools" -version = "0.7.1" +version = "0.7.2" dependencies = [ "clap", "itertools 0.14.0", @@ -5113,7 +5113,7 @@ dependencies = [ [[package]] name = "rspack_tracing" -version = "0.7.1" +version = "0.7.2" dependencies = [ "chrono", "rspack_tracing_perfetto", @@ -5123,7 +5123,7 @@ dependencies = [ [[package]] name = "rspack_tracing_perfetto" -version = "0.7.1" +version = "0.7.2" dependencies = [ "bytes", "micromegas-perfetto", @@ -5135,7 +5135,7 @@ dependencies = [ [[package]] name = "rspack_util" -version = "0.7.1" +version = "0.7.2" dependencies = [ "anyhow", "base64-simd 0.8.0", @@ -5168,7 +5168,7 @@ dependencies = [ [[package]] name = "rspack_watcher" -version = "0.7.1" +version = "0.7.2" dependencies = [ "cow-utils", "dashmap 6.1.0", @@ -5184,7 +5184,7 @@ dependencies = [ [[package]] name = "rspack_workspace" -version = "0.7.1" +version = "0.7.2" [[package]] name = "rustc-demangle" diff --git a/Cargo.toml b/Cargo.toml index 8aab94a8335b..638a53429888 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ edition = "2024" homepage = "https://rspack.rs/" license = "MIT" repository = "https://github.com/web-infra-dev/rspack" -version = "0.7.1" +version = "0.7.2" [workspace.metadata.cargo-shear] ignored = ["swc", "rspack"] @@ -162,92 +162,92 @@ wasmtime = { version = "35.0.0", default-features = false } # all rspack workspace dependencies -rspack = { version = "=0.7.1", path = "crates/rspack", default-features = false } -rspack_allocator = { version = "=0.7.1", path = "crates/rspack_allocator", default-features = false } -rspack_binding_api = { version = "=0.7.1", path = "crates/rspack_binding_api", default-features = false } -rspack_binding_build = { version = "=0.7.1", path = "crates/rspack_binding_build", default-features = false } -rspack_binding_builder = { version = "=0.7.1", path = "crates/rspack_binding_builder", default-features = false } -rspack_binding_builder_macros = { version = "=0.7.1", path = "crates/rspack_binding_builder_macros", default-features = false } -rspack_browser = { version = "=0.7.1", path = "crates/rspack_browser", default-features = false } -rspack_browserslist = { version = "=0.7.1", path = "crates/rspack_browserslist", default-features = false } -rspack_cacheable = { version = "=0.7.1", path = "crates/rspack_cacheable", default-features = false } -rspack_cacheable_macros = { version = "=0.7.1", path = "crates/rspack_cacheable_macros", default-features = false } -rspack_collections = { version = "=0.7.1", path = "crates/rspack_collections", default-features = false } -rspack_core = { version = "=0.7.1", path = "crates/rspack_core", default-features = false } -rspack_error = { version = "=0.7.1", path = "crates/rspack_error", default-features = false } -rspack_fs = { version = "=0.7.1", path = "crates/rspack_fs", default-features = false } -rspack_futures = { version = "=0.7.1", path = "crates/rspack_futures", default-features = false } -rspack_hash = { version = "=0.7.1", path = "crates/rspack_hash", default-features = false } -rspack_hook = { version = "=0.7.1", path = "crates/rspack_hook", default-features = false } -rspack_ids = { version = "=0.7.1", path = "crates/rspack_ids", default-features = false } -rspack_javascript_compiler = { version = "=0.7.1", path = "crates/rspack_javascript_compiler", default-features = false } -rspack_loader_lightningcss = { version = "=0.7.1", path = "crates/rspack_loader_lightningcss", default-features = false } -rspack_loader_preact_refresh = { version = "=0.7.1", path = "crates/rspack_loader_preact_refresh", default-features = false } -rspack_loader_react_refresh = { version = "=0.7.1", path = "crates/rspack_loader_react_refresh", default-features = false } -rspack_loader_runner = { version = "=0.7.1", path = "crates/rspack_loader_runner", default-features = false } -rspack_loader_swc = { version = "=0.7.1", path = "crates/rspack_loader_swc", default-features = false } -rspack_loader_testing = { version = "=0.7.1", path = "crates/rspack_loader_testing", default-features = false } -rspack_location = { version = "=0.7.1", path = "crates/rspack_location", default-features = false } -rspack_macros = { version = "=0.7.1", path = "crates/rspack_macros", default-features = false } -rspack_napi = { version = "=0.7.1", path = "crates/rspack_napi", default-features = false } -rspack_napi_macros = { version = "=0.7.1", path = "crates/rspack_napi_macros", default-features = false } -rspack_paths = { version = "=0.7.1", path = "crates/rspack_paths", default-features = false } -rspack_plugin_asset = { version = "=0.7.1", path = "crates/rspack_plugin_asset", default-features = false } -rspack_plugin_banner = { version = "=0.7.1", path = "crates/rspack_plugin_banner", default-features = false } -rspack_plugin_case_sensitive = { version = "=0.7.1", path = "crates/rspack_plugin_case_sensitive", default-features = false } -rspack_plugin_circular_dependencies = { version = "=0.7.1", path = "crates/rspack_plugin_circular_dependencies", default-features = false } -rspack_plugin_copy = { version = "=0.7.1", path = "crates/rspack_plugin_copy", default-features = false } -rspack_plugin_css = { version = "=0.7.1", path = "crates/rspack_plugin_css", default-features = false } -rspack_plugin_css_chunking = { version = "=0.7.1", path = "crates/rspack_plugin_css_chunking", default-features = false } -rspack_plugin_devtool = { version = "=0.7.1", path = "crates/rspack_plugin_devtool", default-features = false } -rspack_plugin_dll = { version = "=0.7.1", path = "crates/rspack_plugin_dll", default-features = false } -rspack_plugin_dynamic_entry = { version = "=0.7.1", path = "crates/rspack_plugin_dynamic_entry", default-features = false } -rspack_plugin_ensure_chunk_conditions = { version = "=0.7.1", path = "crates/rspack_plugin_ensure_chunk_conditions", default-features = false } -rspack_plugin_entry = { version = "=0.7.1", path = "crates/rspack_plugin_entry", default-features = false } -rspack_plugin_esm_library = { version = "=0.7.1", path = "crates/rspack_plugin_esm_library", default-features = false } -rspack_plugin_externals = { version = "=0.7.1", path = "crates/rspack_plugin_externals", default-features = false } -rspack_plugin_extract_css = { version = "=0.7.1", path = "crates/rspack_plugin_extract_css", default-features = false } -rspack_plugin_hmr = { version = "=0.7.1", path = "crates/rspack_plugin_hmr", default-features = false } -rspack_plugin_html = { version = "=0.7.1", path = "crates/rspack_plugin_html", default-features = false } -rspack_plugin_ignore = { version = "=0.7.1", path = "crates/rspack_plugin_ignore", default-features = false } -rspack_plugin_javascript = { version = "=0.7.1", path = "crates/rspack_plugin_javascript", default-features = false } -rspack_plugin_json = { version = "=0.7.1", path = "crates/rspack_plugin_json", default-features = false } -rspack_plugin_lazy_compilation = { version = "=0.7.1", path = "crates/rspack_plugin_lazy_compilation", default-features = false } -rspack_plugin_library = { version = "=0.7.1", path = "crates/rspack_plugin_library", default-features = false } -rspack_plugin_lightning_css_minimizer = { version = "=0.7.1", path = "crates/rspack_plugin_lightning_css_minimizer", default-features = false } -rspack_plugin_limit_chunk_count = { version = "=0.7.1", path = "crates/rspack_plugin_limit_chunk_count", default-features = false } -rspack_plugin_merge_duplicate_chunks = { version = "=0.7.1", path = "crates/rspack_plugin_merge_duplicate_chunks", default-features = false } -rspack_plugin_mf = { version = "=0.7.1", path = "crates/rspack_plugin_mf", default-features = false } -rspack_plugin_module_info_header = { version = "=0.7.1", path = "crates/rspack_plugin_module_info_header", default-features = false } -rspack_plugin_module_replacement = { version = "=0.7.1", path = "crates/rspack_plugin_module_replacement", default-features = false } -rspack_plugin_no_emit_on_errors = { version = "=0.7.1", path = "crates/rspack_plugin_no_emit_on_errors", default-features = false } -rspack_plugin_progress = { version = "=0.7.1", path = "crates/rspack_plugin_progress", default-features = false } -rspack_plugin_real_content_hash = { version = "=0.7.1", path = "crates/rspack_plugin_real_content_hash", default-features = false } -rspack_plugin_remove_duplicate_modules = { version = "=0.7.1", path = "crates/rspack_plugin_remove_duplicate_modules", default-features = false } -rspack_plugin_remove_empty_chunks = { version = "=0.7.1", path = "crates/rspack_plugin_remove_empty_chunks", default-features = false } -rspack_plugin_rsdoctor = { version = "=0.7.1", path = "crates/rspack_plugin_rsdoctor", default-features = false } -rspack_plugin_rslib = { version = "=0.7.1", path = "crates/rspack_plugin_rslib", default-features = false } -rspack_plugin_rstest = { version = "=0.7.1", path = "crates/rspack_plugin_rstest", default-features = false } -rspack_plugin_runtime = { version = "=0.7.1", path = "crates/rspack_plugin_runtime", default-features = false } -rspack_plugin_runtime_chunk = { version = "=0.7.1", path = "crates/rspack_plugin_runtime_chunk", default-features = false } -rspack_plugin_schemes = { version = "=0.7.1", path = "crates/rspack_plugin_schemes", default-features = false } -rspack_plugin_size_limits = { version = "=0.7.1", path = "crates/rspack_plugin_size_limits", default-features = false } -rspack_plugin_split_chunks = { version = "=0.7.1", path = "crates/rspack_plugin_split_chunks", default-features = false } -rspack_plugin_sri = { version = "=0.7.1", path = "crates/rspack_plugin_sri", default-features = false } -rspack_plugin_swc_js_minimizer = { version = "=0.7.1", path = "crates/rspack_plugin_swc_js_minimizer", default-features = false } -rspack_plugin_wasm = { version = "=0.7.1", path = "crates/rspack_plugin_wasm", default-features = false } -rspack_plugin_web_worker_template = { version = "=0.7.1", path = "crates/rspack_plugin_web_worker_template", default-features = false } -rspack_plugin_worker = { version = "=0.7.1", path = "crates/rspack_plugin_worker", default-features = false } -rspack_regex = { version = "=0.7.1", path = "crates/rspack_regex", default-features = false } -rspack_storage = { version = "=0.7.1", path = "crates/rspack_storage", default-features = false } -rspack_swc_plugin_import = { version = "=0.7.1", path = "crates/swc_plugin_import", default-features = false } -rspack_swc_plugin_ts_collector = { version = "=0.7.1", path = "crates/swc_plugin_ts_collector", default-features = false } -rspack_tasks = { version = "=0.7.1", path = "crates/rspack_tasks", default-features = false } -rspack_tracing = { version = "=0.7.1", path = "crates/rspack_tracing", default-features = false } -rspack_tracing_perfetto = { version = "=0.7.1", path = "crates/rspack_tracing_perfetto", default-features = false } -rspack_util = { version = "=0.7.1", path = "crates/rspack_util", default-features = false } -rspack_watcher = { version = "=0.7.1", path = "crates/rspack_watcher", default-features = false } -rspack_workspace = { version = "=0.7.1", path = "crates/rspack_workspace", default-features = false } +rspack = { version = "=0.7.2", path = "crates/rspack", default-features = false } +rspack_allocator = { version = "=0.7.2", path = "crates/rspack_allocator", default-features = false } +rspack_binding_api = { version = "=0.7.2", path = "crates/rspack_binding_api", default-features = false } +rspack_binding_build = { version = "=0.7.2", path = "crates/rspack_binding_build", default-features = false } +rspack_binding_builder = { version = "=0.7.2", path = "crates/rspack_binding_builder", default-features = false } +rspack_binding_builder_macros = { version = "=0.7.2", path = "crates/rspack_binding_builder_macros", default-features = false } +rspack_browser = { version = "=0.7.2", path = "crates/rspack_browser", default-features = false } +rspack_browserslist = { version = "=0.7.2", path = "crates/rspack_browserslist", default-features = false } +rspack_cacheable = { version = "=0.7.2", path = "crates/rspack_cacheable", default-features = false } +rspack_cacheable_macros = { version = "=0.7.2", path = "crates/rspack_cacheable_macros", default-features = false } +rspack_collections = { version = "=0.7.2", path = "crates/rspack_collections", default-features = false } +rspack_core = { version = "=0.7.2", path = "crates/rspack_core", default-features = false } +rspack_error = { version = "=0.7.2", path = "crates/rspack_error", default-features = false } +rspack_fs = { version = "=0.7.2", path = "crates/rspack_fs", default-features = false } +rspack_futures = { version = "=0.7.2", path = "crates/rspack_futures", default-features = false } +rspack_hash = { version = "=0.7.2", path = "crates/rspack_hash", default-features = false } +rspack_hook = { version = "=0.7.2", path = "crates/rspack_hook", default-features = false } +rspack_ids = { version = "=0.7.2", path = "crates/rspack_ids", default-features = false } +rspack_javascript_compiler = { version = "=0.7.2", path = "crates/rspack_javascript_compiler", default-features = false } +rspack_loader_lightningcss = { version = "=0.7.2", path = "crates/rspack_loader_lightningcss", default-features = false } +rspack_loader_preact_refresh = { version = "=0.7.2", path = "crates/rspack_loader_preact_refresh", default-features = false } +rspack_loader_react_refresh = { version = "=0.7.2", path = "crates/rspack_loader_react_refresh", default-features = false } +rspack_loader_runner = { version = "=0.7.2", path = "crates/rspack_loader_runner", default-features = false } +rspack_loader_swc = { version = "=0.7.2", path = "crates/rspack_loader_swc", default-features = false } +rspack_loader_testing = { version = "=0.7.2", path = "crates/rspack_loader_testing", default-features = false } +rspack_location = { version = "=0.7.2", path = "crates/rspack_location", default-features = false } +rspack_macros = { version = "=0.7.2", path = "crates/rspack_macros", default-features = false } +rspack_napi = { version = "=0.7.2", path = "crates/rspack_napi", default-features = false } +rspack_napi_macros = { version = "=0.7.2", path = "crates/rspack_napi_macros", default-features = false } +rspack_paths = { version = "=0.7.2", path = "crates/rspack_paths", default-features = false } +rspack_plugin_asset = { version = "=0.7.2", path = "crates/rspack_plugin_asset", default-features = false } +rspack_plugin_banner = { version = "=0.7.2", path = "crates/rspack_plugin_banner", default-features = false } +rspack_plugin_case_sensitive = { version = "=0.7.2", path = "crates/rspack_plugin_case_sensitive", default-features = false } +rspack_plugin_circular_dependencies = { version = "=0.7.2", path = "crates/rspack_plugin_circular_dependencies", default-features = false } +rspack_plugin_copy = { version = "=0.7.2", path = "crates/rspack_plugin_copy", default-features = false } +rspack_plugin_css = { version = "=0.7.2", path = "crates/rspack_plugin_css", default-features = false } +rspack_plugin_css_chunking = { version = "=0.7.2", path = "crates/rspack_plugin_css_chunking", default-features = false } +rspack_plugin_devtool = { version = "=0.7.2", path = "crates/rspack_plugin_devtool", default-features = false } +rspack_plugin_dll = { version = "=0.7.2", path = "crates/rspack_plugin_dll", default-features = false } +rspack_plugin_dynamic_entry = { version = "=0.7.2", path = "crates/rspack_plugin_dynamic_entry", default-features = false } +rspack_plugin_ensure_chunk_conditions = { version = "=0.7.2", path = "crates/rspack_plugin_ensure_chunk_conditions", default-features = false } +rspack_plugin_entry = { version = "=0.7.2", path = "crates/rspack_plugin_entry", default-features = false } +rspack_plugin_esm_library = { version = "=0.7.2", path = "crates/rspack_plugin_esm_library", default-features = false } +rspack_plugin_externals = { version = "=0.7.2", path = "crates/rspack_plugin_externals", default-features = false } +rspack_plugin_extract_css = { version = "=0.7.2", path = "crates/rspack_plugin_extract_css", default-features = false } +rspack_plugin_hmr = { version = "=0.7.2", path = "crates/rspack_plugin_hmr", default-features = false } +rspack_plugin_html = { version = "=0.7.2", path = "crates/rspack_plugin_html", default-features = false } +rspack_plugin_ignore = { version = "=0.7.2", path = "crates/rspack_plugin_ignore", default-features = false } +rspack_plugin_javascript = { version = "=0.7.2", path = "crates/rspack_plugin_javascript", default-features = false } +rspack_plugin_json = { version = "=0.7.2", path = "crates/rspack_plugin_json", default-features = false } +rspack_plugin_lazy_compilation = { version = "=0.7.2", path = "crates/rspack_plugin_lazy_compilation", default-features = false } +rspack_plugin_library = { version = "=0.7.2", path = "crates/rspack_plugin_library", default-features = false } +rspack_plugin_lightning_css_minimizer = { version = "=0.7.2", path = "crates/rspack_plugin_lightning_css_minimizer", default-features = false } +rspack_plugin_limit_chunk_count = { version = "=0.7.2", path = "crates/rspack_plugin_limit_chunk_count", default-features = false } +rspack_plugin_merge_duplicate_chunks = { version = "=0.7.2", path = "crates/rspack_plugin_merge_duplicate_chunks", default-features = false } +rspack_plugin_mf = { version = "=0.7.2", path = "crates/rspack_plugin_mf", default-features = false } +rspack_plugin_module_info_header = { version = "=0.7.2", path = "crates/rspack_plugin_module_info_header", default-features = false } +rspack_plugin_module_replacement = { version = "=0.7.2", path = "crates/rspack_plugin_module_replacement", default-features = false } +rspack_plugin_no_emit_on_errors = { version = "=0.7.2", path = "crates/rspack_plugin_no_emit_on_errors", default-features = false } +rspack_plugin_progress = { version = "=0.7.2", path = "crates/rspack_plugin_progress", default-features = false } +rspack_plugin_real_content_hash = { version = "=0.7.2", path = "crates/rspack_plugin_real_content_hash", default-features = false } +rspack_plugin_remove_duplicate_modules = { version = "=0.7.2", path = "crates/rspack_plugin_remove_duplicate_modules", default-features = false } +rspack_plugin_remove_empty_chunks = { version = "=0.7.2", path = "crates/rspack_plugin_remove_empty_chunks", default-features = false } +rspack_plugin_rsdoctor = { version = "=0.7.2", path = "crates/rspack_plugin_rsdoctor", default-features = false } +rspack_plugin_rslib = { version = "=0.7.2", path = "crates/rspack_plugin_rslib", default-features = false } +rspack_plugin_rstest = { version = "=0.7.2", path = "crates/rspack_plugin_rstest", default-features = false } +rspack_plugin_runtime = { version = "=0.7.2", path = "crates/rspack_plugin_runtime", default-features = false } +rspack_plugin_runtime_chunk = { version = "=0.7.2", path = "crates/rspack_plugin_runtime_chunk", default-features = false } +rspack_plugin_schemes = { version = "=0.7.2", path = "crates/rspack_plugin_schemes", default-features = false } +rspack_plugin_size_limits = { version = "=0.7.2", path = "crates/rspack_plugin_size_limits", default-features = false } +rspack_plugin_split_chunks = { version = "=0.7.2", path = "crates/rspack_plugin_split_chunks", default-features = false } +rspack_plugin_sri = { version = "=0.7.2", path = "crates/rspack_plugin_sri", default-features = false } +rspack_plugin_swc_js_minimizer = { version = "=0.7.2", path = "crates/rspack_plugin_swc_js_minimizer", default-features = false } +rspack_plugin_wasm = { version = "=0.7.2", path = "crates/rspack_plugin_wasm", default-features = false } +rspack_plugin_web_worker_template = { version = "=0.7.2", path = "crates/rspack_plugin_web_worker_template", default-features = false } +rspack_plugin_worker = { version = "=0.7.2", path = "crates/rspack_plugin_worker", default-features = false } +rspack_regex = { version = "=0.7.2", path = "crates/rspack_regex", default-features = false } +rspack_storage = { version = "=0.7.2", path = "crates/rspack_storage", default-features = false } +rspack_swc_plugin_import = { version = "=0.7.2", path = "crates/swc_plugin_import", default-features = false } +rspack_swc_plugin_ts_collector = { version = "=0.7.2", path = "crates/swc_plugin_ts_collector", default-features = false } +rspack_tasks = { version = "=0.7.2", path = "crates/rspack_tasks", default-features = false } +rspack_tracing = { version = "=0.7.2", path = "crates/rspack_tracing", default-features = false } +rspack_tracing_perfetto = { version = "=0.7.2", path = "crates/rspack_tracing_perfetto", default-features = false } +rspack_util = { version = "=0.7.2", path = "crates/rspack_util", default-features = false } +rspack_watcher = { version = "=0.7.2", path = "crates/rspack_watcher", default-features = false } +rspack_workspace = { version = "=0.7.2", path = "crates/rspack_workspace", default-features = false } [workspace.metadata.release] rate-limit = { existing-packages = 70, new-packages = 70 } diff --git a/crates/node_binding/package.json b/crates/node_binding/package.json index 589d84950067..4834bb072882 100644 --- a/crates/node_binding/package.json +++ b/crates/node_binding/package.json @@ -1,6 +1,6 @@ { "name": "@rspack/binding", - "version": "1.7.1", + "version": "1.7.2", "license": "MIT", "description": "Node binding for rspack", "main": "binding.js", diff --git a/crates/rspack_workspace/src/generated.rs b/crates/rspack_workspace/src/generated.rs index e000e5a786fd..d7a2d70611df 100644 --- a/crates/rspack_workspace/src/generated.rs +++ b/crates/rspack_workspace/src/generated.rs @@ -6,10 +6,10 @@ pub const fn rspack_swc_core_version() -> &'static str { /// The version of the JavaScript `@rspack/core` package. pub const fn rspack_pkg_version() -> &'static str { - "1.7.1" + "1.7.2" } /// The version of the Rust workspace in the root `Cargo.toml` of the repository. pub const fn rspack_workspace_version() -> &'static str { - "0.7.1" + "0.7.2" } diff --git a/npm/darwin-arm64/package.json b/npm/darwin-arm64/package.json index 346b1ac400e2..999130a12913 100644 --- a/npm/darwin-arm64/package.json +++ b/npm/darwin-arm64/package.json @@ -1,6 +1,6 @@ { "name": "@rspack/binding-darwin-arm64", - "version": "1.7.1", + "version": "1.7.2", "license": "MIT", "description": "Node binding for rspack", "main": "rspack.darwin-arm64.node", diff --git a/npm/darwin-x64/package.json b/npm/darwin-x64/package.json index af3141704fdc..a0c1eaccaa7d 100644 --- a/npm/darwin-x64/package.json +++ b/npm/darwin-x64/package.json @@ -1,6 +1,6 @@ { "name": "@rspack/binding-darwin-x64", - "version": "1.7.1", + "version": "1.7.2", "license": "MIT", "description": "Node binding for rspack", "main": "rspack.darwin-x64.node", diff --git a/npm/linux-arm64-gnu/package.json b/npm/linux-arm64-gnu/package.json index 132a900f5cc4..15c75aa10a12 100644 --- a/npm/linux-arm64-gnu/package.json +++ b/npm/linux-arm64-gnu/package.json @@ -1,6 +1,6 @@ { "name": "@rspack/binding-linux-arm64-gnu", - "version": "1.7.1", + "version": "1.7.2", "license": "MIT", "description": "Node binding for rspack", "main": "rspack.linux-arm64-gnu.node", diff --git a/npm/linux-arm64-musl/package.json b/npm/linux-arm64-musl/package.json index 10707cbb10c8..5a929e705875 100644 --- a/npm/linux-arm64-musl/package.json +++ b/npm/linux-arm64-musl/package.json @@ -1,6 +1,6 @@ { "name": "@rspack/binding-linux-arm64-musl", - "version": "1.7.1", + "version": "1.7.2", "license": "MIT", "description": "Node binding for rspack", "main": "rspack.linux-arm64-musl.node", diff --git a/npm/linux-x64-gnu/package.json b/npm/linux-x64-gnu/package.json index a1666acaf3ae..5ab4e868a7b9 100644 --- a/npm/linux-x64-gnu/package.json +++ b/npm/linux-x64-gnu/package.json @@ -1,6 +1,6 @@ { "name": "@rspack/binding-linux-x64-gnu", - "version": "1.7.1", + "version": "1.7.2", "license": "MIT", "description": "Node binding for rspack", "main": "rspack.linux-x64-gnu.node", diff --git a/npm/linux-x64-musl/package.json b/npm/linux-x64-musl/package.json index 3ab820992cc0..0a38fcde1628 100644 --- a/npm/linux-x64-musl/package.json +++ b/npm/linux-x64-musl/package.json @@ -1,6 +1,6 @@ { "name": "@rspack/binding-linux-x64-musl", - "version": "1.7.1", + "version": "1.7.2", "license": "MIT", "description": "Node binding for rspack", "main": "rspack.linux-x64-musl.node", diff --git a/npm/wasm32-wasi/package.json b/npm/wasm32-wasi/package.json index 767fe277d1c7..988545902273 100644 --- a/npm/wasm32-wasi/package.json +++ b/npm/wasm32-wasi/package.json @@ -1,6 +1,6 @@ { "name": "@rspack/binding-wasm32-wasi", - "version": "1.7.1", + "version": "1.7.2", "license": "MIT", "description": "Node binding for rspack", "main": "rspack.wasi.cjs", diff --git a/npm/win32-arm64-msvc/package.json b/npm/win32-arm64-msvc/package.json index 69aafc985b72..f89d1112ab91 100644 --- a/npm/win32-arm64-msvc/package.json +++ b/npm/win32-arm64-msvc/package.json @@ -1,6 +1,6 @@ { "name": "@rspack/binding-win32-arm64-msvc", - "version": "1.7.1", + "version": "1.7.2", "license": "MIT", "description": "Node binding for rspack", "main": "rspack.win32-arm64-msvc.node", diff --git a/npm/win32-ia32-msvc/package.json b/npm/win32-ia32-msvc/package.json index babe2c959756..9e05c6e7b227 100644 --- a/npm/win32-ia32-msvc/package.json +++ b/npm/win32-ia32-msvc/package.json @@ -1,6 +1,6 @@ { "name": "@rspack/binding-win32-ia32-msvc", - "version": "1.7.1", + "version": "1.7.2", "license": "MIT", "description": "Node binding for rspack", "main": "rspack.win32-ia32-msvc.node", diff --git a/npm/win32-x64-msvc/package.json b/npm/win32-x64-msvc/package.json index 45c49ae1c99a..9a37ad023cb1 100644 --- a/npm/win32-x64-msvc/package.json +++ b/npm/win32-x64-msvc/package.json @@ -1,6 +1,6 @@ { "name": "@rspack/binding-win32-x64-msvc", - "version": "1.7.1", + "version": "1.7.2", "license": "MIT", "description": "Node binding for rspack", "main": "rspack.win32-x64-msvc.node", diff --git a/package.json b/package.json index 7467cede552a..bb382484ad95 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "monorepo", - "version": "1.7.1", + "version": "1.7.2", "license": "MIT", "description": "The fast Rust-based web bundler with webpack-compatible API", "private": true, diff --git a/packages/create-rspack/package.json b/packages/create-rspack/package.json index e030e8a2e13d..899338ede751 100644 --- a/packages/create-rspack/package.json +++ b/packages/create-rspack/package.json @@ -1,6 +1,6 @@ { "name": "create-rspack", - "version": "1.7.1", + "version": "1.7.2", "homepage": "https://rspack.rs", "bugs": "https://github.com/web-infra-dev/rspack/issues", "repository": { diff --git a/packages/rspack-browser/package.json b/packages/rspack-browser/package.json index 3faf2bb1e88a..c6c5abcdf943 100644 --- a/packages/rspack-browser/package.json +++ b/packages/rspack-browser/package.json @@ -1,6 +1,6 @@ { "name": "@rspack/browser", - "version": "1.7.1", + "version": "1.7.2", "webpackVersion": "5.75.0", "license": "MIT", "description": "Rspack for running in the browser. This is still in early stage and may not follow the semver.", diff --git a/packages/rspack-cli/package.json b/packages/rspack-cli/package.json index 2c66e0ac6f89..0e860620b40f 100644 --- a/packages/rspack-cli/package.json +++ b/packages/rspack-cli/package.json @@ -1,6 +1,6 @@ { "name": "@rspack/cli", - "version": "1.7.1", + "version": "1.7.2", "description": "CLI for rspack", "homepage": "https://rspack.rs", "bugs": "https://github.com/web-infra-dev/rspack/issues", diff --git a/packages/rspack-test-tools/package.json b/packages/rspack-test-tools/package.json index ec4a163380bf..52bab598adb4 100644 --- a/packages/rspack-test-tools/package.json +++ b/packages/rspack-test-tools/package.json @@ -1,6 +1,6 @@ { "name": "@rspack/test-tools", - "version": "1.7.1", + "version": "1.7.2", "license": "MIT", "description": "Test tools for rspack", "main": "dist/index.js", diff --git a/packages/rspack/package.json b/packages/rspack/package.json index 2be157ff09cd..1f19f871cfa5 100644 --- a/packages/rspack/package.json +++ b/packages/rspack/package.json @@ -1,6 +1,6 @@ { "name": "@rspack/core", - "version": "1.7.1", + "version": "1.7.2", "webpackVersion": "5.75.0", "license": "MIT", "description": "The fast Rust-based web bundler with webpack-compatible API", From 0f1b1e48a6aec8c3872c8c596269957509a37829 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 14 Jan 2026 02:11:00 +0000 Subject: [PATCH 52/87] chore(deps): update dependency @rspack/plugin-react-refresh to ^1.6.0 (#12718) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- examples/react/package.json | 2 +- .../template-react-js/package.json | 2 +- .../template-react-ts/package.json | 2 +- pnpm-lock.yaml | 32 +++++++++---------- tests/bench/package.json | 2 +- tests/e2e/package.json | 2 +- tests/rspack-test/package.json | 2 +- 7 files changed, 22 insertions(+), 22 deletions(-) diff --git a/examples/react/package.json b/examples/react/package.json index 5d36f137d9b6..136b1c245d66 100644 --- a/examples/react/package.json +++ b/examples/react/package.json @@ -14,7 +14,7 @@ "devDependencies": { "@rspack/cli": "workspace:*", "@rspack/core": "workspace:*", - "@rspack/plugin-react-refresh": "^1.5.3", + "@rspack/plugin-react-refresh": "^1.6.0", "@types/react": "^19.2.7", "@types/react-dom": "^19.2.3", "react-refresh": "^0.18.0", diff --git a/packages/create-rspack/template-react-js/package.json b/packages/create-rspack/template-react-js/package.json index 7598dd7d783a..5490a95adaad 100644 --- a/packages/create-rspack/template-react-js/package.json +++ b/packages/create-rspack/template-react-js/package.json @@ -14,7 +14,7 @@ "devDependencies": { "@rspack/cli": "workspace:*", "@rspack/core": "workspace:*", - "@rspack/plugin-react-refresh": "^1.5.3", + "@rspack/plugin-react-refresh": "^1.6.0", "@types/react": "^19.2.7", "@types/react-dom": "^19.2.3", "react-refresh": "^0.18.0" diff --git a/packages/create-rspack/template-react-ts/package.json b/packages/create-rspack/template-react-ts/package.json index 556797953079..7e0082ccd117 100644 --- a/packages/create-rspack/template-react-ts/package.json +++ b/packages/create-rspack/template-react-ts/package.json @@ -14,7 +14,7 @@ "devDependencies": { "@rspack/cli": "workspace:*", "@rspack/core": "workspace:*", - "@rspack/plugin-react-refresh": "^1.5.3", + "@rspack/plugin-react-refresh": "^1.6.0", "@types/react": "^19.2.7", "@types/react-dom": "^19.2.3", "react-refresh": "^0.18.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 787fb12e404f..80ba4ded1652 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -163,8 +163,8 @@ importers: specifier: workspace:* version: link:../../packages/rspack '@rspack/plugin-react-refresh': - specifier: ^1.5.3 - version: 1.5.3(react-refresh@0.18.0) + specifier: ^1.6.0 + version: 1.6.0(react-refresh@0.18.0) '@types/react': specifier: ^19.2.7 version: 19.2.7 @@ -243,8 +243,8 @@ importers: specifier: workspace:* version: link:../../rspack '@rspack/plugin-react-refresh': - specifier: ^1.5.3 - version: 1.5.3(react-refresh@0.18.0) + specifier: ^1.6.0 + version: 1.6.0(react-refresh@0.18.0) '@types/react': specifier: ^19.2.7 version: 19.2.7 @@ -271,8 +271,8 @@ importers: specifier: workspace:* version: link:../../rspack '@rspack/plugin-react-refresh': - specifier: ^1.5.3 - version: 1.5.3(react-refresh@0.18.0) + specifier: ^1.6.0 + version: 1.6.0(react-refresh@0.18.0) '@types/react': specifier: ^19.2.7 version: 19.2.7 @@ -625,8 +625,8 @@ importers: specifier: workspace:* version: link:../../packages/rspack '@rspack/plugin-react-refresh': - specifier: ^1.5.3 - version: 1.5.3(react-refresh@0.18.0) + specifier: ^1.6.0 + version: 1.6.0(react-refresh@0.18.0) '@types/react': specifier: ^19.2.7 version: 19.2.7 @@ -655,8 +655,8 @@ importers: specifier: ~1.1.5 version: 1.1.5(@rspack/core@packages+rspack)(@types/express@4.17.23)(webpack@5.102.1) '@rspack/plugin-react-refresh': - specifier: ^1.5.3 - version: 1.5.3(react-refresh@0.18.0) + specifier: ^1.6.0 + version: 1.6.0(react-refresh@0.18.0) '@swc/helpers': specifier: 0.5.18 version: 0.5.18 @@ -727,8 +727,8 @@ importers: specifier: 1.1.4 version: 1.1.4(@prefresh/core@1.5.7(preact@10.27.2))(@prefresh/utils@1.2.1) '@rspack/plugin-react-refresh': - specifier: ^1.5.3 - version: 1.5.3(react-refresh@0.18.0) + specifier: ^1.6.0 + version: 1.6.0(react-refresh@0.18.0) '@rspack/test-tools': specifier: workspace:* version: link:../../packages/rspack-test-tools @@ -3476,8 +3476,8 @@ packages: '@prefresh/core': ^1.5.0 '@prefresh/utils': ^1.2.0 - '@rspack/plugin-react-refresh@1.5.3': - resolution: {integrity: sha512-VOnQMf3YOHkTqJ0+BJbrYga4tQAWNwoAnkgwRauXB4HOyCc5wLfBs9DcOFla/2usnRT3Sq6CMVhXmdPobwAoTA==} + '@rspack/plugin-react-refresh@1.6.0': + resolution: {integrity: sha512-OO53gkrte/Ty4iRXxxM6lkwPGxsSsupFKdrPFnjwFIYrPvFLjeolAl5cTx+FzO5hYygJiGnw7iEKTmD+ptxqDA==} peerDependencies: react-refresh: '>=0.10.0 <1.0.0' webpack-hot-middleware: 2.x @@ -10829,7 +10829,7 @@ snapshots: '@rsbuild/plugin-react@1.4.2(@rsbuild/core@1.6.15)': dependencies: '@rsbuild/core': 1.6.15 - '@rspack/plugin-react-refresh': 1.5.3(react-refresh@0.18.0) + '@rspack/plugin-react-refresh': 1.6.0(react-refresh@0.18.0) react-refresh: 0.18.0 transitivePeerDependencies: - webpack-hot-middleware @@ -11080,7 +11080,7 @@ snapshots: '@prefresh/core': 1.5.7(preact@10.27.2) '@prefresh/utils': 1.2.1 - '@rspack/plugin-react-refresh@1.5.3(react-refresh@0.18.0)': + '@rspack/plugin-react-refresh@1.6.0(react-refresh@0.18.0)': dependencies: error-stack-parser: 2.1.4 html-entities: 2.6.0 diff --git a/tests/bench/package.json b/tests/bench/package.json index c7a40f4f3276..a3417831cffa 100644 --- a/tests/bench/package.json +++ b/tests/bench/package.json @@ -10,7 +10,7 @@ "@codspeed/vitest-plugin": "^4.0.1", "@rspack/cli": "workspace:*", "@rspack/core": "workspace:*", - "@rspack/plugin-react-refresh": "^1.5.3", + "@rspack/plugin-react-refresh": "^1.6.0", "@types/react": "^19.2.7", "@types/react-dom": "^19.2.3", "vitest": "^3.2.4" diff --git a/tests/e2e/package.json b/tests/e2e/package.json index 544df3c9b94e..e9de9b489e9b 100644 --- a/tests/e2e/package.json +++ b/tests/e2e/package.json @@ -13,7 +13,7 @@ "core-js": "3.47.0", "@rspack/core": "workspace:*", "@rspack/dev-server": "~1.1.5", - "@rspack/plugin-react-refresh": "^1.5.3", + "@rspack/plugin-react-refresh": "^1.6.0", "@swc/helpers": "0.5.18", "@types/fs-extra": "11.0.4", "babel-loader": "^10.0.0", diff --git a/tests/rspack-test/package.json b/tests/rspack-test/package.json index 7b0238c94597..e1ad121a7ae5 100644 --- a/tests/rspack-test/package.json +++ b/tests/rspack-test/package.json @@ -17,7 +17,7 @@ "@rspack/core": "workspace:*", "@rspack/binding-testing": "workspace:*", "@rspack/plugin-preact-refresh": "1.1.4", - "@rspack/plugin-react-refresh": "^1.5.3", + "@rspack/plugin-react-refresh": "^1.6.0", "@rspack/test-tools": "workspace:*", "@rstest/core": "^0.7.8", "@swc/helpers": "0.5.18", From a10781f8ef59870c1cbe7f3eb327b08c71bbdb7f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 14 Jan 2026 02:13:37 +0000 Subject: [PATCH 53/87] chore(deps): update dependency @shikijs/transformers to ^3.21.0 (#12719) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- pnpm-lock.yaml | 32 +++++++++++++++++++++++++------- website/package.json | 2 +- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 80ba4ded1652..1cf733f19309 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -977,8 +977,8 @@ importers: specifier: 2.0.0-rc.4 version: 2.0.0-rc.4(@rspress/core@2.0.0-rc.4(@types/react@19.2.7)) '@shikijs/transformers': - specifier: ^3.20.0 - version: 3.20.0 + specifier: ^3.21.0 + version: 3.21.0 '@types/node': specifier: ^20.19.27 version: 20.19.27 @@ -3631,6 +3631,9 @@ packages: '@shikijs/core@3.20.0': resolution: {integrity: sha512-f2ED7HYV4JEk827mtMDwe/yQ25pRiXZmtHjWF8uzZKuKiEsJR7Ce1nuQ+HhV9FzDcbIo4ObBCD9GPTzNuy9S1g==} + '@shikijs/core@3.21.0': + resolution: {integrity: sha512-AXSQu/2n1UIQekY8euBJlvFYZIw0PHY63jUzGbrOma4wPxzznJXTXkri+QcHeBNaFxiiOljKxxJkVSoB3PjbyA==} + '@shikijs/engine-javascript@3.20.0': resolution: {integrity: sha512-OFx8fHAZuk7I42Z9YAdZ95To6jDePQ9Rnfbw9uSRTSbBhYBp1kEOKv/3jOimcj3VRUKusDYM6DswLauwfhboLg==} @@ -3646,12 +3649,15 @@ packages: '@shikijs/themes@3.20.0': resolution: {integrity: sha512-U1NSU7Sl26Q7ErRvJUouArxfM2euWqq1xaSrbqMu2iqa+tSp0D1Yah8216sDYbdDHw4C8b75UpE65eWorm2erQ==} - '@shikijs/transformers@3.20.0': - resolution: {integrity: sha512-PrHHMRr3Q5W1qB/42kJW6laqFyWdhrPF2hNR9qjOm1xcSiAO3hAHo7HaVyHE6pMyevmy3i51O8kuGGXC78uK3g==} + '@shikijs/transformers@3.21.0': + resolution: {integrity: sha512-CZwvCWWIiRRiFk9/JKzdEooakAP8mQDtBOQ1TKiCaS2E1bYtyBCOkUzS8akO34/7ufICQ29oeSfkb3tT5KtrhA==} '@shikijs/types@3.20.0': resolution: {integrity: sha512-lhYAATn10nkZcBQ0BlzSbJA3wcmL5MXUUF8d2Zzon6saZDlToKaiRX60n2+ZaHJCmXEcZRWNzn+k9vplr8Jhsw==} + '@shikijs/types@3.21.0': + resolution: {integrity: sha512-zGrWOxZ0/+0ovPY7PvBU2gIS9tmhSUUt30jAcNV0Bq0gb2S98gwfjIs1vxlmH5zM7/4YxLamT6ChlqqAJmPPjA==} + '@shikijs/vscode-textmate@10.0.2': resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==} @@ -11290,6 +11296,13 @@ snapshots: '@types/hast': 3.0.4 hast-util-to-html: 9.0.5 + '@shikijs/core@3.21.0': + dependencies: + '@shikijs/types': 3.21.0 + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.4 + hast-util-to-html: 9.0.5 + '@shikijs/engine-javascript@3.20.0': dependencies: '@shikijs/types': 3.20.0 @@ -11318,16 +11331,21 @@ snapshots: dependencies: '@shikijs/types': 3.20.0 - '@shikijs/transformers@3.20.0': + '@shikijs/transformers@3.21.0': dependencies: - '@shikijs/core': 3.20.0 - '@shikijs/types': 3.20.0 + '@shikijs/core': 3.21.0 + '@shikijs/types': 3.21.0 '@shikijs/types@3.20.0': dependencies: '@shikijs/vscode-textmate': 10.0.2 '@types/hast': 3.0.4 + '@shikijs/types@3.21.0': + dependencies: + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.4 + '@shikijs/vscode-textmate@10.0.2': {} '@sinclair/typebox@0.27.8': {} diff --git a/website/package.json b/website/package.json index 10b0e28bfef5..210d6464b294 100644 --- a/website/package.json +++ b/website/package.json @@ -33,7 +33,7 @@ "@rspress/plugin-llms": "2.0.0-rc.4", "@rspress/plugin-rss": "2.0.0-rc.4", "@rspress/plugin-sitemap": "2.0.0-rc.4", - "@shikijs/transformers": "^3.20.0", + "@shikijs/transformers": "^3.21.0", "@types/node": "^20.19.27", "@types/react": "^19.2.7", "@types/semver": "^7.7.1", From 0ddce9d224b5d7b447236996fba31bb85cfebef6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 14 Jan 2026 02:26:37 +0000 Subject: [PATCH 54/87] chore(deps): update patch crates (#12716) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 132 ++++++++++++++++++++++++++--------------------------- Cargo.toml | 4 +- 2 files changed, 68 insertions(+), 68 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2b67d404c6a2..dc5f4b2d2bde 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -185,7 +185,7 @@ checksum = "2eb025ef00a6da925cf40870b9c8d008526b6004ece399cb0974209720f0b194" dependencies = [ "quote", "swc_macros_common", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -196,7 +196,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -207,7 +207,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -224,7 +224,7 @@ checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -449,7 +449,7 @@ checksum = "523363cbe1df49b68215efdf500b103ac3b0fb4836aed6d15689a076eadb8fff" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -689,7 +689,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -1096,7 +1096,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -1146,7 +1146,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -1157,7 +1157,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -1240,7 +1240,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -1250,7 +1250,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ "derive_builder_core", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -1270,7 +1270,7 @@ checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", "unicode-xid", ] @@ -1298,7 +1298,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -1396,7 +1396,7 @@ checksum = "1ccd72f8e71e242f71705868f5478fe7592a6e194c06330d8732421ffdbc554c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -1524,7 +1524,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5ff35a391aef949120a0340d690269b3d9f63460a6106e99bd07b961f345ea9" dependencies = [ "swc_macros_common", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -1609,7 +1609,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -1972,7 +1972,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -2115,7 +2115,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -2469,7 +2469,7 @@ checksum = "db5b29714e950dbb20d5e6f74f9dcec4edbcc1067bb7f8ed198c097b8c1a818b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -2542,7 +2542,7 @@ checksum = "1bb5c1d8184f13f7d0ccbeeca0def2f9a181bce2624302793005f5ca8aa62e5e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -2580,7 +2580,7 @@ dependencies = [ "napi-derive-backend", "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -2593,7 +2593,7 @@ dependencies = [ "proc-macro2", "quote", "semver", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -2966,7 +2966,7 @@ dependencies = [ "phf_shared", "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -3111,7 +3111,7 @@ dependencies = [ "itertools 0.14.0", "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -3160,7 +3160,7 @@ checksum = "ca414edb151b4c8d125c12566ab0d74dc9cdba36fb80eb7b848c15f495fd32d1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -3183,7 +3183,7 @@ checksum = "938543690519c20c3a480d20a8efcc8e69abeb44093ab1df4e7c1f81f26c677a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -3308,7 +3308,7 @@ checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -3438,7 +3438,7 @@ checksum = "09cb82b74b4810f07e460852c32f522e979787691b0b7b7439fe473e49d49b2f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -3524,7 +3524,7 @@ checksum = "125d6c4fea52a20e2baaa381c122e111a825ac4c3cccdbb50605805f025d7197" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -3689,7 +3689,7 @@ dependencies = [ "proc-macro2", "quote", "rspack_binding_builder", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -3750,7 +3750,7 @@ name = "rspack_cacheable_macros" version = "0.7.2" dependencies = [ "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -4089,7 +4089,7 @@ version = "0.7.2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -4128,7 +4128,7 @@ version = "0.7.2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -5330,7 +5330,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -5504,9 +5504,9 @@ dependencies = [ [[package]] name = "smol_str" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3498b0a27f93ef1402f20eefacfaa1691272ac4eca1cdc8c596cb0a245d6cbf5" +checksum = "0f7a918bd2a9951d18ee6e48f076843e8e73a9a5d22cf05bcd4b7a81bdd04e17" [[package]] name = "st-map" @@ -5545,7 +5545,7 @@ checksum = "710e9696ef338691287aeb937ee6ffe60022f579d3c8d2fd9d58973a9a10a466" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -5590,7 +5590,7 @@ checksum = "ae36a4951ca7bd1cfd991c241584a9824a70f6aff1e7d4f693fb3f2465e4030e" dependencies = [ "quote", "swc_macros_common", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -5804,7 +5804,7 @@ dependencies = [ "proc-macro2", "quote", "swc_macros_common", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -5889,7 +5889,7 @@ checksum = "e276dc62c0a2625a560397827989c82a93fd545fcf6f7faec0935a82cc4ddbb8" dependencies = [ "proc-macro2", "swc_macros_common", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -6212,7 +6212,7 @@ dependencies = [ "swc_ecma_ast", "swc_ecma_parser", "swc_macros_common", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -6325,7 +6325,7 @@ dependencies = [ "proc-macro2", "quote", "swc_macros_common", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -6500,7 +6500,7 @@ checksum = "c16ce73424a6316e95e09065ba6a207eba7765496fed113702278b7711d4b632" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -6524,7 +6524,7 @@ checksum = "b45db26cc495a8695f8034277ceb6a44e52eb702d6c64ea5c7156dd673ea8c98" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -6627,7 +6627,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f98ef1f87379c816ba7d22351c9fc993af38b034bce4da3286cfe4b17e7ec9e2" dependencies = [ "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -6703,7 +6703,7 @@ checksum = "aae1efbaa74943dc5ad2a2fb16cbd78b77d7e4d63188f3c5b4df2b4dcd2faaae" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -6789,7 +6789,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfd2b4b0adb82e36f2ac688d00a6a67132c7f4170c772617516793a701be89e8" dependencies = [ "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -6827,9 +6827,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.113" +version = "2.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678faa00651c9eb72dd2020cbdf275d92eccb2400d568e419efdd64838145cb4" +checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a" dependencies = [ "proc-macro2", "quote", @@ -6844,7 +6844,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -6949,7 +6949,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -6960,7 +6960,7 @@ checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -7050,7 +7050,7 @@ checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -7152,7 +7152,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -7510,7 +7510,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", "wasm-bindgen-shared", ] @@ -7532,7 +7532,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -7753,7 +7753,7 @@ checksum = "342b0466f92b7217a4de9e114175fedee1907028567d2548bcd42f71a8b5b016" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -7817,7 +7817,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", "witx", ] @@ -7829,7 +7829,7 @@ checksum = "f5872fbe512b73acd514e7ef5bd5aee0ff951a12c1fed0293e1f7992de30df9f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", "wiggle-generate", ] @@ -7947,7 +7947,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -7958,7 +7958,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -8278,7 +8278,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", "synstructure", ] @@ -8309,7 +8309,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -8320,7 +8320,7 @@ checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -8340,7 +8340,7 @@ checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", "synstructure", ] @@ -8363,7 +8363,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 638a53429888..7e3e51fc3ed4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -93,10 +93,10 @@ sftrace-setup = { version = "0.1.2", default-features = false } sha2 = { version = "0.10.9", default-features = false } signal-hook = { version = "0.3.18", default-features = false, features = ["iterator"] } simd-json = { version = "0.17.0", default-features = false } -smol_str = { version = "0.3.4", default-features = false } +smol_str = { version = "0.3.5", default-features = false } stacker = { version = "0.1.22", default-features = false } sugar_path = { version = "1.2.1", default-features = false, features = ["cached_current_dir"] } -syn = { version = "2.0.113", default-features = false } +syn = { version = "2.0.114", default-features = false } termcolor = { version = "1.4.1", default-features = false } textwrap = { version = "0.16.1", default-features = false } thread_local = { version = "1.1.9", default-features = false } From 36866eaae3ae0f0259a48a7b86f541680574e696 Mon Sep 17 00:00:00 2001 From: jinrui Date: Wed, 14 Jan 2026 17:13:41 +0800 Subject: [PATCH 55/87] test: skip recover-from-error/delete-file in watchCases (#12726) --- .../watchCases/recover-from-error/delete-file/test.filter.js | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 tests/rspack-test/watchCases/recover-from-error/delete-file/test.filter.js diff --git a/tests/rspack-test/watchCases/recover-from-error/delete-file/test.filter.js b/tests/rspack-test/watchCases/recover-from-error/delete-file/test.filter.js new file mode 100644 index 000000000000..b5a3b17e242b --- /dev/null +++ b/tests/rspack-test/watchCases/recover-from-error/delete-file/test.filter.js @@ -0,0 +1,2 @@ +module.exports = () => + 'TODO: The test is unstable and prone to timeouts on CI machines.'; From 25020fd1f3819636eb3740844dd010691217bfcc Mon Sep 17 00:00:00 2001 From: jinrui Date: Wed, 14 Jan 2026 17:37:41 +0800 Subject: [PATCH 56/87] feat: support portable cache and disable by default (#12680) * feat: support portable cache * feat: disable portable cache by default --- crates/rspack_cacheable/src/with/as_string.rs | 14 ---- crates/rspack_cacheable/src/with/custom.rs | 31 ++++++++- crates/rspack_collections/src/identifier.rs | 24 +++---- .../persistent/build_dependencies/mod.rs | 25 +++++++- .../src/cache/persistent/cacheable_context.rs | 8 --- .../rspack_core/src/cache/persistent/codec.rs | 64 +++++++++++++++++++ .../rspack_core/src/cache/persistent/mod.rs | 41 ++++++++---- .../src/cache/persistent/occasion/make/mod.rs | 12 ++-- .../persistent/occasion/make/module_graph.rs | 19 +++--- .../src/cache/persistent/occasion/meta/mod.rs | 13 ++-- .../src/cache/persistent/snapshot/mod.rs | 31 ++++++--- .../src/cache/persistent/snapshot/option.rs | 5 +- .../src/cache/persistent/storage/mod.rs | 7 +- crates/rspack_loader_runner/src/content.rs | 5 +- crates/rspack_paths/src/lib.rs | 20 +++--- .../rspack_tools/src/compare/occasion/make.rs | 10 +-- .../cacheCases/portable/basic/index.js | 28 ++++---- 17 files changed, 246 insertions(+), 111 deletions(-) delete mode 100644 crates/rspack_core/src/cache/persistent/cacheable_context.rs create mode 100644 crates/rspack_core/src/cache/persistent/codec.rs diff --git a/crates/rspack_cacheable/src/with/as_string.rs b/crates/rspack_cacheable/src/with/as_string.rs index 0063f77c2a6e..17dd1e53e875 100644 --- a/crates/rspack_cacheable/src/with/as_string.rs +++ b/crates/rspack_cacheable/src/with/as_string.rs @@ -59,17 +59,3 @@ where AsStringConverter::from_str(field.as_str()) } } - -// for pathbuf -use std::path::PathBuf; -impl AsStringConverter for PathBuf { - fn to_string(&self) -> Result { - Ok(self.to_string_lossy().to_string()) - } - fn from_str(s: &str) -> Result - where - Self: Sized, - { - Ok(PathBuf::from(s)) - } -} diff --git a/crates/rspack_cacheable/src/with/custom.rs b/crates/rspack_cacheable/src/with/custom.rs index 8d871bc3a1c7..eaeec7f0ca24 100644 --- a/crates/rspack_cacheable/src/with/custom.rs +++ b/crates/rspack_cacheable/src/with/custom.rs @@ -1,3 +1,5 @@ +use std::hash::Hash; + use rkyv::{ Archive, Deserialize, Place, Serialize, de::Pooling, @@ -5,8 +7,9 @@ use rkyv::{ ser::Sharing, with::{ArchiveWith, DeserializeWith, SerializeWith}, }; +use rspack_cacheable_macros::enable_cacheable as cacheable; -use crate::{ContextGuard, Error, Result, cacheable}; +use crate::{ContextGuard, Error, Result}; /// A trait for writing custom serialization and deserialization. /// @@ -27,6 +30,32 @@ pub struct Custom; #[cacheable(crate=crate)] pub struct DataBox(T); +// impl hashable for ArchivedDataBox +impl Hash for ArchivedDataBox +where + T: Archive, + T::Archived: Hash, +{ + fn hash(&self, state: &mut H) { + self.0.hash(state); + } +} +impl PartialEq for ArchivedDataBox +where + T: Archive, + T::Archived: PartialEq, +{ + fn eq(&self, other: &Self) -> bool { + self.0 == other.0 + } +} +impl Eq for ArchivedDataBox +where + T: Archive, + T::Archived: Eq, +{ +} + pub struct CustomResolver { resolver: DataBoxResolver, value: DataBox, diff --git a/crates/rspack_collections/src/identifier.rs b/crates/rspack_collections/src/identifier.rs index 3cec6a0ac319..9b5cfea1a958 100644 --- a/crates/rspack_collections/src/identifier.rs +++ b/crates/rspack_collections/src/identifier.rs @@ -9,7 +9,11 @@ use std::{ use dashmap::{DashMap, DashSet}; use hashlink::{LinkedHashMap, LinkedHashSet}; use indexmap::{IndexMap, IndexSet}; -use rspack_cacheable::{cacheable, with, with::AsPreset}; +use rspack_cacheable::{ + ContextGuard, Error as CacheableError, cacheable, + utils::PortableString, + with::{Custom, CustomConverter}, +}; use serde::Serialize; use ustr::Ustr; @@ -34,10 +38,10 @@ pub type IdentifierIndexSet = IndexSet>; pub type IdentifierLinkedSet = LinkedHashSet>; -#[cacheable(hashable)] +#[cacheable(with=Custom, hashable)] #[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize)] #[cfg_attr(allocative, derive(allocative::Allocative))] -pub struct Identifier(#[cacheable(with=AsPreset)] Ustr); +pub struct Identifier(Ustr); impl Deref for Identifier { type Target = Ustr; @@ -99,14 +103,12 @@ impl fmt::Display for Identifier { } // for Identifier -impl with::AsRefStrConverter for Identifier { - fn as_str(&self) -> &str { - self.0.as_str() +impl CustomConverter for Identifier { + type Target = PortableString; + fn serialize(&self, guard: &ContextGuard) -> Result { + Ok(PortableString::new(self.as_str(), guard.project_root())) } - fn from_str(s: &str) -> Self - where - Self: Sized, - { - s.into() + fn deserialize(data: Self::Target, guard: &ContextGuard) -> Result { + Ok(Self::from(data.into_path_string(guard.project_root()))) } } diff --git a/crates/rspack_core/src/cache/persistent/build_dependencies/mod.rs b/crates/rspack_core/src/cache/persistent/build_dependencies/mod.rs index 1b3622c1e63f..35aa5123d46b 100644 --- a/crates/rspack_core/src/cache/persistent/build_dependencies/mod.rs +++ b/crates/rspack_core/src/cache/persistent/build_dependencies/mod.rs @@ -9,6 +9,7 @@ use rustc_hash::FxHashSet as HashSet; use self::helper::{Helper, is_node_package_path}; use super::{ + codec::CacheCodec, snapshot::{Snapshot, SnapshotOptions}, storage::Storage, }; @@ -40,6 +41,7 @@ impl BuildDeps { snapshot_options: &SnapshotOptions, fs: Arc, storage: Arc, + codec: Arc, ) -> Self { Self { added: Default::default(), @@ -49,6 +51,7 @@ impl BuildDeps { snapshot_options.clone(), fs.clone(), storage.clone(), + codec, ), storage, fs, @@ -112,7 +115,10 @@ mod test { use rspack_fs::{MemoryFileSystem, WritableFileSystem}; use rspack_storage::Storage; - use super::{super::storage::MemoryStorage, BuildDeps, SCOPE, SnapshotOptions}; + use super::{ + super::{codec::CacheCodec, storage::MemoryStorage}, + BuildDeps, SCOPE, SnapshotOptions, + }; #[tokio::test] async fn build_dependencies_test() { let fs = Arc::new(MemoryFileSystem::default()); @@ -151,13 +157,26 @@ mod test { let options = vec![PathBuf::from("/index.js"), PathBuf::from("/configs")]; let snapshot_options = SnapshotOptions::default(); let storage = Arc::new(MemoryStorage::default()); - let mut build_deps = BuildDeps::new(&options, &snapshot_options, fs.clone(), storage.clone()); + let codec = Arc::new(CacheCodec::new(None)); + let mut build_deps = BuildDeps::new( + &options, + &snapshot_options, + fs.clone(), + storage.clone(), + codec.clone(), + ); let warnings = build_deps.add(vec![].into_iter()).await; assert_eq!(warnings.len(), 1); let data = storage.load(SCOPE).await.expect("should load success"); assert_eq!(data.len(), 9); - let mut build_deps = BuildDeps::new(&options, &snapshot_options, fs.clone(), storage.clone()); + let mut build_deps = BuildDeps::new( + &options, + &snapshot_options, + fs.clone(), + storage.clone(), + codec, + ); fs.write("/b.js".into(), r#"require("./c")"#.as_bytes()) .await .unwrap(); diff --git a/crates/rspack_core/src/cache/persistent/cacheable_context.rs b/crates/rspack_core/src/cache/persistent/cacheable_context.rs deleted file mode 100644 index b2e919abb23d..000000000000 --- a/crates/rspack_core/src/cache/persistent/cacheable_context.rs +++ /dev/null @@ -1,8 +0,0 @@ -#[derive(Debug)] -pub struct CacheableContext; - -impl rspack_cacheable::CacheableContext for CacheableContext { - fn project_root(&self) -> Option<&std::path::Path> { - None - } -} diff --git a/crates/rspack_core/src/cache/persistent/codec.rs b/crates/rspack_core/src/cache/persistent/codec.rs new file mode 100644 index 000000000000..24791964c3d7 --- /dev/null +++ b/crates/rspack_core/src/cache/persistent/codec.rs @@ -0,0 +1,64 @@ +use std::path::Path; + +use rspack_cacheable::{ + __private::rkyv::{Archive, Deserialize, Serialize, bytecheck::CheckBytes}, + Deserializer, Serializer, Validator, from_bytes, to_bytes, +}; +use rspack_error::Result; +use rspack_paths::Utf8PathBuf; + +/// Internal cacheable context for serialization +#[derive(Debug, Clone)] +struct Context { + project_path: Option, +} + +impl rspack_cacheable::CacheableContext for Context { + fn project_root(&self) -> Option<&Path> { + self.project_path.as_ref().map(|p| p.as_std_path()) + } +} + +/// Cache codec for encoding and decoding cacheable data +/// +/// This struct encapsulates the serialization and deserialization logic, +/// automatically passing the project context to rspack_cacheable's to_bytes and from_bytes. +/// +/// # Example +/// +/// ```ignore +/// let codec = CacheCodec::new(project_path); +/// +/// // Encode data to bytes +/// let bytes = codec.encode(&my_data)?; +/// +/// // Decode bytes back to data +/// let my_data: MyType = codec.decode(&bytes)?; +/// ``` +#[derive(Debug, Clone)] +pub struct CacheCodec { + context: Context, +} + +impl CacheCodec { + pub fn new(project_path: Option) -> Self { + Self { + context: Context { project_path }, + } + } + + pub fn encode(&self, data: &T) -> Result> + where + T: for<'a> Serialize>, + { + to_bytes(data, &self.context).map_err(|e| rspack_error::error!(e.to_string())) + } + + pub fn decode(&self, bytes: &[u8]) -> Result + where + T: Archive, + T::Archived: for<'a> CheckBytes> + Deserialize, + { + from_bytes(bytes, &self.context).map_err(|e| rspack_error::error!(e.to_string())) + } +} diff --git a/crates/rspack_core/src/cache/persistent/mod.rs b/crates/rspack_core/src/cache/persistent/mod.rs index 6dde42607888..6d5558feecf5 100644 --- a/crates/rspack_core/src/cache/persistent/mod.rs +++ b/crates/rspack_core/src/cache/persistent/mod.rs @@ -1,5 +1,5 @@ pub mod build_dependencies; -mod cacheable_context; +pub mod codec; pub mod occasion; pub mod snapshot; pub mod storage; @@ -9,13 +9,18 @@ use std::{ sync::Arc, }; -pub use cacheable_context::CacheableContext; +use rspack_cacheable::{ + cacheable, + utils::PortablePath, + with::{As, AsVec}, +}; use rspack_fs::{IntermediateFileSystem, ReadableFileSystem}; use rspack_paths::ArcPathSet; use rspack_workspace::rspack_pkg_version; use self::{ build_dependencies::{BuildDeps, BuildDepsOptions}, + codec::CacheCodec, occasion::{MakeOccasion, MetaOccasion}, snapshot::{Snapshot, SnapshotOptions}, storage::{Storage, StorageOptions, create_storage}, @@ -26,8 +31,10 @@ use crate::{ compilation::build_module_graph::{BuildModuleGraphArtifact, BuildModuleGraphArtifactState}, }; +#[cacheable] #[derive(Debug, Clone, Hash)] pub struct PersistentCacheOptions { + #[cacheable(with=AsVec>)] pub build_dependencies: BuildDepsOptions, pub version: String, pub snapshot: SnapshotOptions, @@ -40,10 +47,10 @@ pub struct PersistentCache { initialized: bool, build_deps: BuildDeps, snapshot: Snapshot, - storage: Arc, make_occasion: MakeOccasion, meta_occasion: MetaOccasion, async_mode: bool, + storage: Arc, // TODO replace to logger and output warnings directly. warnings: Vec, } @@ -57,19 +64,23 @@ impl PersistentCache { intermediate_filesystem: Arc, ) -> Self { let async_mode = compiler_options.mode.is_development(); + let codec = Arc::new(CacheCodec::new(None)); + // use codec.encode to transform the absolute path in option, + // it will ensure that same project in different directory have the same version. + let option_bytes = codec + .encode(option) + .expect("should persistent cache options can be serialized"); let version = { let mut hasher = DefaultHasher::new(); compiler_path.hash(&mut hasher); - option.hash(&mut hasher); + option_bytes.hash(&mut hasher); rspack_pkg_version!().hash(&mut hasher); compiler_options.name.hash(&mut hasher); compiler_options.mode.hash(&mut hasher); hex::encode(hasher.finish().to_ne_bytes()) }; let storage = create_storage(option.storage.clone(), version, intermediate_filesystem); - let context = Arc::new(CacheableContext); - let make_occasion = MakeOccasion::new(storage.clone(), context); - let meta_occasion = MetaOccasion::new(storage.clone()); + Self { initialized: false, build_deps: BuildDeps::new( @@ -77,13 +88,19 @@ impl PersistentCache { &option.snapshot, input_filesystem.clone(), storage.clone(), + codec.clone(), ), - snapshot: Snapshot::new(option.snapshot.clone(), input_filesystem, storage.clone()), - storage, - make_occasion, - meta_occasion, - async_mode, + snapshot: Snapshot::new( + option.snapshot.clone(), + input_filesystem, + storage.clone(), + codec.clone(), + ), + make_occasion: MakeOccasion::new(storage.clone(), codec.clone()), + meta_occasion: MetaOccasion::new(storage.clone(), codec), warnings: Default::default(), + async_mode, + storage, } } diff --git a/crates/rspack_core/src/cache/persistent/occasion/make/mod.rs b/crates/rspack_core/src/cache/persistent/occasion/make/mod.rs index 7205525aa1f8..fc1cceeecaa0 100644 --- a/crates/rspack_core/src/cache/persistent/occasion/make/mod.rs +++ b/crates/rspack_core/src/cache/persistent/occasion/make/mod.rs @@ -8,7 +8,7 @@ use rspack_collections::IdentifierSet; use rspack_error::Result; use rustc_hash::FxHashSet; -use super::super::{Storage, cacheable_context::CacheableContext}; +use super::super::{Storage, codec::CacheCodec}; use crate::{ FactorizeInfo, compilation::build_module_graph::{BuildModuleGraphArtifact, BuildModuleGraphArtifactState}, @@ -18,13 +18,13 @@ use crate::{ /// Make Occasion is used to save MakeArtifact #[derive(Debug)] pub struct MakeOccasion { - context: Arc, + codec: Arc, storage: Arc, } impl MakeOccasion { - pub fn new(storage: Arc, context: Arc) -> Self { - Self { storage, context } + pub fn new(storage: Arc, codec: Arc) -> Self { + Self { storage, codec } } #[tracing::instrument(name = "Cache::Occasion::Make::save", skip_all)] @@ -65,14 +65,14 @@ impl MakeOccasion { affected_modules.removed(), &need_update_modules, &self.storage, - &self.context, + &self.codec, ); } #[tracing::instrument(name = "Cache::Occasion::Make::recovery", skip_all)] pub async fn recovery(&self) -> Result { let (mg, module_to_lazy_make, entry_dependencies) = - module_graph::recovery_module_graph(&self.storage, &self.context).await?; + module_graph::recovery_module_graph(&self.storage, &self.codec).await?; // regenerate statistical data // recovery make_failed_module diff --git a/crates/rspack_core/src/cache/persistent/occasion/make/module_graph.rs b/crates/rspack_core/src/cache/persistent/occasion/make/module_graph.rs index 6720d58ecf98..00e798d5e1ae 100644 --- a/crates/rspack_core/src/cache/persistent/occasion/make/module_graph.rs +++ b/crates/rspack_core/src/cache/persistent/occasion/make/module_graph.rs @@ -1,9 +1,7 @@ use std::sync::Arc; use rayon::prelude::*; -use rspack_cacheable::{ - Error as CacheableError, cacheable, from_bytes, to_bytes, utils::OwnedOrRef, -}; +use rspack_cacheable::{cacheable, utils::OwnedOrRef}; use rspack_collections::IdentifierSet; use rspack_error::Result; use rustc_hash::FxHashSet as HashSet; @@ -16,7 +14,7 @@ use crate::{ AsyncDependenciesBlock, AsyncDependenciesBlockIdentifier, BoxDependency, BoxModule, Dependency, DependencyId, DependencyParents, ExportsInfoData, ModuleGraph, ModuleGraphConnection, ModuleGraphModule, ModuleIdentifier, RayonConsumer, - cache::persistent::cacheable_context::CacheableContext, + cache::persistent::codec::CacheCodec, compilation::build_module_graph::{LazyDependencies, ModuleToLazyMake}, }; @@ -43,7 +41,7 @@ pub fn save_module_graph( removed_modules: &IdentifierSet, need_update_modules: &IdentifierSet, storage: &Arc, - context: &CacheableContext, + codec: &CacheCodec, ) { for identifier in removed_modules { storage.remove(SCOPE, identifier.as_bytes()); @@ -94,9 +92,9 @@ pub fn save_module_graph( blocks, lazy_info, }; - match to_bytes(&node, context) { + match codec.encode(&node) { Ok(bytes) => (identifier.as_bytes().to_vec(), bytes), - Err(err @ CacheableError::UnsupportedField) => { + Err(err) if err.to_string().contains("unsupported field") => { tracing::warn!("to bytes failed {:?}", err); // try use alternatives node.module = TempModule::transform_from(node.module); @@ -106,7 +104,7 @@ pub fn save_module_graph( .map(|(dep, _)| (TempDependency::transform_from(dep), None)) .collect(); node.blocks = vec![]; - if let Ok(bytes) = to_bytes(&node, context) { + if let Ok(bytes) = codec.encode(&node) { (identifier.as_bytes().to_vec(), bytes) } else { panic!("alternatives serialize failed") @@ -129,7 +127,7 @@ pub fn save_module_graph( #[tracing::instrument("Cache::Occasion::Make::ModuleGraph::recovery", skip_all)] pub async fn recovery_module_graph( storage: &Arc, - context: &CacheableContext, + codec: &CacheCodec, ) -> Result<(ModuleGraph, ModuleToLazyMake, HashSet)> { let mut need_check_dep = vec![]; let mut mg = ModuleGraph::default(); @@ -139,7 +137,8 @@ pub async fn recovery_module_graph( .await? .into_par_iter() .map(|(_, v)| { - from_bytes::(&v, context) + codec + .decode::(&v) .expect("unexpected module graph deserialize failed") }) .with_max_len(1) diff --git a/crates/rspack_core/src/cache/persistent/occasion/meta/mod.rs b/crates/rspack_core/src/cache/persistent/occasion/meta/mod.rs index da6a84e2a30c..41afc8a3b99a 100644 --- a/crates/rspack_core/src/cache/persistent/occasion/meta/mod.rs +++ b/crates/rspack_core/src/cache/persistent/occasion/meta/mod.rs @@ -1,10 +1,10 @@ use std::sync::Arc; -use rspack_cacheable::{cacheable, from_bytes, to_bytes}; +use rspack_cacheable::cacheable; use rspack_error::Result; use rspack_tasks::{get_current_dependency_id, set_current_dependency_id}; -use super::super::Storage; +use super::super::{Storage, codec::CacheCodec}; pub const SCOPE: &str = "meta"; @@ -18,11 +18,12 @@ struct Meta { #[derive(Debug)] pub struct MetaOccasion { storage: Arc, + codec: Arc, } impl MetaOccasion { - pub fn new(storage: Arc) -> Self { - Self { storage } + pub fn new(storage: Arc, codec: Arc) -> Self { + Self { storage, codec } } #[tracing::instrument("Cache::Occasion::Meta::save", skip_all)] @@ -33,7 +34,7 @@ impl MetaOccasion { self.storage.set( SCOPE, "default".as_bytes().to_vec(), - to_bytes(&meta, &()).expect("should to bytes success"), + self.codec.encode(&meta).expect("should encode success"), ); } @@ -43,7 +44,7 @@ impl MetaOccasion { return Ok(()); }; - let meta: Meta = from_bytes(&value, &()).expect("should from bytes success"); + let meta: Meta = self.codec.decode(&value).expect("should decode success"); if get_current_dependency_id() != 0 { panic!("The global dependency id generator is not 0 when the persistent cache is restored."); } diff --git a/crates/rspack_core/src/cache/persistent/snapshot/mod.rs b/crates/rspack_core/src/cache/persistent/snapshot/mod.rs index 6a6007402a3e..c0ef9a5bddc2 100644 --- a/crates/rspack_core/src/cache/persistent/snapshot/mod.rs +++ b/crates/rspack_core/src/cache/persistent/snapshot/mod.rs @@ -1,9 +1,8 @@ mod option; mod strategy; -use std::{path::Path, sync::Arc}; +use std::sync::Arc; -use rspack_cacheable::{from_bytes, to_bytes}; use rspack_error::Result; use rspack_fs::ReadableFileSystem; use rspack_paths::{ArcPath, ArcPathSet}; @@ -13,7 +12,7 @@ pub use self::{ option::{PathMatcher, SnapshotOptions}, strategy::Strategy, }; -use super::storage::Storage; +use super::{codec::CacheCodec, storage::Storage}; use crate::FutureConsumer; pub const SCOPE: &str = "snapshot"; @@ -28,6 +27,7 @@ pub struct Snapshot { options: Arc, fs: Arc, storage: Arc, + codec: Arc, } impl Snapshot { @@ -35,12 +35,14 @@ impl Snapshot { options: SnapshotOptions, fs: Arc, storage: Arc, + codec: Arc, ) -> Self { Self { scope: SCOPE, options: Arc::new(options), fs, storage, + codec, } } @@ -49,12 +51,14 @@ impl Snapshot { options: SnapshotOptions, fs: Arc, storage: Arc, + codec: Arc, ) -> Self { Self { scope, options: Arc::new(options), fs, storage, + codec, } } @@ -81,16 +85,18 @@ impl Snapshot { #[tracing::instrument("Cache::Snapshot::add", skip_all)] pub async fn add(&self, paths: impl Iterator) { let helper = Arc::new(StrategyHelper::new(self.fs.clone())); + let codec = self.codec.clone(); // TODO merge package version file paths .map(|path| { let helper = helper.clone(); let options = self.options.clone(); + let codec = codec.clone(); async move { let strategy = Self::calc_strategy(&options, &helper, &path).await?; Some(( - path.as_os_str().as_encoded_bytes().to_vec(), - to_bytes::<_, ()>(&strategy, &()).expect("should to bytes success"), + codec.encode(&path).expect("should encode success"), + codec.encode(&strategy).expect("should encode success"), )) } }) @@ -117,6 +123,7 @@ impl Snapshot { let mut deleted_path = ArcPathSet::default(); let mut no_change_path = ArcPathSet::default(); let helper = Arc::new(StrategyHelper::new(self.fs.clone())); + let codec = self.codec.clone(); let data = self.storage.load(self.scope).await?; let is_hot_start = !data.is_empty(); @@ -124,10 +131,10 @@ impl Snapshot { .into_iter() .map(|(key, value)| { let helper = helper.clone(); + let codec = codec.clone(); async move { - let path: ArcPath = Path::new(&*String::from_utf8_lossy(&key)).into(); - let strategy: Strategy = - from_bytes::(&value, &()).expect("should from bytes success"); + let path: ArcPath = codec.decode(&key).expect("should decode success"); + let strategy: Strategy = codec.decode(&value).expect("should decode success"); let validate = helper.validate(&path, &strategy).await; (path, validate) } @@ -156,7 +163,10 @@ mod tests { use rspack_fs::{MemoryFileSystem, WritableFileSystem}; use rspack_paths::ArcPath; - use super::{super::storage::MemoryStorage, PathMatcher, Snapshot, SnapshotOptions}; + use super::{ + super::{codec::CacheCodec, storage::MemoryStorage}, + PathMatcher, Snapshot, SnapshotOptions, + }; macro_rules! p { ($tt:tt) => { @@ -168,6 +178,7 @@ mod tests { async fn should_snapshot_work() { let fs = Arc::new(MemoryFileSystem::default()); let storage = Arc::new(MemoryStorage::default()); + let codec = Arc::new(CacheCodec::new(None)); let options = SnapshotOptions::new( vec![PathMatcher::String("constant".into())], vec![PathMatcher::String("node_modules/project".into())], @@ -201,7 +212,7 @@ mod tests { .await .unwrap(); - let snapshot = Snapshot::new(options, fs.clone(), storage); + let snapshot = Snapshot::new(options, fs.clone(), storage, codec); snapshot .add( diff --git a/crates/rspack_core/src/cache/persistent/snapshot/option.rs b/crates/rspack_core/src/cache/persistent/snapshot/option.rs index 6fdca9f6e6e5..c1bd94065e64 100644 --- a/crates/rspack_core/src/cache/persistent/snapshot/option.rs +++ b/crates/rspack_core/src/cache/persistent/snapshot/option.rs @@ -1,9 +1,11 @@ +use rspack_cacheable::{cacheable, utils::PortablePath, with::As}; use rspack_regex::RspackRegex; /// Use string or regex to match path +#[cacheable] #[derive(Debug, Clone, Hash)] pub enum PathMatcher { - String(String), + String(#[cacheable(with=As)] String), Regexp(RspackRegex), } @@ -17,6 +19,7 @@ impl PathMatcher { } /// Snapshot options +#[cacheable] #[derive(Debug, Default, Clone, Hash)] pub struct SnapshotOptions { /// immutable paths, snapshot will ignore them diff --git a/crates/rspack_core/src/cache/persistent/storage/mod.rs b/crates/rspack_core/src/cache/persistent/storage/mod.rs index d55fac9e6989..fce42c9e3c2a 100644 --- a/crates/rspack_core/src/cache/persistent/storage/mod.rs +++ b/crates/rspack_core/src/cache/persistent/storage/mod.rs @@ -4,6 +4,7 @@ mod memory; use std::{path::PathBuf, sync::Arc}; pub use memory::MemoryStorage; +use rspack_cacheable::{cacheable, utils::PortablePath, with::As}; use rspack_fs::IntermediateFileSystem; pub use rspack_storage::Storage; use rspack_storage::{BridgeFileSystem, PackStorage, PackStorageOptions}; @@ -12,9 +13,13 @@ use rspack_storage::{BridgeFileSystem, PackStorage, PackStorageOptions}; /// /// This enum contains all of supported storage options. /// Since MemoryStorage is only used in unit test, there is no need to add it here. +#[cacheable] #[derive(Debug, Clone, Hash)] pub enum StorageOptions { - FileSystem { directory: PathBuf }, + FileSystem { + #[cacheable(with=As)] + directory: PathBuf, + }, } pub fn create_storage( diff --git a/crates/rspack_loader_runner/src/content.rs b/crates/rspack_loader_runner/src/content.rs index 2c19e9c92ba3..9c770cb7db5d 100644 --- a/crates/rspack_loader_runner/src/content.rs +++ b/crates/rspack_loader_runner/src/content.rs @@ -8,7 +8,8 @@ use anymap::CloneAny; use once_cell::sync::OnceCell; use rspack_cacheable::{ cacheable, - with::{AsInner, AsOption, AsPreset, AsString}, + utils::PortablePath, + with::{As, AsInner, AsOption, AsPreset}, }; use rspack_error::{Error, Result, ToStringResultToRspackResultExt}; use rspack_paths::{Utf8Path, Utf8PathBuf}; @@ -307,7 +308,7 @@ impl ResourceData { #[derive(Debug, Clone)] pub struct DescriptionData { /// Path to package.json - #[cacheable(with=AsString)] + #[cacheable(with=As)] path: PathBuf, /// Raw package.json diff --git a/crates/rspack_paths/src/lib.rs b/crates/rspack_paths/src/lib.rs index b3d082b7de3f..0331fc6e47ae 100644 --- a/crates/rspack_paths/src/lib.rs +++ b/crates/rspack_paths/src/lib.rs @@ -11,8 +11,9 @@ pub use camino::{Utf8Component, Utf8Components, Utf8Path, Utf8PathBuf, Utf8Prefi use dashmap::{DashMap, DashSet}; use indexmap::IndexSet; use rspack_cacheable::{ - cacheable, - with::{AsRefStr, AsRefStrConverter}, + ContextGuard, Error as CacheableError, cacheable, + utils::PortablePath, + with::{Custom, CustomConverter}, }; use rustc_hash::FxHasher; use ustr::IdentityHasher; @@ -52,7 +53,7 @@ impl<'a> AssertUtf8 for &'a Path { } } -#[cacheable(with=AsRefStr, hashable)] +#[cacheable(with=Custom)] #[derive(Clone, PartialEq, Eq)] pub struct ArcPath { path: Arc, @@ -126,12 +127,15 @@ impl From<&str> for ArcPath { } } -impl AsRefStrConverter for ArcPath { - fn as_str(&self) -> &str { - self.path.to_str().expect("expect utf8 str") +impl CustomConverter for ArcPath { + type Target = PortablePath; + fn serialize(&self, guard: &ContextGuard) -> Result { + Ok(PortablePath::new(&self.path, guard.project_root())) } - fn from_str(s: &str) -> Self { - Self::from(Path::new(s)) + fn deserialize(data: Self::Target, guard: &ContextGuard) -> Result { + Ok(Self::from(PathBuf::from( + data.into_path_string(guard.project_root()), + ))) } } diff --git a/crates/rspack_tools/src/compare/occasion/make.rs b/crates/rspack_tools/src/compare/occasion/make.rs index 6d196c0fcab3..433c61786479 100644 --- a/crates/rspack_tools/src/compare/occasion/make.rs +++ b/crates/rspack_tools/src/compare/occasion/make.rs @@ -4,9 +4,10 @@ pub use rspack_core::cache::persistent::occasion::make::SCOPE; use rspack_core::{ DependencyId, build_module_graph::BuildModuleGraphArtifact, - cache::persistent::{CacheableContext, occasion::make::MakeOccasion, storage::Storage}, + cache::persistent::{codec::CacheCodec, occasion::make::MakeOccasion, storage::Storage}, }; use rspack_error::Result; +use rspack_paths::Utf8PathBuf; use rustc_hash::FxHashMap as HashMap; use crate::{debug_info::DebugInfo, utils::ensure_iter_equal}; @@ -29,9 +30,10 @@ pub async fn compare( ensure_iter_equal("Make module key", map1.keys(), map2.keys(), &debug_info)?; // Convert stored data to BuildModuleGraphArtifact using MakeOccasion's recovery ability - let context = Arc::new(CacheableContext); - let occasion1 = MakeOccasion::new(storage1.clone(), context.clone()); - let occasion2 = MakeOccasion::new(storage2.clone(), context.clone()); + // Use a dummy path for codec since we're only deserializing + let codec = Arc::new(CacheCodec::new(Some(Utf8PathBuf::from("/")))); + let occasion1 = MakeOccasion::new(storage1.clone(), codec.clone()); + let occasion2 = MakeOccasion::new(storage2.clone(), codec.clone()); let artifact1 = occasion1.recovery().await?; let artifact2 = occasion2.recovery().await?; diff --git a/tests/rspack-test/cacheCases/portable/basic/index.js b/tests/rspack-test/cacheCases/portable/basic/index.js index bbd66bf5780c..3363d4d4ead7 100644 --- a/tests/rspack-test/cacheCases/portable/basic/index.js +++ b/tests/rspack-test/cacheCases/portable/basic/index.js @@ -1,17 +1,17 @@ -import value from "./file"; +import value from './file'; -it("should basic test work", async () => { - if (COMPILER_INDEX == 0) { - expect(value).toBe(1); - await NEXT_START(); - } - if (COMPILER_INDEX == 1) { - expect(value).toBe(1); - await NEXT_MOVE_DIR_START(); - } - if (COMPILER_INDEX == 2) { - expect(value).toBe(3); - } +it('should basic test work', async () => { + if (COMPILER_INDEX == 0) { + expect(value).toBe(1); + await NEXT_START(); + } + if (COMPILER_INDEX == 1) { + expect(value).toBe(1); + await NEXT_MOVE_DIR_START(); + } + if (COMPILER_INDEX == 2) { + expect(value).toBe(3); + } }); -module.hot.accept("./file"); +module.hot.accept('./file'); From 07d36648755548872c12d0b1950327f08feee107 Mon Sep 17 00:00:00 2001 From: "zhanghang.heal" Date: Wed, 14 Jan 2026 17:48:50 +0800 Subject: [PATCH 57/87] fix: rename reShake to secondaryTreeShaking --- crates/node_binding/rspack.wasi-browser.js | 61 +------------------ crates/node_binding/rspack.wasi.cjs | 61 +------------------ packages/rspack/etc/core.api.md | 4 +- packages/rspack/package.json | 2 +- .../src/container/ModuleFederationPlugin.ts | 2 +- .../src/sharing/TreeShakingSharedPlugin.ts | 14 ++--- pnpm-lock.yaml | 58 +++++++++--------- .../package.json | 7 +++ .../manifest-file-name/package.json | 7 +++ .../sharing/reshake-share/CustomPlugin.js | 2 +- .../sharing/reshake-share/index.js | 8 +-- .../sharing/reshake-share/rspack.config.js | 4 +- .../webpack/tree-shaking-shared-plugin.mdx | 6 +- .../webpack/tree-shaking-shared-plugin.mdx | 6 +- 14 files changed, 69 insertions(+), 173 deletions(-) create mode 100644 tests/rspack-test/configCases/container-1-5/manifest-disable-assets-analyze/package.json create mode 100644 tests/rspack-test/configCases/container-1-5/manifest-file-name/package.json diff --git a/crates/node_binding/rspack.wasi-browser.js b/crates/node_binding/rspack.wasi-browser.js index e3e5c0a99d48..ee65959b37bc 100644 --- a/crates/node_binding/rspack.wasi-browser.js +++ b/crates/node_binding/rspack.wasi-browser.js @@ -63,63 +63,4 @@ const { }, }) export default __napiModule.exports -export const Assets = __napiModule.exports.Assets -export const AsyncDependenciesBlock = __napiModule.exports.AsyncDependenciesBlock -export const Chunk = __napiModule.exports.Chunk -export const ChunkGraph = __napiModule.exports.ChunkGraph -export const ChunkGroup = __napiModule.exports.ChunkGroup -export const Chunks = __napiModule.exports.Chunks -export const CodeGenerationResult = __napiModule.exports.CodeGenerationResult -export const CodeGenerationResults = __napiModule.exports.CodeGenerationResults -export const ConcatenatedModule = __napiModule.exports.ConcatenatedModule -export const ContextModule = __napiModule.exports.ContextModule -export const Dependency = __napiModule.exports.Dependency -export const Diagnostics = __napiModule.exports.Diagnostics -export const EntryDataDto = __napiModule.exports.EntryDataDto -export const EntryDataDTO = __napiModule.exports.EntryDataDTO -export const EntryDependency = __napiModule.exports.EntryDependency -export const EntryOptionsDto = __napiModule.exports.EntryOptionsDto -export const EntryOptionsDTO = __napiModule.exports.EntryOptionsDTO -export const ExternalModule = __napiModule.exports.ExternalModule -export const JsCompilation = __napiModule.exports.JsCompilation -export const JsCompiler = __napiModule.exports.JsCompiler -export const JsContextModuleFactoryAfterResolveData = __napiModule.exports.JsContextModuleFactoryAfterResolveData -export const JsContextModuleFactoryBeforeResolveData = __napiModule.exports.JsContextModuleFactoryBeforeResolveData -export const JsDependencies = __napiModule.exports.JsDependencies -export const JsEntries = __napiModule.exports.JsEntries -export const JsExportsInfo = __napiModule.exports.JsExportsInfo -export const JsModuleGraph = __napiModule.exports.JsModuleGraph -export const JsResolver = __napiModule.exports.JsResolver -export const JsResolverFactory = __napiModule.exports.JsResolverFactory -export const JsStats = __napiModule.exports.JsStats -export const KnownBuildInfo = __napiModule.exports.KnownBuildInfo -export const Module = __napiModule.exports.Module -export const ModuleGraphConnection = __napiModule.exports.ModuleGraphConnection -export const NativeWatcher = __napiModule.exports.NativeWatcher -export const NativeWatchResult = __napiModule.exports.NativeWatchResult -export const NormalModule = __napiModule.exports.NormalModule -export const RawExternalItemFnCtx = __napiModule.exports.RawExternalItemFnCtx -export const ReadonlyResourceData = __napiModule.exports.ReadonlyResourceData -export const ResolverFactory = __napiModule.exports.ResolverFactory -export const Sources = __napiModule.exports.Sources -export const VirtualFileStore = __napiModule.exports.VirtualFileStore -export const JsVirtualFileStore = __napiModule.exports.JsVirtualFileStore -export const async = __napiModule.exports.async -export const BuiltinPluginName = __napiModule.exports.BuiltinPluginName -export const cleanupGlobalTrace = __napiModule.exports.cleanupGlobalTrace -export const EnforceExtension = __napiModule.exports.EnforceExtension -export const EXPECTED_RSPACK_CORE_VERSION = __napiModule.exports.EXPECTED_RSPACK_CORE_VERSION -export const formatDiagnostic = __napiModule.exports.formatDiagnostic -export const JsLoaderState = __napiModule.exports.JsLoaderState -export const JsRspackSeverity = __napiModule.exports.JsRspackSeverity -export const loadBrowserslist = __napiModule.exports.loadBrowserslist -export const minify = __napiModule.exports.minify -export const minifySync = __napiModule.exports.minifySync -export const RawJavascriptParserCommonjsExports = __napiModule.exports.RawJavascriptParserCommonjsExports -export const RawRuleSetConditionType = __napiModule.exports.RawRuleSetConditionType -export const registerGlobalTrace = __napiModule.exports.registerGlobalTrace -export const RegisterJsTapKind = __napiModule.exports.RegisterJsTapKind -export const sync = __napiModule.exports.sync -export const syncTraceEvent = __napiModule.exports.syncTraceEvent -export const transform = __napiModule.exports.transform -export const transformSync = __napiModule.exports.transformSync + diff --git a/crates/node_binding/rspack.wasi.cjs b/crates/node_binding/rspack.wasi.cjs index a251ce4d0d7d..1ad96db4aac4 100644 --- a/crates/node_binding/rspack.wasi.cjs +++ b/crates/node_binding/rspack.wasi.cjs @@ -108,63 +108,4 @@ const { instance: __napiInstance, module: __wasiModule, napiModule: __napiModule }, }) module.exports = __napiModule.exports -module.exports.Assets = __napiModule.exports.Assets -module.exports.AsyncDependenciesBlock = __napiModule.exports.AsyncDependenciesBlock -module.exports.Chunk = __napiModule.exports.Chunk -module.exports.ChunkGraph = __napiModule.exports.ChunkGraph -module.exports.ChunkGroup = __napiModule.exports.ChunkGroup -module.exports.Chunks = __napiModule.exports.Chunks -module.exports.CodeGenerationResult = __napiModule.exports.CodeGenerationResult -module.exports.CodeGenerationResults = __napiModule.exports.CodeGenerationResults -module.exports.ConcatenatedModule = __napiModule.exports.ConcatenatedModule -module.exports.ContextModule = __napiModule.exports.ContextModule -module.exports.Dependency = __napiModule.exports.Dependency -module.exports.Diagnostics = __napiModule.exports.Diagnostics -module.exports.EntryDataDto = __napiModule.exports.EntryDataDto -module.exports.EntryDataDTO = __napiModule.exports.EntryDataDTO -module.exports.EntryDependency = __napiModule.exports.EntryDependency -module.exports.EntryOptionsDto = __napiModule.exports.EntryOptionsDto -module.exports.EntryOptionsDTO = __napiModule.exports.EntryOptionsDTO -module.exports.ExternalModule = __napiModule.exports.ExternalModule -module.exports.JsCompilation = __napiModule.exports.JsCompilation -module.exports.JsCompiler = __napiModule.exports.JsCompiler -module.exports.JsContextModuleFactoryAfterResolveData = __napiModule.exports.JsContextModuleFactoryAfterResolveData -module.exports.JsContextModuleFactoryBeforeResolveData = __napiModule.exports.JsContextModuleFactoryBeforeResolveData -module.exports.JsDependencies = __napiModule.exports.JsDependencies -module.exports.JsEntries = __napiModule.exports.JsEntries -module.exports.JsExportsInfo = __napiModule.exports.JsExportsInfo -module.exports.JsModuleGraph = __napiModule.exports.JsModuleGraph -module.exports.JsResolver = __napiModule.exports.JsResolver -module.exports.JsResolverFactory = __napiModule.exports.JsResolverFactory -module.exports.JsStats = __napiModule.exports.JsStats -module.exports.KnownBuildInfo = __napiModule.exports.KnownBuildInfo -module.exports.Module = __napiModule.exports.Module -module.exports.ModuleGraphConnection = __napiModule.exports.ModuleGraphConnection -module.exports.NativeWatcher = __napiModule.exports.NativeWatcher -module.exports.NativeWatchResult = __napiModule.exports.NativeWatchResult -module.exports.NormalModule = __napiModule.exports.NormalModule -module.exports.RawExternalItemFnCtx = __napiModule.exports.RawExternalItemFnCtx -module.exports.ReadonlyResourceData = __napiModule.exports.ReadonlyResourceData -module.exports.ResolverFactory = __napiModule.exports.ResolverFactory -module.exports.Sources = __napiModule.exports.Sources -module.exports.VirtualFileStore = __napiModule.exports.VirtualFileStore -module.exports.JsVirtualFileStore = __napiModule.exports.JsVirtualFileStore -module.exports.async = __napiModule.exports.async -module.exports.BuiltinPluginName = __napiModule.exports.BuiltinPluginName -module.exports.cleanupGlobalTrace = __napiModule.exports.cleanupGlobalTrace -module.exports.EnforceExtension = __napiModule.exports.EnforceExtension -module.exports.EXPECTED_RSPACK_CORE_VERSION = __napiModule.exports.EXPECTED_RSPACK_CORE_VERSION -module.exports.formatDiagnostic = __napiModule.exports.formatDiagnostic -module.exports.JsLoaderState = __napiModule.exports.JsLoaderState -module.exports.JsRspackSeverity = __napiModule.exports.JsRspackSeverity -module.exports.loadBrowserslist = __napiModule.exports.loadBrowserslist -module.exports.minify = __napiModule.exports.minify -module.exports.minifySync = __napiModule.exports.minifySync -module.exports.RawJavascriptParserCommonjsExports = __napiModule.exports.RawJavascriptParserCommonjsExports -module.exports.RawRuleSetConditionType = __napiModule.exports.RawRuleSetConditionType -module.exports.registerGlobalTrace = __napiModule.exports.registerGlobalTrace -module.exports.RegisterJsTapKind = __napiModule.exports.RegisterJsTapKind -module.exports.sync = __napiModule.exports.sync -module.exports.syncTraceEvent = __napiModule.exports.syncTraceEvent -module.exports.transform = __napiModule.exports.transform -module.exports.transformSync = __napiModule.exports.transformSync + diff --git a/packages/rspack/etc/core.api.md b/packages/rspack/etc/core.api.md index 2e5cbd45e25c..69cfef7c7419 100644 --- a/packages/rspack/etc/core.api.md +++ b/packages/rspack/etc/core.api.md @@ -8442,7 +8442,7 @@ class TreeShakingSharedPlugin { // (undocumented) outputDir: string; // (undocumented) - reShake?: boolean; + secondary?: boolean; } // @public (undocumented) @@ -8450,7 +8450,7 @@ export interface TreeshakingSharedPluginOptions { // (undocumented) mfConfig: ModuleFederationPluginOptions; // (undocumented) - reShake?: boolean; + secondary?: boolean; } // @public (undocumented) diff --git a/packages/rspack/package.json b/packages/rspack/package.json index 28f827f468c2..c53a0c2e6a88 100644 --- a/packages/rspack/package.json +++ b/packages/rspack/package.json @@ -65,7 +65,7 @@ "webpack-sources": "3.3.3" }, "dependencies": { - "@module-federation/runtime-tools": "0.0.0-feat-shared-treeshake-poc-20260112063915", + "@module-federation/runtime-tools": "0.0.0-feat-shared-treeshake-poc-20260114091859", "@rspack/binding": "workspace:*", "@rspack/lite-tapable": "1.1.0" }, diff --git a/packages/rspack/src/container/ModuleFederationPlugin.ts b/packages/rspack/src/container/ModuleFederationPlugin.ts index 23cec8dad615..a809ad8e68ed 100644 --- a/packages/rspack/src/container/ModuleFederationPlugin.ts +++ b/packages/rspack/src/container/ModuleFederationPlugin.ts @@ -50,7 +50,7 @@ export class ModuleFederationPlugin { if (treeShakingEntries.length > 0) { this._treeShakingSharedPlugin = new TreeShakingSharedPlugin({ mfConfig: this._options, - reShake: false, + secondary: false, }); this._treeShakingSharedPlugin.apply(compiler); } diff --git a/packages/rspack/src/sharing/TreeShakingSharedPlugin.ts b/packages/rspack/src/sharing/TreeShakingSharedPlugin.ts index d8cce4e89717..d630f50d14a1 100644 --- a/packages/rspack/src/sharing/TreeShakingSharedPlugin.ts +++ b/packages/rspack/src/sharing/TreeShakingSharedPlugin.ts @@ -6,25 +6,25 @@ import { normalizeSharedOptions } from './SharePlugin'; export interface TreeshakingSharedPluginOptions { mfConfig: ModuleFederationPluginOptions; - reShake?: boolean; + secondary?: boolean; } export class TreeShakingSharedPlugin { mfConfig: ModuleFederationPluginOptions; outputDir: string; - reShake?: boolean; + secondary?: boolean; private _independentSharePlugin?: IndependentSharedPlugin; name = 'TreeShakingSharedPlugin'; constructor(options: TreeshakingSharedPluginOptions) { - const { mfConfig, reShake } = options; + const { mfConfig, secondary } = options; this.mfConfig = mfConfig; this.outputDir = mfConfig.treeShakingSharedDir || 'independent-packages'; - this.reShake = Boolean(reShake); + this.secondary = Boolean(secondary); } apply(compiler: Compiler) { - const { mfConfig, outputDir, reShake } = this; + const { mfConfig, outputDir, secondary } = this; const { name, shared, library, treeShakingSharedPlugins } = mfConfig; if (!shared) { return; @@ -39,7 +39,7 @@ export class TreeShakingSharedPlugin { ([_, config]) => config.treeShaking && config.import !== false, ) ) { - if (!reShake) { + if (!secondary) { new SharedUsedExportsOptimizerPlugin( sharedOptions, mfConfig.injectTreeShakingUsedExports, @@ -55,7 +55,7 @@ export class TreeShakingSharedPlugin { const _constructor = require(p); return new _constructor(); }) || [], - treeShaking: reShake, + treeShaking: secondary, library, manifest: mfConfig.manifest, treeShakingSharedExcludePlugins: diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fd6724106a90..91774ff3d27a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -345,8 +345,8 @@ importers: packages/rspack: dependencies: '@module-federation/runtime-tools': - specifier: 0.0.0-feat-shared-treeshake-poc-20260112063915 - version: 0.0.0-feat-shared-treeshake-poc-20260112063915 + specifier: 0.0.0-feat-shared-treeshake-poc-20260114091859 + version: 0.0.0-feat-shared-treeshake-poc-20260114091859 '@rspack/binding': specifier: workspace:* version: link:../../crates/node_binding @@ -2436,8 +2436,8 @@ packages: '@microsoft/tsdoc@0.16.0': resolution: {integrity: sha512-xgAyonlVVS+q7Vc7qLW0UrJU7rSFcETRWsqdXZtjzRU8dF+6CkozTK4V4y1LwOX7j8r/vHphjDeMeGI4tNGeGA==} - '@module-federation/error-codes@0.0.0-feat-shared-treeshake-poc-20260112063915': - resolution: {integrity: sha512-4uEX/pP736lBol4kNQhBXWxgi5ZwYt5yessvex4QyPBFhgbwKUAlUXkDjq9majoDUvfwrnmR3qVcyZldyffzsQ==} + '@module-federation/error-codes@0.0.0-feat-shared-treeshake-poc-20260114091859': + resolution: {integrity: sha512-9OWijy+79YkHNWjuw0V8pLBoJPyIrjnVDfoC/2Ojg1QdWCRHld8oVj5JozU5J/GbFEzqm8ChOEmU6IWF5mNHNg==} '@module-federation/error-codes@0.21.6': resolution: {integrity: sha512-MLJUCQ05KnoVl8xd6xs9a5g2/8U+eWmVxg7xiBMeR0+7OjdWUbHwcwgVFatRIwSZvFgKHfWEiI7wsU1q1XbTRQ==} @@ -2445,8 +2445,8 @@ packages: '@module-federation/error-codes@0.22.0': resolution: {integrity: sha512-xF9SjnEy7vTdx+xekjPCV5cIHOGCkdn3pIxo9vU7gEZMIw0SvAEdsy6Uh17xaCpm8V0FWvR0SZoK9Ik6jGOaug==} - '@module-federation/runtime-core@0.0.0-feat-shared-treeshake-poc-20260112063915': - resolution: {integrity: sha512-tUlxVoY12LFvY3kCwiVMFtoMhJ0+/Igmca4MD3iA9e52s/regdpfucNhZHCpsg9fYmY7uJsjeLMVB45vbM0cKA==} + '@module-federation/runtime-core@0.0.0-feat-shared-treeshake-poc-20260114091859': + resolution: {integrity: sha512-KmLnVDlMSeMRI3pnhhplO4f1t7j7CQJv49Wf+s6P4K6lRxoAD9+OOf29RDfo7Lqvux/nYfmxGGFUGJ8mh22QrA==} '@module-federation/runtime-core@0.21.6': resolution: {integrity: sha512-5Hd1Y5qp5lU/aTiK66lidMlM/4ji2gr3EXAtJdreJzkY+bKcI5+21GRcliZ4RAkICmvdxQU5PHPL71XmNc7Lsw==} @@ -2454,8 +2454,8 @@ packages: '@module-federation/runtime-core@0.22.0': resolution: {integrity: sha512-GR1TcD6/s7zqItfhC87zAp30PqzvceoeDGYTgF3Vx2TXvsfDrhP6Qw9T4vudDQL3uJRne6t7CzdT29YyVxlgIA==} - '@module-federation/runtime-tools@0.0.0-feat-shared-treeshake-poc-20260112063915': - resolution: {integrity: sha512-WsMFP6u0ii3v4htfAF5WglAFQOz3l6wNgifU5bZJfCCBDL6xfp8yUhXQBmY26NosDYBGyZeVXB+YI4By4dH5dQ==} + '@module-federation/runtime-tools@0.0.0-feat-shared-treeshake-poc-20260114091859': + resolution: {integrity: sha512-v1sAMviM9OtPeOQKu4eW7SEo0d57M0ojWgI9rubvRdUX/lee3p02rpA8D8ouXsTvWR8zkBT+arrMhKwfv8/U+g==} '@module-federation/runtime-tools@0.21.6': resolution: {integrity: sha512-fnP+ZOZTFeBGiTAnxve+axGmiYn2D60h86nUISXjXClK3LUY1krUfPgf6MaD4YDJ4i51OGXZWPekeMe16pkd8Q==} @@ -2463,8 +2463,8 @@ packages: '@module-federation/runtime-tools@0.22.0': resolution: {integrity: sha512-4ScUJ/aUfEernb+4PbLdhM/c60VHl698Gn1gY21m9vyC1Ucn69fPCA1y2EwcCB7IItseRMoNhdcWQnzt/OPCNA==} - '@module-federation/runtime@0.0.0-feat-shared-treeshake-poc-20260112063915': - resolution: {integrity: sha512-u4SaPkbYtMWdEmxbXhEj13nROnGBr02U6IXF8JXIvvPEHO+ryF/DXJt21HTCgVzYjf2q2kkam0pd7qd+82R/Eg==} + '@module-federation/runtime@0.0.0-feat-shared-treeshake-poc-20260114091859': + resolution: {integrity: sha512-Sp+3lm1Z+7xZcBDkEozF78LSLhR3gAySSMKLhmv14NRls0EkPwEuaDZAS6SZwpWeZ9zubwch977jDq4hRcCgeA==} '@module-federation/runtime@0.21.6': resolution: {integrity: sha512-+caXwaQqwTNh+CQqyb4mZmXq7iEemRDrTZQGD+zyeH454JAYnJ3s/3oDFizdH6245pk+NiqDyOOkHzzFQorKhQ==} @@ -2472,8 +2472,8 @@ packages: '@module-federation/runtime@0.22.0': resolution: {integrity: sha512-38g5iPju2tPC3KHMPxRKmy4k4onNp6ypFPS1eKGsNLUkXgHsPMBFqAjDw96iEcjri91BrahG4XcdyKi97xZzlA==} - '@module-federation/sdk@0.0.0-feat-shared-treeshake-poc-20260112063915': - resolution: {integrity: sha512-O8jgq1o8blGys+zf87ToqNsjTaRBUV9zfzcpy4S1YPCAOcW8i2alHOdqppJAXF5fGlI6x8+3jXEALGqxAUrkWQ==} + '@module-federation/sdk@0.0.0-feat-shared-treeshake-poc-20260114091859': + resolution: {integrity: sha512-KD8otMLAzLNYGO7W6eGv0ddXt58KO4OJJ4NJsvCNpGDBf3XhbPUOWeswcGxk0dSiAcAGh9qLu9FEslRW+5/3AQ==} '@module-federation/sdk@0.21.6': resolution: {integrity: sha512-x6hARETb8iqHVhEsQBysuWpznNZViUh84qV2yE7AD+g7uIzHKiYdoWqj10posbo5XKf/147qgWDzKZoKoEP2dw==} @@ -2481,8 +2481,8 @@ packages: '@module-federation/sdk@0.22.0': resolution: {integrity: sha512-x4aFNBKn2KVQRuNVC5A7SnrSCSqyfIWmm1DvubjbO9iKFe7ith5niw8dqSFBekYBg2Fwy+eMg4sEFNVvCAdo6g==} - '@module-federation/webpack-bundler-runtime@0.0.0-feat-shared-treeshake-poc-20260112063915': - resolution: {integrity: sha512-ULsyc6WLtiyeZ3BegBL685cCBc5XrxjvwnGhNcsE4POY5Eev/fznBq3lsLoeycc2bHwXxaZzk0u8OYmH1Mnn9A==} + '@module-federation/webpack-bundler-runtime@0.0.0-feat-shared-treeshake-poc-20260114091859': + resolution: {integrity: sha512-q+PPBcIT8rBUobBvS6eEcP9IZn9jBv796LNtpsYLwy643aAvMsRefAUJnI9KmMdJLQLareO6j/6uNkzYJ4mAmA==} '@module-federation/webpack-bundler-runtime@0.21.6': resolution: {integrity: sha512-7zIp3LrcWbhGuFDTUMLJ2FJvcwjlddqhWGxi/MW3ur1a+HaO8v5tF2nl+vElKmbG1DFLU/52l3PElVcWf/YcsQ==} @@ -10220,16 +10220,16 @@ snapshots: '@microsoft/tsdoc@0.16.0': {} - '@module-federation/error-codes@0.0.0-feat-shared-treeshake-poc-20260112063915': {} + '@module-federation/error-codes@0.0.0-feat-shared-treeshake-poc-20260114091859': {} '@module-federation/error-codes@0.21.6': {} '@module-federation/error-codes@0.22.0': {} - '@module-federation/runtime-core@0.0.0-feat-shared-treeshake-poc-20260112063915': + '@module-federation/runtime-core@0.0.0-feat-shared-treeshake-poc-20260114091859': dependencies: - '@module-federation/error-codes': 0.0.0-feat-shared-treeshake-poc-20260112063915 - '@module-federation/sdk': 0.0.0-feat-shared-treeshake-poc-20260112063915 + '@module-federation/error-codes': 0.0.0-feat-shared-treeshake-poc-20260114091859 + '@module-federation/sdk': 0.0.0-feat-shared-treeshake-poc-20260114091859 '@module-federation/runtime-core@0.21.6': dependencies: @@ -10241,10 +10241,10 @@ snapshots: '@module-federation/error-codes': 0.22.0 '@module-federation/sdk': 0.22.0 - '@module-federation/runtime-tools@0.0.0-feat-shared-treeshake-poc-20260112063915': + '@module-federation/runtime-tools@0.0.0-feat-shared-treeshake-poc-20260114091859': dependencies: - '@module-federation/runtime': 0.0.0-feat-shared-treeshake-poc-20260112063915 - '@module-federation/webpack-bundler-runtime': 0.0.0-feat-shared-treeshake-poc-20260112063915 + '@module-federation/runtime': 0.0.0-feat-shared-treeshake-poc-20260114091859 + '@module-federation/webpack-bundler-runtime': 0.0.0-feat-shared-treeshake-poc-20260114091859 '@module-federation/runtime-tools@0.21.6': dependencies: @@ -10256,11 +10256,11 @@ snapshots: '@module-federation/runtime': 0.22.0 '@module-federation/webpack-bundler-runtime': 0.22.0 - '@module-federation/runtime@0.0.0-feat-shared-treeshake-poc-20260112063915': + '@module-federation/runtime@0.0.0-feat-shared-treeshake-poc-20260114091859': dependencies: - '@module-federation/error-codes': 0.0.0-feat-shared-treeshake-poc-20260112063915 - '@module-federation/runtime-core': 0.0.0-feat-shared-treeshake-poc-20260112063915 - '@module-federation/sdk': 0.0.0-feat-shared-treeshake-poc-20260112063915 + '@module-federation/error-codes': 0.0.0-feat-shared-treeshake-poc-20260114091859 + '@module-federation/runtime-core': 0.0.0-feat-shared-treeshake-poc-20260114091859 + '@module-federation/sdk': 0.0.0-feat-shared-treeshake-poc-20260114091859 '@module-federation/runtime@0.21.6': dependencies: @@ -10274,16 +10274,16 @@ snapshots: '@module-federation/runtime-core': 0.22.0 '@module-federation/sdk': 0.22.0 - '@module-federation/sdk@0.0.0-feat-shared-treeshake-poc-20260112063915': {} + '@module-federation/sdk@0.0.0-feat-shared-treeshake-poc-20260114091859': {} '@module-federation/sdk@0.21.6': {} '@module-federation/sdk@0.22.0': {} - '@module-federation/webpack-bundler-runtime@0.0.0-feat-shared-treeshake-poc-20260112063915': + '@module-federation/webpack-bundler-runtime@0.0.0-feat-shared-treeshake-poc-20260114091859': dependencies: - '@module-federation/runtime': 0.0.0-feat-shared-treeshake-poc-20260112063915 - '@module-federation/sdk': 0.0.0-feat-shared-treeshake-poc-20260112063915 + '@module-federation/runtime': 0.0.0-feat-shared-treeshake-poc-20260114091859 + '@module-federation/sdk': 0.0.0-feat-shared-treeshake-poc-20260114091859 '@module-federation/webpack-bundler-runtime@0.21.6': dependencies: diff --git a/tests/rspack-test/configCases/container-1-5/manifest-disable-assets-analyze/package.json b/tests/rspack-test/configCases/container-1-5/manifest-disable-assets-analyze/package.json new file mode 100644 index 000000000000..275b33fac442 --- /dev/null +++ b/tests/rspack-test/configCases/container-1-5/manifest-disable-assets-analyze/package.json @@ -0,0 +1,7 @@ +{ + "name": "manifest-disable-assets-analyze", + "version": "1.0.0", + "dependencies": { + "react": "^1.0.0" + } +} \ No newline at end of file diff --git a/tests/rspack-test/configCases/container-1-5/manifest-file-name/package.json b/tests/rspack-test/configCases/container-1-5/manifest-file-name/package.json new file mode 100644 index 000000000000..23dc364280c4 --- /dev/null +++ b/tests/rspack-test/configCases/container-1-5/manifest-file-name/package.json @@ -0,0 +1,7 @@ +{ + "name": "manifest-file-name", + "version": "1.0.0", + "dependencies": { + "react": "^1.0.0" + } +} \ No newline at end of file diff --git a/tests/rspack-test/configCases/sharing/reshake-share/CustomPlugin.js b/tests/rspack-test/configCases/sharing/reshake-share/CustomPlugin.js index ea059b07e499..33acd3bf6441 100644 --- a/tests/rspack-test/configCases/sharing/reshake-share/CustomPlugin.js +++ b/tests/rspack-test/configCases/sharing/reshake-share/CustomPlugin.js @@ -7,7 +7,7 @@ class CustomPlugin { }, async () => { compilation.emitAsset('apply-plugin.json', new compilation.compiler.rspack.sources.RawSource(JSON.stringify({ - reShake: true + secondary: true }))) }) }) diff --git a/tests/rspack-test/configCases/sharing/reshake-share/index.js b/tests/rspack-test/configCases/sharing/reshake-share/index.js index 87c399c8a755..1f2f88d31ef2 100644 --- a/tests/rspack-test/configCases/sharing/reshake-share/index.js +++ b/tests/rspack-test/configCases/sharing/reshake-share/index.js @@ -35,8 +35,8 @@ it("should build independent share file", () => { expect(fs.existsSync(customPluginAssetPath)).toBe(true); }); -it("reshake share container should only have specify usedExports", async () => { - const uiLibDepShareContainerModule = __non_webpack_require__(uiLibDepShareContainerPath).reshake_share_ui_lib_dep_100; +it("secondary tree shaking shared container should only have specify usedExports", async () => { + const uiLibDepShareContainerModule = __non_webpack_require__(uiLibDepShareContainerPath).secondary_tree_shaking_share_ui_lib_dep_100; await uiLibDepShareContainerModule.init({},{ installInitialConsumes: async ()=>{ return 'call init' @@ -49,8 +49,8 @@ it("reshake share container should only have specify usedExports", async () => { }); -it("correct handle share dep while reshake", async () => { - const uiLibShareContainerModule = __non_webpack_require__(uiLibShareContainerPath).reshake_share_ui_lib_100; +it("correct handle share dep while secondary tree shaking", async () => { + const uiLibShareContainerModule = __non_webpack_require__(uiLibShareContainerPath).secondary_tree_shaking_share_ui_lib_100; await uiLibShareContainerModule.init({},{ installInitialConsumes: async ({webpackRequire})=>{ webpackRequire.m['webpack/sharing/consume/default/ui-lib-dep'] = (m)=>{ diff --git a/tests/rspack-test/configCases/sharing/reshake-share/rspack.config.js b/tests/rspack-test/configCases/sharing/reshake-share/rspack.config.js index 2da9224482b6..d6756beb9c61 100644 --- a/tests/rspack-test/configCases/sharing/reshake-share/rspack.config.js +++ b/tests/rspack-test/configCases/sharing/reshake-share/rspack.config.js @@ -14,9 +14,9 @@ module.exports = { }, plugins: [ new TreeShakingSharedPlugin({ - reShake: true, + secondary: true, mfConfig: { - name: 'reshake_share', + name: 'secondary_tree_shaking_share', library: { type: 'commonjs2', }, diff --git a/website/docs/en/plugins/webpack/tree-shaking-shared-plugin.mdx b/website/docs/en/plugins/webpack/tree-shaking-shared-plugin.mdx index 8b1145ca57af..630cbaf41c03 100644 --- a/website/docs/en/plugins/webpack/tree-shaking-shared-plugin.mdx +++ b/website/docs/en/plugins/webpack/tree-shaking-shared-plugin.mdx @@ -12,7 +12,7 @@ import { Stability, ApiMeta } from '@components/ApiMeta'; - `mfConfig`: `ModuleFederationPluginOptions`, configuration passed to the Module Federation plugin. - `plugins`: extra plugins reused during independent builds. -- `reShake`: whether to perform a second tree-shake during independent builds (typically used when the deployment platform has determined complete dependency info and triggers a fresh build to improve tree-shake accuracy for shared dependencies). +- `secondary`: whether to perform a second tree-shake during independent builds (typically used when the deployment platform has determined complete dependency info and triggers a fresh build to improve tree-shake accuracy for shared dependencies). **Usage** @@ -23,7 +23,7 @@ const { TreeShakingSharedPlugin } = require('@rspack/core'); module.exports = { plugins: [ new TreeShakingSharedPlugin({ - reShake: true, + secondary: true, mfConfig: { name: 'app', shared: { @@ -41,5 +41,5 @@ module.exports = { **Behavior** - Normalizes `shared` into `[shareName, SharedConfig][]`. -- Registers `SharedUsedExportsOptimizerPlugin` when `reShake` is `false` to inject used-exports from the stats manifest. +- Registers `SharedUsedExportsOptimizerPlugin` when `secondary` is `false` to inject used-exports from the stats manifest. - Triggers independent compilation for shared entries with `tree shaking: true`, and writes the produced assets back to the `stats/manifest` (fallback fields). diff --git a/website/docs/zh/plugins/webpack/tree-shaking-shared-plugin.mdx b/website/docs/zh/plugins/webpack/tree-shaking-shared-plugin.mdx index ebb90326d966..221c2047671a 100644 --- a/website/docs/zh/plugins/webpack/tree-shaking-shared-plugin.mdx +++ b/website/docs/zh/plugins/webpack/tree-shaking-shared-plugin.mdx @@ -12,7 +12,7 @@ import { Stability, ApiMeta } from '@components/ApiMeta'; - `mfConfig`:`ModuleFederationPluginOptions`,传入模块联邦插件所需要的配置项。 - `plugins`:额外插件列表,可在独立编译中复用。 -- `reShake`:是否在独立编译阶段执行二次摇树优化(二次摇树通常在部署平台确定了完整的依赖信息后重新触发的一次全新构建,提高共享依赖 tree shaking 命中的准确率)。 +- `secondary`:是否在独立编译阶段执行二次摇树优化(二次摇树通常在部署平台确定了完整的依赖信息后重新触发的一次全新构建,提高共享依赖 tree shaking 命中的准确率)。 **使用示例** @@ -23,7 +23,7 @@ const { TreeShakingSharedPlugin } = require('@rspack/core'); module.exports = { plugins: [ new TreeShakingSharedPlugin({ - reShake: true, + secondary: true, mfConfig: { name: 'app', shared: { @@ -41,5 +41,5 @@ module.exports = { **行为说明** - 读取 `shared` 配置后标准化为 `[shareName, SharedConfig][]`。 -- 当 `reShake` 为 `false` 时,注册 `SharedUsedExportsOptimizerPlugin`,基于 stats 清单注入已用导出集合。 +- 当 `secondary` 为 `false` 时,注册 `SharedUsedExportsOptimizerPlugin`,基于 stats 清单注入已用导出集合。 - 对 `tree shaking` 的共享包触发独立编译,产出回写到 stats/manifest 中的 fallback 字段。 From 58d41d1683e449e9d18412b1fe389b62b9c28249 Mon Sep 17 00:00:00 2001 From: "zhanghang.heal" Date: Wed, 14 Jan 2026 19:01:43 +0800 Subject: [PATCH 58/87] chore: update artificat --- crates/node_binding/rspack.wasi-browser.js | 61 +++++++++++++++++++++- crates/node_binding/rspack.wasi.cjs | 61 +++++++++++++++++++++- 2 files changed, 120 insertions(+), 2 deletions(-) diff --git a/crates/node_binding/rspack.wasi-browser.js b/crates/node_binding/rspack.wasi-browser.js index ee65959b37bc..e3e5c0a99d48 100644 --- a/crates/node_binding/rspack.wasi-browser.js +++ b/crates/node_binding/rspack.wasi-browser.js @@ -63,4 +63,63 @@ const { }, }) export default __napiModule.exports - +export const Assets = __napiModule.exports.Assets +export const AsyncDependenciesBlock = __napiModule.exports.AsyncDependenciesBlock +export const Chunk = __napiModule.exports.Chunk +export const ChunkGraph = __napiModule.exports.ChunkGraph +export const ChunkGroup = __napiModule.exports.ChunkGroup +export const Chunks = __napiModule.exports.Chunks +export const CodeGenerationResult = __napiModule.exports.CodeGenerationResult +export const CodeGenerationResults = __napiModule.exports.CodeGenerationResults +export const ConcatenatedModule = __napiModule.exports.ConcatenatedModule +export const ContextModule = __napiModule.exports.ContextModule +export const Dependency = __napiModule.exports.Dependency +export const Diagnostics = __napiModule.exports.Diagnostics +export const EntryDataDto = __napiModule.exports.EntryDataDto +export const EntryDataDTO = __napiModule.exports.EntryDataDTO +export const EntryDependency = __napiModule.exports.EntryDependency +export const EntryOptionsDto = __napiModule.exports.EntryOptionsDto +export const EntryOptionsDTO = __napiModule.exports.EntryOptionsDTO +export const ExternalModule = __napiModule.exports.ExternalModule +export const JsCompilation = __napiModule.exports.JsCompilation +export const JsCompiler = __napiModule.exports.JsCompiler +export const JsContextModuleFactoryAfterResolveData = __napiModule.exports.JsContextModuleFactoryAfterResolveData +export const JsContextModuleFactoryBeforeResolveData = __napiModule.exports.JsContextModuleFactoryBeforeResolveData +export const JsDependencies = __napiModule.exports.JsDependencies +export const JsEntries = __napiModule.exports.JsEntries +export const JsExportsInfo = __napiModule.exports.JsExportsInfo +export const JsModuleGraph = __napiModule.exports.JsModuleGraph +export const JsResolver = __napiModule.exports.JsResolver +export const JsResolverFactory = __napiModule.exports.JsResolverFactory +export const JsStats = __napiModule.exports.JsStats +export const KnownBuildInfo = __napiModule.exports.KnownBuildInfo +export const Module = __napiModule.exports.Module +export const ModuleGraphConnection = __napiModule.exports.ModuleGraphConnection +export const NativeWatcher = __napiModule.exports.NativeWatcher +export const NativeWatchResult = __napiModule.exports.NativeWatchResult +export const NormalModule = __napiModule.exports.NormalModule +export const RawExternalItemFnCtx = __napiModule.exports.RawExternalItemFnCtx +export const ReadonlyResourceData = __napiModule.exports.ReadonlyResourceData +export const ResolverFactory = __napiModule.exports.ResolverFactory +export const Sources = __napiModule.exports.Sources +export const VirtualFileStore = __napiModule.exports.VirtualFileStore +export const JsVirtualFileStore = __napiModule.exports.JsVirtualFileStore +export const async = __napiModule.exports.async +export const BuiltinPluginName = __napiModule.exports.BuiltinPluginName +export const cleanupGlobalTrace = __napiModule.exports.cleanupGlobalTrace +export const EnforceExtension = __napiModule.exports.EnforceExtension +export const EXPECTED_RSPACK_CORE_VERSION = __napiModule.exports.EXPECTED_RSPACK_CORE_VERSION +export const formatDiagnostic = __napiModule.exports.formatDiagnostic +export const JsLoaderState = __napiModule.exports.JsLoaderState +export const JsRspackSeverity = __napiModule.exports.JsRspackSeverity +export const loadBrowserslist = __napiModule.exports.loadBrowserslist +export const minify = __napiModule.exports.minify +export const minifySync = __napiModule.exports.minifySync +export const RawJavascriptParserCommonjsExports = __napiModule.exports.RawJavascriptParserCommonjsExports +export const RawRuleSetConditionType = __napiModule.exports.RawRuleSetConditionType +export const registerGlobalTrace = __napiModule.exports.registerGlobalTrace +export const RegisterJsTapKind = __napiModule.exports.RegisterJsTapKind +export const sync = __napiModule.exports.sync +export const syncTraceEvent = __napiModule.exports.syncTraceEvent +export const transform = __napiModule.exports.transform +export const transformSync = __napiModule.exports.transformSync diff --git a/crates/node_binding/rspack.wasi.cjs b/crates/node_binding/rspack.wasi.cjs index 1ad96db4aac4..a251ce4d0d7d 100644 --- a/crates/node_binding/rspack.wasi.cjs +++ b/crates/node_binding/rspack.wasi.cjs @@ -108,4 +108,63 @@ const { instance: __napiInstance, module: __wasiModule, napiModule: __napiModule }, }) module.exports = __napiModule.exports - +module.exports.Assets = __napiModule.exports.Assets +module.exports.AsyncDependenciesBlock = __napiModule.exports.AsyncDependenciesBlock +module.exports.Chunk = __napiModule.exports.Chunk +module.exports.ChunkGraph = __napiModule.exports.ChunkGraph +module.exports.ChunkGroup = __napiModule.exports.ChunkGroup +module.exports.Chunks = __napiModule.exports.Chunks +module.exports.CodeGenerationResult = __napiModule.exports.CodeGenerationResult +module.exports.CodeGenerationResults = __napiModule.exports.CodeGenerationResults +module.exports.ConcatenatedModule = __napiModule.exports.ConcatenatedModule +module.exports.ContextModule = __napiModule.exports.ContextModule +module.exports.Dependency = __napiModule.exports.Dependency +module.exports.Diagnostics = __napiModule.exports.Diagnostics +module.exports.EntryDataDto = __napiModule.exports.EntryDataDto +module.exports.EntryDataDTO = __napiModule.exports.EntryDataDTO +module.exports.EntryDependency = __napiModule.exports.EntryDependency +module.exports.EntryOptionsDto = __napiModule.exports.EntryOptionsDto +module.exports.EntryOptionsDTO = __napiModule.exports.EntryOptionsDTO +module.exports.ExternalModule = __napiModule.exports.ExternalModule +module.exports.JsCompilation = __napiModule.exports.JsCompilation +module.exports.JsCompiler = __napiModule.exports.JsCompiler +module.exports.JsContextModuleFactoryAfterResolveData = __napiModule.exports.JsContextModuleFactoryAfterResolveData +module.exports.JsContextModuleFactoryBeforeResolveData = __napiModule.exports.JsContextModuleFactoryBeforeResolveData +module.exports.JsDependencies = __napiModule.exports.JsDependencies +module.exports.JsEntries = __napiModule.exports.JsEntries +module.exports.JsExportsInfo = __napiModule.exports.JsExportsInfo +module.exports.JsModuleGraph = __napiModule.exports.JsModuleGraph +module.exports.JsResolver = __napiModule.exports.JsResolver +module.exports.JsResolverFactory = __napiModule.exports.JsResolverFactory +module.exports.JsStats = __napiModule.exports.JsStats +module.exports.KnownBuildInfo = __napiModule.exports.KnownBuildInfo +module.exports.Module = __napiModule.exports.Module +module.exports.ModuleGraphConnection = __napiModule.exports.ModuleGraphConnection +module.exports.NativeWatcher = __napiModule.exports.NativeWatcher +module.exports.NativeWatchResult = __napiModule.exports.NativeWatchResult +module.exports.NormalModule = __napiModule.exports.NormalModule +module.exports.RawExternalItemFnCtx = __napiModule.exports.RawExternalItemFnCtx +module.exports.ReadonlyResourceData = __napiModule.exports.ReadonlyResourceData +module.exports.ResolverFactory = __napiModule.exports.ResolverFactory +module.exports.Sources = __napiModule.exports.Sources +module.exports.VirtualFileStore = __napiModule.exports.VirtualFileStore +module.exports.JsVirtualFileStore = __napiModule.exports.JsVirtualFileStore +module.exports.async = __napiModule.exports.async +module.exports.BuiltinPluginName = __napiModule.exports.BuiltinPluginName +module.exports.cleanupGlobalTrace = __napiModule.exports.cleanupGlobalTrace +module.exports.EnforceExtension = __napiModule.exports.EnforceExtension +module.exports.EXPECTED_RSPACK_CORE_VERSION = __napiModule.exports.EXPECTED_RSPACK_CORE_VERSION +module.exports.formatDiagnostic = __napiModule.exports.formatDiagnostic +module.exports.JsLoaderState = __napiModule.exports.JsLoaderState +module.exports.JsRspackSeverity = __napiModule.exports.JsRspackSeverity +module.exports.loadBrowserslist = __napiModule.exports.loadBrowserslist +module.exports.minify = __napiModule.exports.minify +module.exports.minifySync = __napiModule.exports.minifySync +module.exports.RawJavascriptParserCommonjsExports = __napiModule.exports.RawJavascriptParserCommonjsExports +module.exports.RawRuleSetConditionType = __napiModule.exports.RawRuleSetConditionType +module.exports.registerGlobalTrace = __napiModule.exports.registerGlobalTrace +module.exports.RegisterJsTapKind = __napiModule.exports.RegisterJsTapKind +module.exports.sync = __napiModule.exports.sync +module.exports.syncTraceEvent = __napiModule.exports.syncTraceEvent +module.exports.transform = __napiModule.exports.transform +module.exports.transformSync = __napiModule.exports.transformSync From 63a410af4c13be213104f822886389b5fe7403d4 Mon Sep 17 00:00:00 2001 From: 9aoy <9aoyuao@gmail.com> Date: Wed, 14 Jan 2026 22:04:25 +0800 Subject: [PATCH 59/87] test: use Rstest projects to define tests (#12729) * test: use rstest projects * test: update * test: output.module * test: update --- package.json | 2 +- packages/rspack-cli/rstest.config.ts | 1 + pnpm-lock.yaml | 14 ++++----- tests/rspack-test/package.json | 10 +++---- tests/rspack-test/rstest.config.hot.ts | 7 ----- tests/rspack-test/rstest.config.ts | 41 ++++++++++++++++---------- 6 files changed, 40 insertions(+), 35 deletions(-) delete mode 100644 tests/rspack-test/rstest.config.hot.ts diff --git a/package.json b/package.json index bb382484ad95..8132001260ce 100644 --- a/package.json +++ b/package.json @@ -74,7 +74,7 @@ "cross-env": "^10.1.0", "husky": "^9.1.7", "is-ci": "4.1.0", - "@rstest/core": "^0.7.8", + "@rstest/core": "^0.7.9", "lint-staged": "^16.2.7", "prettier": "3.7.4", "prettier-2": "npm:prettier@2.8.8", diff --git a/packages/rspack-cli/rstest.config.ts b/packages/rspack-cli/rstest.config.ts index 17b6894cc8d6..ab1b0e96ae29 100644 --- a/packages/rspack-cli/rstest.config.ts +++ b/packages/rspack-cli/rstest.config.ts @@ -22,6 +22,7 @@ export default defineConfig({ }, output: { externals: [/@rspack\/core/], + module: false, }, env: { RUST_BACKTRACE: 'full', diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1cf733f19309..78cf7d83faac 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -29,8 +29,8 @@ importers: specifier: workspace:* version: link:packages/rspack-cli '@rstest/core': - specifier: ^0.7.8 - version: 0.7.8(jsdom@26.1.0) + specifier: ^0.7.9 + version: 0.7.9(jsdom@26.1.0) '@taplo/cli': specifier: ^0.7.0 version: 0.7.0 @@ -733,8 +733,8 @@ importers: specifier: workspace:* version: link:../../packages/rspack-test-tools '@rstest/core': - specifier: ^0.7.8 - version: 0.7.8(jsdom@26.1.0) + specifier: ^0.7.9 + version: 0.7.9(jsdom@26.1.0) '@swc/helpers': specifier: 0.5.18 version: 0.5.18 @@ -3582,8 +3582,8 @@ packages: '@rstack-dev/doc-ui@1.12.2': resolution: {integrity: sha512-4C+tfhODxCp81ohCik9baOdbhYGNFqdwcwQMAESncF0YX3EawdNCORI1E26DqkY/F3ggfKG4qOlEAu+oOxrPxg==} - '@rstest/core@0.7.8': - resolution: {integrity: sha512-A7oN5GLMYuVkTGjXTH+69nz3wR0lxHUkWax+hVq+jNQmcf81ZqJosTLqN6jwFZdmCfHbj3iTd9ku6boo8tJlnA==} + '@rstest/core@0.7.9': + resolution: {integrity: sha512-RHNPS1MDUxtf+1Z0YZi+vIQ13SdvCbcbpzDA7XHcPziTRy2mAPg8nfcms+XzbIp95KXH75ucAhgAKNFO0QgARA==} engines: {node: '>=18.12.0'} hasBin: true peerDependencies: @@ -11237,7 +11237,7 @@ snapshots: - react - react-dom - '@rstest/core@0.7.8(jsdom@26.1.0)': + '@rstest/core@0.7.9(jsdom@26.1.0)': dependencies: '@rsbuild/core': 1.7.1 '@types/chai': 5.2.3 diff --git a/tests/rspack-test/package.json b/tests/rspack-test/package.json index e1ad121a7ae5..fe7ec3a9c3b2 100644 --- a/tests/rspack-test/package.json +++ b/tests/rspack-test/package.json @@ -7,10 +7,10 @@ "author": "", "license": "ISC", "scripts": { - "test": "cross-env RUST_BACKTRACE=full pnpm run --stream /^test:.*/", - "testu": "pnpm run --stream /^test:.*/ -u", - "test:base": "rstest", - "test:hot": "cross-env RSPACK_HOT_TEST=true node --no-warnings --expose-gc --max-old-space-size=8192 --experimental-vm-modules ../../node_modules/@rstest/core/bin/rstest --config ./rstest.config.hot.ts --passWithNoTests" + "test": "rstest", + "testu": "rstest -u", + "test:base": "rstest --project base", + "test:hot": "rstest --project hottest" }, "devDependencies": { "@rspack/cli": "workspace:*", @@ -19,7 +19,7 @@ "@rspack/plugin-preact-refresh": "1.1.4", "@rspack/plugin-react-refresh": "^1.6.0", "@rspack/test-tools": "workspace:*", - "@rstest/core": "^0.7.8", + "@rstest/core": "^0.7.9", "@swc/helpers": "0.5.18", "@swc/plugin-remove-console": "^12.1.0", "@types/babel__generator": "7.27.0", diff --git a/tests/rspack-test/rstest.config.hot.ts b/tests/rspack-test/rstest.config.hot.ts deleted file mode 100644 index 158301288274..000000000000 --- a/tests/rspack-test/rstest.config.hot.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { defineConfig } from '@rstest/core'; -import config from './rstest.config' - -export default defineConfig({ - ...config, - include: process.env.WASM ? [] : ["/*.hottest.js"] -}); diff --git a/tests/rspack-test/rstest.config.ts b/tests/rspack-test/rstest.config.ts index d2ec3209a5b3..aa8c2ead2b58 100644 --- a/tests/rspack-test/rstest.config.ts +++ b/tests/rspack-test/rstest.config.ts @@ -1,5 +1,6 @@ import path from 'node:path'; -import { defineConfig } from '@rstest/core'; +import { defineConfig, defineProject, type ProjectConfig } from '@rstest/core'; + const root = path.resolve(__dirname, "../../"); process.env.NO_COLOR = '1'; @@ -9,7 +10,7 @@ const setupFilesAfterEnv = [ "@rspack/test-tools/setup-expect", ]; -const wasmConfig = process.env.WASM && defineConfig({ +const wasmConfig = process.env.WASM && defineProject({ setupFiles: [...setupFilesAfterEnv, "@rspack/test-tools/setup-wasm"], exclude: [ // Skip because they rely on snapshots @@ -31,20 +32,16 @@ const wasmConfig = process.env.WASM && defineConfig({ "NativeWatcher*.test.js", ], maxConcurrency: 1, - pool: { - maxWorkers: 1, - execArgv: ['--no-warnings', '--expose-gc', '--max-old-space-size=6144', '--experimental-vm-modules'], - } }); -export default defineConfig({ +const sharedConfig = defineProject({ setupFiles: setupFilesAfterEnv, testTimeout: process.env.CI ? 60000 : 30000, include: [ "*.test.js", ], slowTestThreshold: 5000, - // Retry on CI to reduce flakes + // Retry on CI to reduce flakes retry: process.env.CI ? 3 : 0, resolve: { alias: { @@ -70,13 +67,9 @@ export default defineConfig({ chaiConfig: process.env.CI ? { // show all info on CI truncateThreshold: 5000, - } : undefined, - pool: { - maxWorkers: "80%", - execArgv: ['--no-warnings', '--expose-gc', '--max-old-space-size=8192', '--experimental-vm-modules'], - }, env: { + RUST_BACKTRACE: 'full', updateSnapshot: process.argv.includes("-u") || process.argv.includes("--updateSnapshot") ? 'true' : 'false', RSPACK_DEV: 'false', @@ -104,8 +97,26 @@ export default defineConfig({ __RSPACK_TEST_TOOLS_PATH__: path.resolve(root, "packages/rspack-test-tools"), __DEBUG__: process.env.DEBUG === "test" ? 'true' : 'false', }, - hideSkippedTests: true, - reporters: ['default'], ...(wasmConfig || {}), +}) as ProjectConfig; + +export default defineConfig({ + projects: [{ + extends: sharedConfig, + name: 'base', + }, { + extends: sharedConfig, + name: 'hottest', + include: process.env.WASM ? [] : ["/*.hottest.js"], + env: { + RSPACK_HOT_TEST: 'true', + }, + }], + reporters: ['default'], + hideSkippedTests: true, + pool: { + maxWorkers: process.env.WASM ? 1 : "80%", + execArgv: ['--no-warnings', '--expose-gc', '--max-old-space-size=8192', '--experimental-vm-modules'], + }, }); From 785c0f6fb668cee71b3dd79f9addb5e236f8ce2d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 14 Jan 2026 22:56:41 +0800 Subject: [PATCH 60/87] chore(deps): update patch npm dependencies (#12717) * chore(deps): update patch npm dependencies * fix: downgrade MF --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: neverland --- examples/react/package.json | 2 +- package.json | 2 +- packages/create-rspack/package.json | 2 +- .../template-react-js/package.json | 2 +- .../template-react-ts/package.json | 2 +- packages/rspack-cli/package.json | 2 +- packages/rspack-test-tools/package.json | 10 +- packages/rspack/package.json | 6 +- pnpm-lock.yaml | 1077 ++++++++--------- tests/bench/package.json | 2 +- tests/e2e/package.json | 2 +- tests/rspack-test/package.json | 4 +- website/package.json | 20 +- 13 files changed, 504 insertions(+), 629 deletions(-) diff --git a/examples/react/package.json b/examples/react/package.json index 136b1c245d66..885ba8be4b36 100644 --- a/examples/react/package.json +++ b/examples/react/package.json @@ -15,7 +15,7 @@ "@rspack/cli": "workspace:*", "@rspack/core": "workspace:*", "@rspack/plugin-react-refresh": "^1.6.0", - "@types/react": "^19.2.7", + "@types/react": "^19.2.8", "@types/react-dom": "^19.2.3", "react-refresh": "^0.18.0", "typescript": "^5.9.3" diff --git a/package.json b/package.json index 8132001260ce..a8af2948b7ba 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ "@rspack/cli": "workspace:*", "@taplo/cli": "^0.7.0", "@types/is-ci": "^3.0.4", - "@types/node": "^20.19.27", + "@types/node": "^20.19.29", "check-dependency-version-consistency": "^5.0.1", "commander": "14.0.2", "cross-env": "^10.1.0", diff --git a/packages/create-rspack/package.json b/packages/create-rspack/package.json index 899338ede751..42a0e2011b58 100644 --- a/packages/create-rspack/package.json +++ b/packages/create-rspack/package.json @@ -27,7 +27,7 @@ "create-rstack": "1.7.20" }, "devDependencies": { - "@rslib/core": "0.19.1", + "@rslib/core": "0.19.2", "typescript": "^5.9.3" }, "publishConfig": { diff --git a/packages/create-rspack/template-react-js/package.json b/packages/create-rspack/template-react-js/package.json index 5490a95adaad..fea794822d92 100644 --- a/packages/create-rspack/template-react-js/package.json +++ b/packages/create-rspack/template-react-js/package.json @@ -15,7 +15,7 @@ "@rspack/cli": "workspace:*", "@rspack/core": "workspace:*", "@rspack/plugin-react-refresh": "^1.6.0", - "@types/react": "^19.2.7", + "@types/react": "^19.2.8", "@types/react-dom": "^19.2.3", "react-refresh": "^0.18.0" } diff --git a/packages/create-rspack/template-react-ts/package.json b/packages/create-rspack/template-react-ts/package.json index 7e0082ccd117..70ef071ed8cc 100644 --- a/packages/create-rspack/template-react-ts/package.json +++ b/packages/create-rspack/template-react-ts/package.json @@ -15,7 +15,7 @@ "@rspack/cli": "workspace:*", "@rspack/core": "workspace:*", "@rspack/plugin-react-refresh": "^1.6.0", - "@types/react": "^19.2.7", + "@types/react": "^19.2.8", "@types/react-dom": "^19.2.3", "react-refresh": "^0.18.0", "typescript": "^5.9.3" diff --git a/packages/rspack-cli/package.json b/packages/rspack-cli/package.json index 0e860620b40f..b4c771dbeebc 100644 --- a/packages/rspack-cli/package.json +++ b/packages/rspack-cli/package.json @@ -39,7 +39,7 @@ "webpack-bundle-analyzer": "4.10.2" }, "devDependencies": { - "@rslib/core": "0.19.1", + "@rslib/core": "0.19.2", "@rspack/core": "workspace:*", "@rspack/test-tools": "workspace:*", "@types/webpack-bundle-analyzer": "^4.7.0", diff --git a/packages/rspack-test-tools/package.json b/packages/rspack-test-tools/package.json index 52bab598adb4..f92246f768fe 100644 --- a/packages/rspack-test-tools/package.json +++ b/packages/rspack-test-tools/package.json @@ -41,14 +41,14 @@ "directory": "packages/rspack-test-tools" }, "dependencies": { - "@babel/generator": "7.28.5", - "@babel/parser": "7.28.5", - "@babel/traverse": "7.28.5", - "@babel/types": "7.28.5", + "@babel/generator": "7.28.6", + "@babel/parser": "7.28.6", + "@babel/traverse": "7.28.6", + "@babel/types": "7.28.6", "cross-env": "^10.1.0", "filenamify": "4.3.0", "fs-extra": "^11.3.3", - "iconv-lite": "^0.7.1", + "iconv-lite": "^0.7.2", "javascript-stringify": "^2.1.0", "jest-diff": "^30.2.0", "jest-snapshot": "29.7.0", diff --git a/packages/rspack/package.json b/packages/rspack/package.json index 1f19f871cfa5..808c625ec961 100644 --- a/packages/rspack/package.json +++ b/packages/rspack/package.json @@ -46,12 +46,12 @@ "directory": "packages/rspack" }, "devDependencies": { - "@ast-grep/napi": "^0.40.4", + "@ast-grep/napi": "^0.40.5", "@napi-rs/wasm-runtime": "1.0.7", "@rsbuild/plugin-node-polyfill": "^1.4.2", - "@rslib/core": "0.19.1", + "@rslib/core": "0.19.2", "@swc/types": "0.1.25", - "@types/node": "^20.19.27", + "@types/node": "^20.19.29", "@types/watchpack": "^2.4.5", "browserslist-load-config": "^1.0.1", "enhanced-resolve": "5.18.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 78cf7d83faac..97be27569e2b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -18,10 +18,10 @@ importers: version: 2.3.11 '@microsoft/api-extractor': specifier: 7.55.2 - version: 7.55.2(@types/node@20.19.27) + version: 7.55.2(@types/node@20.19.29) '@microsoft/api-extractor-model': specifier: 7.32.2 - version: 7.32.2(@types/node@20.19.27) + version: 7.32.2(@types/node@20.19.29) '@rslint/core': specifier: 0.1.13 version: 0.1.13 @@ -38,8 +38,8 @@ importers: specifier: ^3.0.4 version: 3.0.4 '@types/node': - specifier: ^20.19.27 - version: 20.19.27 + specifier: ^20.19.29 + version: 20.19.29 check-dependency-version-consistency: specifier: ^5.0.1 version: 5.0.1 @@ -81,7 +81,7 @@ importers: devDependencies: '@napi-rs/cli': specifier: 3.0.4 - version: 3.0.4(@emnapi/runtime@1.5.0)(@types/node@20.19.27)(emnapi@1.7.1(node-addon-api@7.1.1)) + version: 3.0.4(@emnapi/runtime@1.5.0)(@types/node@20.19.29)(emnapi@1.7.1(node-addon-api@7.1.1)) '@napi-rs/wasm-runtime': specifier: 1.0.7 version: 1.0.7 @@ -127,7 +127,7 @@ importers: devDependencies: '@napi-rs/cli': specifier: 3.0.4 - version: 3.0.4(@emnapi/runtime@1.5.0)(@types/node@20.19.27)(emnapi@1.7.1(node-addon-api@7.1.1)) + version: 3.0.4(@emnapi/runtime@1.5.0)(@types/node@20.19.29)(emnapi@1.7.1(node-addon-api@7.1.1)) '@napi-rs/wasm-runtime': specifier: 1.0.7 version: 1.0.7 @@ -166,11 +166,11 @@ importers: specifier: ^1.6.0 version: 1.6.0(react-refresh@0.18.0) '@types/react': - specifier: ^19.2.7 - version: 19.2.7 + specifier: ^19.2.8 + version: 19.2.8 '@types/react-dom': specifier: ^19.2.3 - version: 19.2.3(@types/react@19.2.7) + version: 19.2.3(@types/react@19.2.8) react-refresh: specifier: ^0.18.0 version: 0.18.0 @@ -221,8 +221,8 @@ importers: version: 1.7.20 devDependencies: '@rslib/core': - specifier: 0.19.1 - version: 0.19.1(@microsoft/api-extractor@7.55.2(@types/node@20.19.27))(typescript@5.9.3) + specifier: 0.19.2 + version: 0.19.2(@microsoft/api-extractor@7.55.2(@types/node@20.19.29))(typescript@5.9.3) typescript: specifier: ^5.9.3 version: 5.9.3 @@ -246,11 +246,11 @@ importers: specifier: ^1.6.0 version: 1.6.0(react-refresh@0.18.0) '@types/react': - specifier: ^19.2.7 - version: 19.2.7 + specifier: ^19.2.8 + version: 19.2.8 '@types/react-dom': specifier: ^19.2.3 - version: 19.2.3(@types/react@19.2.7) + version: 19.2.3(@types/react@19.2.8) react-refresh: specifier: ^0.18.0 version: 0.18.0 @@ -274,11 +274,11 @@ importers: specifier: ^1.6.0 version: 1.6.0(react-refresh@0.18.0) '@types/react': - specifier: ^19.2.7 - version: 19.2.7 + specifier: ^19.2.8 + version: 19.2.8 '@types/react-dom': specifier: ^19.2.3 - version: 19.2.3(@types/react@19.2.7) + version: 19.2.3(@types/react@19.2.8) react-refresh: specifier: ^0.18.0 version: 0.18.0 @@ -358,8 +358,8 @@ importers: version: 0.5.17 devDependencies: '@ast-grep/napi': - specifier: ^0.40.4 - version: 0.40.4 + specifier: ^0.40.5 + version: 0.40.5 '@napi-rs/wasm-runtime': specifier: 1.0.7 version: 1.0.7 @@ -367,14 +367,14 @@ importers: specifier: ^1.4.2 version: 1.4.2(@rsbuild/core@1.7.2) '@rslib/core': - specifier: 0.19.1 - version: 0.19.1(@microsoft/api-extractor@7.55.2(@types/node@20.19.27))(typescript@5.9.3) + specifier: 0.19.2 + version: 0.19.2(@microsoft/api-extractor@7.55.2(@types/node@20.19.29))(typescript@5.9.3) '@swc/types': specifier: 0.1.25 version: 0.1.25 '@types/node': - specifier: ^20.19.27 - version: 20.19.27 + specifier: ^20.19.29 + version: 20.19.29 '@types/watchpack': specifier: ^2.4.5 version: 2.4.5 @@ -449,8 +449,8 @@ importers: version: 4.10.2 devDependencies: '@rslib/core': - specifier: 0.19.1 - version: 0.19.1(@microsoft/api-extractor@7.55.2(@types/node@20.19.27))(typescript@5.9.3) + specifier: 0.19.2 + version: 0.19.2(@microsoft/api-extractor@7.55.2(@types/node@20.19.29))(typescript@5.9.3) '@rspack/core': specifier: workspace:* version: link:../rspack @@ -480,7 +480,7 @@ importers: version: 4.0.7 ts-node: specifier: ^10.9.2 - version: 10.9.2(@types/node@20.19.27)(typescript@5.9.3) + version: 10.9.2(@types/node@20.19.29)(typescript@5.9.3) typescript: specifier: ^5.9.3 version: 5.9.3 @@ -488,17 +488,17 @@ importers: packages/rspack-test-tools: dependencies: '@babel/generator': - specifier: 7.28.5 - version: 7.28.5 + specifier: 7.28.6 + version: 7.28.6 '@babel/parser': - specifier: 7.28.5 - version: 7.28.5 + specifier: 7.28.6 + version: 7.28.6 '@babel/traverse': - specifier: 7.28.5 - version: 7.28.5 + specifier: 7.28.6 + version: 7.28.6 '@babel/types': - specifier: 7.28.5 - version: 7.28.5 + specifier: 7.28.6 + version: 7.28.6 chalk: specifier: ^4.1.2 version: 4.1.2 @@ -512,8 +512,8 @@ importers: specifier: ^11.3.3 version: 11.3.3 iconv-lite: - specifier: ^0.7.1 - version: 0.7.1 + specifier: ^0.7.2 + version: 0.7.2 javascript-stringify: specifier: ^2.1.0 version: 2.1.0 @@ -617,7 +617,7 @@ importers: devDependencies: '@codspeed/vitest-plugin': specifier: ^4.0.1 - version: 4.0.1(vite@7.1.7(@types/node@20.19.27)(jiti@2.6.1)(less@4.4.2)(sass-embedded@1.93.2)(sass@1.93.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(vitest@3.2.4(@types/debug@4.1.12)(@types/node@20.19.27)(jiti@2.6.1)(jsdom@26.1.0)(less@4.4.2)(sass-embedded@1.93.2)(sass@1.93.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 4.0.1(vite@7.1.7(@types/node@20.19.29)(jiti@2.6.1)(less@4.4.2)(sass-embedded@1.93.2)(sass@1.93.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(vitest@3.2.4(@types/debug@4.1.12)(@types/node@20.19.29)(jiti@2.6.1)(jsdom@26.1.0)(less@4.4.2)(sass-embedded@1.93.2)(sass@1.93.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) '@rspack/cli': specifier: workspace:* version: link:../../packages/rspack-cli @@ -628,23 +628,23 @@ importers: specifier: ^1.6.0 version: 1.6.0(react-refresh@0.18.0) '@types/react': - specifier: ^19.2.7 - version: 19.2.7 + specifier: ^19.2.8 + version: 19.2.8 '@types/react-dom': specifier: ^19.2.3 - version: 19.2.3(@types/react@19.2.7) + version: 19.2.3(@types/react@19.2.8) vitest: specifier: ^3.2.4 - version: 3.2.4(@types/debug@4.1.12)(@types/node@20.19.27)(jiti@2.6.1)(jsdom@26.1.0)(less@4.4.2)(sass-embedded@1.93.2)(sass@1.93.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + version: 3.2.4(@types/debug@4.1.12)(@types/node@20.19.29)(jiti@2.6.1)(jsdom@26.1.0)(less@4.4.2)(sass-embedded@1.93.2)(sass@1.93.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) tests/e2e: devDependencies: '@babel/core': - specifier: ^7.28.5 - version: 7.28.5 + specifier: ^7.28.6 + version: 7.28.6 '@babel/preset-react': specifier: ^7.28.5 - version: 7.28.5(@babel/core@7.28.5) + version: 7.28.5(@babel/core@7.28.6) '@playwright/test': specifier: 1.57.0 version: 1.57.0 @@ -665,7 +665,7 @@ importers: version: 11.0.4 babel-loader: specifier: ^10.0.0 - version: 10.0.0(@babel/core@7.28.5)(webpack@5.102.1) + version: 10.0.0(@babel/core@7.28.6)(webpack@5.102.1) core-js: specifier: 3.47.0 version: 3.47.0 @@ -695,7 +695,7 @@ importers: version: 17.4.5(vue@3.5.26(typescript@5.9.3))(webpack@5.102.1) tailwindcss: specifier: ^3.4.19 - version: 3.4.19(ts-node@10.9.2(@types/node@20.19.27)(typescript@5.9.3)) + version: 3.4.19(ts-node@10.9.2(@types/node@20.19.29)(typescript@5.9.3)) typescript: specifier: ^5.9.3 version: 5.9.3 @@ -709,11 +709,11 @@ importers: tests/rspack-test: devDependencies: '@babel/core': - specifier: ^7.28.5 - version: 7.28.5 + specifier: ^7.28.6 + version: 7.28.6 '@babel/preset-react': specifier: ^7.28.5 - version: 7.28.5(@babel/core@7.28.5) + version: 7.28.5(@babel/core@7.28.6) '@rspack/binding-testing': specifier: workspace:* version: link:../../crates/rspack_binding_builder_testing @@ -754,11 +754,11 @@ importers: specifier: ^21.1.7 version: 21.1.7 '@types/react': - specifier: ^19.2.7 - version: 19.2.7 + specifier: ^19.2.8 + version: 19.2.8 '@types/react-dom': specifier: ^19.2.3 - version: 19.2.3(@types/react@19.2.7) + version: 19.2.3(@types/react@19.2.8) '@webdiscus/pug-loader': specifier: ^2.11.1 version: 2.11.1(enhanced-resolve@5.18.4)(pug@3.0.3)(webpack@5.102.1) @@ -767,7 +767,7 @@ importers: version: 8.15.0 babel-loader: specifier: ^10.0.0 - version: 10.0.0(@babel/core@7.28.5)(webpack@5.102.1) + version: 10.0.0(@babel/core@7.28.6)(webpack@5.102.1) babel-plugin-import: specifier: ^1.13.8 version: 1.13.8 @@ -931,14 +931,14 @@ importers: website: dependencies: '@rstack-dev/doc-ui': - specifier: 1.12.2 - version: 1.12.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + specifier: 1.12.3 + version: 1.12.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3) axios: specifier: ^1.13.2 version: 1.13.2 markdown-to-jsx: - specifier: ^9.5.0 - version: 9.5.0(react@19.2.3)(vue@3.5.26(typescript@5.9.3)) + specifier: ^9.5.7 + version: 9.5.7(react@19.2.3)(vue@3.5.26(typescript@5.9.3)) mermaid: specifier: ^11.12.2 version: 11.12.2 @@ -953,38 +953,38 @@ importers: version: 7.7.3 tailwindcss: specifier: ^3.4.19 - version: 3.4.19(ts-node@10.9.2(@types/node@20.19.27)(typescript@5.9.3)) + version: 3.4.19(ts-node@10.9.2(@types/node@20.19.29)(typescript@5.9.3)) devDependencies: '@rsbuild/plugin-sass': specifier: ^1.4.0 version: 1.4.0(@rsbuild/core@1.7.2) '@rspress/core': - specifier: 2.0.0-rc.4 - version: 2.0.0-rc.4(@types/react@19.2.7) + specifier: 2.0.0-rc.5 + version: 2.0.0-rc.5(@types/react@19.2.8) '@rspress/plugin-algolia': - specifier: 2.0.0-rc.4 - version: 2.0.0-rc.4(@algolia/client-search@5.39.0)(@rspress/core@2.0.0-rc.4(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(search-insights@2.17.3) + specifier: 2.0.0-rc.5 + version: 2.0.0-rc.5(@algolia/client-search@5.39.0)(@rspress/core@2.0.0-rc.5(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(search-insights@2.17.3) '@rspress/plugin-client-redirects': - specifier: 2.0.0-rc.4 - version: 2.0.0-rc.4(@rspress/core@2.0.0-rc.4(@types/react@19.2.7)) + specifier: 2.0.0-rc.5 + version: 2.0.0-rc.5(@rspress/core@2.0.0-rc.5(@types/react@19.2.8)) '@rspress/plugin-llms': - specifier: 2.0.0-rc.4 - version: 2.0.0-rc.4(@rspress/core@2.0.0-rc.4(@types/react@19.2.7)) + specifier: 2.0.0-rc.5 + version: 2.0.0-rc.5(@rspress/core@2.0.0-rc.5(@types/react@19.2.8)) '@rspress/plugin-rss': - specifier: 2.0.0-rc.4 - version: 2.0.0-rc.4(@rspress/core@2.0.0-rc.4(@types/react@19.2.7)) + specifier: 2.0.0-rc.5 + version: 2.0.0-rc.5(@rspress/core@2.0.0-rc.5(@types/react@19.2.8)) '@rspress/plugin-sitemap': - specifier: 2.0.0-rc.4 - version: 2.0.0-rc.4(@rspress/core@2.0.0-rc.4(@types/react@19.2.7)) + specifier: 2.0.0-rc.5 + version: 2.0.0-rc.5(@rspress/core@2.0.0-rc.5(@types/react@19.2.8)) '@shikijs/transformers': specifier: ^3.21.0 version: 3.21.0 '@types/node': - specifier: ^20.19.27 - version: 20.19.27 + specifier: ^20.19.29 + version: 20.19.29 '@types/react': - specifier: ^19.2.7 - version: 19.2.7 + specifier: ^19.2.8 + version: 19.2.8 '@types/semver': specifier: ^7.7.1 version: 7.7.1 @@ -1008,7 +1008,7 @@ importers: version: 1.1.0(@rsbuild/core@1.7.2) rspress-plugin-font-open-sans: specifier: 1.0.3 - version: 1.0.3(@rspress/core@2.0.0-rc.4(@types/react@19.2.7)) + version: 1.0.3(@rspress/core@2.0.0-rc.5(@types/react@19.2.8)) typescript: specifier: ^5.9.3 version: 5.9.3 @@ -1142,8 +1142,8 @@ packages: cpu: [arm64] os: [darwin] - '@ast-grep/napi-darwin-arm64@0.40.4': - resolution: {integrity: sha512-UIkpoEExRghZe5wN6QXGkDzI65zKVoaBQowAzmEd3MCGP8VlAK3FoxDMdy0OLgQVTyRUdBUwG384WpxiWilYEw==} + '@ast-grep/napi-darwin-arm64@0.40.5': + resolution: {integrity: sha512-2F072fGN0WTq7KI3okuEnkGJVEHLbi56Bw1H6NAMf7j2mJJeQWsRyGOMcyNnUXZDeNdvoMH0OB2a5wwUegY/nQ==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] @@ -1154,8 +1154,8 @@ packages: cpu: [x64] os: [darwin] - '@ast-grep/napi-darwin-x64@0.40.4': - resolution: {integrity: sha512-derMkDWiMFjRlcN0SEHXNPeZ67OGR5So6b4r/+ETvZMZavLQv+ER0vevltFS4ci8m402g7l/wVOdSE1oHcN2Iw==} + '@ast-grep/napi-darwin-x64@0.40.5': + resolution: {integrity: sha512-dJMidHZhhxuLBYNi6/FKI812jQ7wcFPSKkVPwviez2D+KvYagapUMAV/4dJ7FCORfguVk8Y0jpPAlYmWRT5nvA==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] @@ -1166,8 +1166,8 @@ packages: cpu: [arm64] os: [linux] - '@ast-grep/napi-linux-arm64-gnu@0.40.4': - resolution: {integrity: sha512-1CeDsK6WRMz169mTXLfXdn2GkQAsMkYbqGd7mHDa2VqutJwDYrqe6t4QiFAlr+LRT2bQuExpPh3AiC8BNd6UQQ==} + '@ast-grep/napi-linux-arm64-gnu@0.40.5': + resolution: {integrity: sha512-nBRCbyoS87uqkaw4Oyfe5VO+SRm2B+0g0T8ME69Qry9ShMf41a2bTdpcQx9e8scZPogq+CTwDHo3THyBV71l9w==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] @@ -1178,8 +1178,8 @@ packages: cpu: [arm64] os: [linux] - '@ast-grep/napi-linux-arm64-musl@0.40.4': - resolution: {integrity: sha512-VqjL9Xbq5NNXexY4rluaFtpuHHGbcNIwFXInbm8hdaZS3Rsr9tz+QCEhDNO4IJgPtcRUOpa7AIztZotwxrb/iw==} + '@ast-grep/napi-linux-arm64-musl@0.40.5': + resolution: {integrity: sha512-/qKsmds5FMoaEj6FdNzepbmLMtlFuBLdrAn9GIWCqOIcVcYvM1Nka8+mncfeXB/MFZKOrzQsQdPTWqrrQzXLrA==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] @@ -1190,8 +1190,8 @@ packages: cpu: [x64] os: [linux] - '@ast-grep/napi-linux-x64-gnu@0.40.4': - resolution: {integrity: sha512-6BrPYjP+Gr+mkI3z3Xh/UHkOedJ25qKGdhRwbYteeK/QX3rWeuuo/tUjow4nh/8ewhk04wHGw/G96OiF47ICjA==} + '@ast-grep/napi-linux-x64-gnu@0.40.5': + resolution: {integrity: sha512-DP4oDbq7f/1A2hRTFLhJfDFR6aI5mRWdEfKfHzRItmlKsR9WlcEl1qDJs/zX9R2EEtIDsSKRzuJNfJllY3/W8Q==} engines: {node: '>= 10'} cpu: [x64] os: [linux] @@ -1202,8 +1202,8 @@ packages: cpu: [x64] os: [linux] - '@ast-grep/napi-linux-x64-musl@0.40.4': - resolution: {integrity: sha512-4LGq6xYmOsgEycx4Cu9CdyNYa99O/C1bOsZi09T0C/NifKR+55v8og6nZrGCwsKEs4jWresdal4p7WXw3k8+0g==} + '@ast-grep/napi-linux-x64-musl@0.40.5': + resolution: {integrity: sha512-BRZUvVBPUNpWPo6Ns8chXVzxHPY+k9gpsubGTHy92Q26ecZULd/dTkWWdnvfhRqttsSQ9Pe/XQdi5+hDQ6RYcg==} engines: {node: '>= 10'} cpu: [x64] os: [linux] @@ -1214,8 +1214,8 @@ packages: cpu: [arm64] os: [win32] - '@ast-grep/napi-win32-arm64-msvc@0.40.4': - resolution: {integrity: sha512-QrI9m9wmFYTRnyTsYOX+9/D/B+h0eyFqZf2qh/U3kbRU/ZZJnxI75YjYVjtoa2QI4oEJlzYb0QhKAN8NKIDYRA==} + '@ast-grep/napi-win32-arm64-msvc@0.40.5': + resolution: {integrity: sha512-y95zSEwc7vhxmcrcH0GnK4ZHEBQrmrszRBNQovzaciF9GUqEcCACNLoBesn4V47IaOp4fYgD2/EhGRTIBFb2Ug==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] @@ -1226,8 +1226,8 @@ packages: cpu: [ia32] os: [win32] - '@ast-grep/napi-win32-ia32-msvc@0.40.4': - resolution: {integrity: sha512-JLhcgCUD7e74rZ39XLEfUOU26TQboJltzHir2oSpvjZPtq4aBHEJOynq7dGABZdMrzRUOPdbBdM+nFzPiU38iQ==} + '@ast-grep/napi-win32-ia32-msvc@0.40.5': + resolution: {integrity: sha512-K/u8De62iUnFCzVUs7FBdTZ2Jrgc5/DLHqjpup66KxZ7GIM9/HGME/O8aSoPkpcAeCD4TiTZ11C1i5p5H98hTg==} engines: {node: '>= 10'} cpu: [ia32] os: [win32] @@ -1238,8 +1238,8 @@ packages: cpu: [x64] os: [win32] - '@ast-grep/napi-win32-x64-msvc@0.40.4': - resolution: {integrity: sha512-DdsqVs/kg4Iun8GU8GoOw9L9WkT2pVLAZ+1hV9t+PsdI6SR3HGRIUIJSzKz2uejr8tY8evTZmdjBWyjUav8qbQ==} + '@ast-grep/napi-win32-x64-msvc@0.40.5': + resolution: {integrity: sha512-dqm5zg/o4Nh4VOQPEpMS23ot8HVd22gG0eg01t4CFcZeuzyuSgBlOL3N7xLbz3iH2sVkk7keuBwAzOIpTqziNQ==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -1248,28 +1248,36 @@ packages: resolution: {integrity: sha512-Hb4o6h1Pf6yRUAX07DR4JVY7dmQw+RVQMW5/m55GoiAT/VRoKCWBtIUPPOnqDVhbx1Cjfil9b6EDrgJsUAujEQ==} engines: {node: '>= 10'} - '@ast-grep/napi@0.40.4': - resolution: {integrity: sha512-unRhSrSn4X0tf7nCuj300rBrlrXqtGbKanFX75CNmn2NM+NyPrdvq1tdDk2F+XA8Z574MynpSeCESii3WBK+bw==} + '@ast-grep/napi@0.40.5': + resolution: {integrity: sha512-hJA62OeBKUQT68DD2gDyhOqJxZxycqg8wLxbqjgqSzYttCMSDL9tiAQ9abgekBYNHudbJosm9sWOEbmCDfpX2A==} engines: {node: '>= 10'} '@babel/code-frame@7.27.1': resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} engines: {node: '>=6.9.0'} + '@babel/code-frame@7.28.6': + resolution: {integrity: sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q==} + engines: {node: '>=6.9.0'} + '@babel/compat-data@7.28.4': resolution: {integrity: sha512-YsmSKC29MJwf0gF8Rjjrg5LQCmyh+j/nD8/eP7f+BeoQTKYqs9RoWbjGOdy0+1Ekr68RJZMUOPVQaQisnIo4Rw==} engines: {node: '>=6.9.0'} + '@babel/compat-data@7.28.6': + resolution: {integrity: sha512-2lfu57JtzctfIrcGMz992hyLlByuzgIk58+hhGCxjKZ3rWI82NnVLjXcaTqkI2NvlcvOskZaiZ5kjUALo3Lpxg==} + engines: {node: '>=6.9.0'} + '@babel/core@7.28.4': resolution: {integrity: sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==} engines: {node: '>=6.9.0'} - '@babel/core@7.28.5': - resolution: {integrity: sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==} + '@babel/core@7.28.6': + resolution: {integrity: sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==} engines: {node: '>=6.9.0'} - '@babel/generator@7.28.5': - resolution: {integrity: sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==} + '@babel/generator@7.28.6': + resolution: {integrity: sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw==} engines: {node: '>=6.9.0'} '@babel/helper-annotate-as-pure@7.27.3': @@ -1280,6 +1288,10 @@ packages: resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==} engines: {node: '>=6.9.0'} + '@babel/helper-compilation-targets@7.28.6': + resolution: {integrity: sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==} + engines: {node: '>=6.9.0'} + '@babel/helper-globals@7.28.0': resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} engines: {node: '>=6.9.0'} @@ -1288,12 +1300,22 @@ packages: resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==} engines: {node: '>=6.9.0'} + '@babel/helper-module-imports@7.28.6': + resolution: {integrity: sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==} + engines: {node: '>=6.9.0'} + '@babel/helper-module-transforms@7.28.3': resolution: {integrity: sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 + '@babel/helper-module-transforms@7.28.6': + resolution: {integrity: sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + '@babel/helper-plugin-utils@7.27.1': resolution: {integrity: sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==} engines: {node: '>=6.9.0'} @@ -1302,10 +1324,6 @@ packages: resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-identifier@7.27.1': - resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==} - engines: {node: '>=6.9.0'} - '@babel/helper-validator-identifier@7.28.5': resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} engines: {node: '>=6.9.0'} @@ -1318,8 +1336,12 @@ packages: resolution: {integrity: sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==} engines: {node: '>=6.9.0'} - '@babel/parser@7.28.5': - resolution: {integrity: sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==} + '@babel/helpers@7.28.6': + resolution: {integrity: sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.28.6': + resolution: {integrity: sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ==} engines: {node: '>=6.0.0'} hasBin: true @@ -1448,12 +1470,16 @@ packages: resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} engines: {node: '>=6.9.0'} - '@babel/traverse@7.28.5': - resolution: {integrity: sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==} + '@babel/template@7.28.6': + resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.28.6': + resolution: {integrity: sha512-fgWX62k02qtjqdSNTAGxmKYY/7FSL9WAS1o2Hu5+I5m9T0yxZzr4cnrfXQ/MX0rIifthCSs6FKTlzYbJcPtMNg==} engines: {node: '>=6.9.0'} - '@babel/types@7.28.5': - resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==} + '@babel/types@7.28.6': + resolution: {integrity: sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==} engines: {node: '>=6.9.0'} '@biomejs/biome@2.3.11': @@ -2436,39 +2462,21 @@ packages: '@microsoft/tsdoc@0.16.0': resolution: {integrity: sha512-xgAyonlVVS+q7Vc7qLW0UrJU7rSFcETRWsqdXZtjzRU8dF+6CkozTK4V4y1LwOX7j8r/vHphjDeMeGI4tNGeGA==} - '@module-federation/error-codes@0.21.6': - resolution: {integrity: sha512-MLJUCQ05KnoVl8xd6xs9a5g2/8U+eWmVxg7xiBMeR0+7OjdWUbHwcwgVFatRIwSZvFgKHfWEiI7wsU1q1XbTRQ==} - '@module-federation/error-codes@0.22.0': resolution: {integrity: sha512-xF9SjnEy7vTdx+xekjPCV5cIHOGCkdn3pIxo9vU7gEZMIw0SvAEdsy6Uh17xaCpm8V0FWvR0SZoK9Ik6jGOaug==} - '@module-federation/runtime-core@0.21.6': - resolution: {integrity: sha512-5Hd1Y5qp5lU/aTiK66lidMlM/4ji2gr3EXAtJdreJzkY+bKcI5+21GRcliZ4RAkICmvdxQU5PHPL71XmNc7Lsw==} - '@module-federation/runtime-core@0.22.0': resolution: {integrity: sha512-GR1TcD6/s7zqItfhC87zAp30PqzvceoeDGYTgF3Vx2TXvsfDrhP6Qw9T4vudDQL3uJRne6t7CzdT29YyVxlgIA==} - '@module-federation/runtime-tools@0.21.6': - resolution: {integrity: sha512-fnP+ZOZTFeBGiTAnxve+axGmiYn2D60h86nUISXjXClK3LUY1krUfPgf6MaD4YDJ4i51OGXZWPekeMe16pkd8Q==} - '@module-federation/runtime-tools@0.22.0': resolution: {integrity: sha512-4ScUJ/aUfEernb+4PbLdhM/c60VHl698Gn1gY21m9vyC1Ucn69fPCA1y2EwcCB7IItseRMoNhdcWQnzt/OPCNA==} - '@module-federation/runtime@0.21.6': - resolution: {integrity: sha512-+caXwaQqwTNh+CQqyb4mZmXq7iEemRDrTZQGD+zyeH454JAYnJ3s/3oDFizdH6245pk+NiqDyOOkHzzFQorKhQ==} - '@module-federation/runtime@0.22.0': resolution: {integrity: sha512-38g5iPju2tPC3KHMPxRKmy4k4onNp6ypFPS1eKGsNLUkXgHsPMBFqAjDw96iEcjri91BrahG4XcdyKi97xZzlA==} - '@module-federation/sdk@0.21.6': - resolution: {integrity: sha512-x6hARETb8iqHVhEsQBysuWpznNZViUh84qV2yE7AD+g7uIzHKiYdoWqj10posbo5XKf/147qgWDzKZoKoEP2dw==} - '@module-federation/sdk@0.22.0': resolution: {integrity: sha512-x4aFNBKn2KVQRuNVC5A7SnrSCSqyfIWmm1DvubjbO9iKFe7ith5niw8dqSFBekYBg2Fwy+eMg4sEFNVvCAdo6g==} - '@module-federation/webpack-bundler-runtime@0.21.6': - resolution: {integrity: sha512-7zIp3LrcWbhGuFDTUMLJ2FJvcwjlddqhWGxi/MW3ur1a+HaO8v5tF2nl+vElKmbG1DFLU/52l3PElVcWf/YcsQ==} - '@module-federation/webpack-bundler-runtime@0.22.0': resolution: {integrity: sha512-aM8gCqXu+/4wBmJtVeMeeMN5guw3chf+2i6HajKtQv7SJfxV/f4IyNQJUeUQu9HfiAZHjqtMV5Lvq/Lvh8LdyA==} @@ -3198,11 +3206,6 @@ packages: cpu: [x64] os: [win32] - '@rsbuild/core@1.6.15': - resolution: {integrity: sha512-LvoOF53PL6zXgdzEhgnnP51S4FseDFH1bHrobK4EK6zZX/tN8qgf5tdlmN7h4OkMv/Qs1oUfvj0QcLWSstnnvA==} - engines: {node: '>=18.12.0'} - hasBin: true - '@rsbuild/core@1.7.1': resolution: {integrity: sha512-ULIE/Qh+Ne80Pm/aUPbRHUvwvIzpap07jYNFB47azI8w5Q3sDEC4Gn574jsluT/42iNDsZTFADRBog9FEvtN9Q==} engines: {node: '>=18.12.0'} @@ -3231,8 +3234,8 @@ packages: peerDependencies: '@rsbuild/core': 1.x - '@rslib/core@0.19.1': - resolution: {integrity: sha512-Fz+uknjf9BRE6tNax7zcZOZ8FX3FLT5kKcR10vHdo6IgCaMZpJxQmM62NNfv21kdy5u1PdIRgKFVpqP2QTarfg==} + '@rslib/core@0.19.2': + resolution: {integrity: sha512-eoRR1tQqkEiq3ijBT170KpxnBM7nf3/sanAUoJhyCeyLKKkGpQW6nr1cKHfZmkEizqSvLyjvLFA7fdIfK7pCMw==} engines: {node: '>=18.12.0'} hasBin: true peerDependencies: @@ -3278,11 +3281,6 @@ packages: cpu: [x64] os: [win32] - '@rspack/binding-darwin-arm64@1.6.8': - resolution: {integrity: sha512-e8CTQtzaeGnf+BIzR7wRMUwKfIg0jd/sxMRc1Vd0bCMHBhSN9EsGoMuJJaKeRrSmy2nwMCNWHIG+TvT1CEKg+A==} - cpu: [arm64] - os: [darwin] - '@rspack/binding-darwin-arm64@1.7.0': resolution: {integrity: sha512-HMYrhvVh3sMRBXl6cSI2JqsvlHJKQ42qX+Sw4qbj7LeZBN6Gv4GjfL3cXRLUTdO37FOC0uLEUYgxVXetx/Y4sA==} cpu: [arm64] @@ -3293,11 +3291,6 @@ packages: cpu: [arm64] os: [darwin] - '@rspack/binding-darwin-x64@1.6.8': - resolution: {integrity: sha512-ku1XpTEPt6Za11zhpFWhfwrTQogcgi9RJrOUVC4FESiPO9aKyd4hJ+JiPgLY0MZOqsptK6vEAgOip+uDVXrCpg==} - cpu: [x64] - os: [darwin] - '@rspack/binding-darwin-x64@1.7.0': resolution: {integrity: sha512-R/SoR04ySmHPqoIBGC+SjP9zRGjL1fS908mdwBvQ1RfFinKu7a/o/5rxH/vxUUsVQrHCyX+o7YXpfWq9xpvyQA==} cpu: [x64] @@ -3308,11 +3301,6 @@ packages: cpu: [x64] os: [darwin] - '@rspack/binding-linux-arm64-gnu@1.6.8': - resolution: {integrity: sha512-fvZX6xZPvBT8qipSpvkKMX5M7yd2BSpZNCZXcefw6gA3uC7LI3gu+er0LrDXY1PtPzVuHTyDx+abwWpagV3PiQ==} - cpu: [arm64] - os: [linux] - '@rspack/binding-linux-arm64-gnu@1.7.0': resolution: {integrity: sha512-jDCcso++qshu58+Iuo6oiL0XKuX04lDugL0qwrWHW8SS/EjZ2rc1J3yQx+XDW0PCQsfI2c9ji0IOW56PzW1hXQ==} cpu: [arm64] @@ -3323,11 +3311,6 @@ packages: cpu: [arm64] os: [linux] - '@rspack/binding-linux-arm64-musl@1.6.8': - resolution: {integrity: sha512-++XMKcMNrt59HcFBLnRaJcn70k3X0GwkAegZBVpel8xYIAgvoXT5+L8P1ExId/yTFxqedaz8DbcxQnNmMozviw==} - cpu: [arm64] - os: [linux] - '@rspack/binding-linux-arm64-musl@1.7.0': resolution: {integrity: sha512-0W49s0SQQhr3hZ8Zd7Auyf2pv4OTBr6wQhgWUQ6XeeMEjB16KpAVypSK5Jpn1ON0v9jAPLdod+a255rz8/f3kg==} cpu: [arm64] @@ -3338,11 +3321,6 @@ packages: cpu: [arm64] os: [linux] - '@rspack/binding-linux-x64-gnu@1.6.8': - resolution: {integrity: sha512-tv3BWkTE1TndfX+DsE1rSTg8fBevCxujNZ3MlfZ22Wfy9x1FMXTJlWG8VIOXmaaJ1wUHzv8S7cE2YUUJ2LuiCg==} - cpu: [x64] - os: [linux] - '@rspack/binding-linux-x64-gnu@1.7.0': resolution: {integrity: sha512-oFjzjTD1MmG0ucAaP0Wyg9eobrsnFwZjEHa7LwyzWDRBeC3GWAF9T04Bqd6Ba6DgASGzU0BjEJcUpjvtXxO95Q==} cpu: [x64] @@ -3353,11 +3331,6 @@ packages: cpu: [x64] os: [linux] - '@rspack/binding-linux-x64-musl@1.6.8': - resolution: {integrity: sha512-DCGgZ5/in1O3FjHWqXnDsncRy+48cMhfuUAAUyl0yDj1NpsZu9pP+xfGLvGcQTiYrVl7IH9Aojf1eShP/77WGA==} - cpu: [x64] - os: [linux] - '@rspack/binding-linux-x64-musl@1.7.0': resolution: {integrity: sha512-MNGslPLOsurdwOcoo6r0u8mLpw1ADar3hkx67WzwwMqYnem/Ky0aANJC2JvQHPC22mu01gCOukHYyEaUFTxcuw==} cpu: [x64] @@ -3368,10 +3341,6 @@ packages: cpu: [x64] os: [linux] - '@rspack/binding-wasm32-wasi@1.6.8': - resolution: {integrity: sha512-VUwdhl/lI4m6o1OGCZ9JwtMjTV/yLY5VZTQdEPKb40JMTlmZ5MBlr5xk7ByaXXYHr6I+qnqEm73iMKQvg6iknw==} - cpu: [wasm32] - '@rspack/binding-wasm32-wasi@1.7.0': resolution: {integrity: sha512-eaZzkGpxzVESmaX/UALMiQO+eNppe/i1VWQksGRfdoUu0rILqr/YDjsWFTcpbI9Dt3fg2kshHawBHxfwtxHcZQ==} cpu: [wasm32] @@ -3380,11 +3349,6 @@ packages: resolution: {integrity: sha512-2r9M5iVchmsFkp3sz7A5YnMm2TfpkB71LK3AoaRWKMfvf5oFky0GSGISYd2TCBASO+X2Qskaq+B24Szo8zH5FA==} cpu: [wasm32] - '@rspack/binding-win32-arm64-msvc@1.6.8': - resolution: {integrity: sha512-23YX7zlOZlub+nPGDBUzktb4D5D6ETUAluKjXEeHIZ9m7fSlEYBnGL66YE+3t1DHXGd0OqsdwlvrNGcyo6EXDQ==} - cpu: [arm64] - os: [win32] - '@rspack/binding-win32-arm64-msvc@1.7.0': resolution: {integrity: sha512-XFg4l7sOhupnpG0soOfzYLeF2cgpSJMenmjmdzd9y06CotTyVId0hNoS7y+A7hEP8XGf3YPbdiUL5UDp6+DRBA==} cpu: [arm64] @@ -3395,11 +3359,6 @@ packages: cpu: [arm64] os: [win32] - '@rspack/binding-win32-ia32-msvc@1.6.8': - resolution: {integrity: sha512-cFgRE3APxrY4AEdooVk2LtipwNNT/9mrnjdC5lVbsIsz+SxvGbZR231bxDJEqP15+RJOaD07FO1sIjINFqXMEg==} - cpu: [ia32] - os: [win32] - '@rspack/binding-win32-ia32-msvc@1.7.0': resolution: {integrity: sha512-eWt2XV6la/c0IlU/18RlhQsqwHGShSypwA3kt4s/dpfOK0YB1h4f0fYeUZuvj2X0MIoJQGhMofMrgA35/IcAcw==} cpu: [ia32] @@ -3410,11 +3369,6 @@ packages: cpu: [ia32] os: [win32] - '@rspack/binding-win32-x64-msvc@1.6.8': - resolution: {integrity: sha512-cIuhVsZYd3o3Neo1JSAhJYw6BDvlxaBoqvgwRkG1rs0ExFmEmgYyG7ip9pFKnKNWph/tmW3rDYypmEfjs1is7g==} - cpu: [x64] - os: [win32] - '@rspack/binding-win32-x64-msvc@1.7.0': resolution: {integrity: sha512-LOL5G8rfbAwlmusx+t98r9QzuGRz+L9Bg+8s5s6K/Qe64iemcNIuxGr5QLVq1jLa0SGNTeog4N21pAzlkWh4jw==} cpu: [x64] @@ -3425,24 +3379,12 @@ packages: cpu: [x64] os: [win32] - '@rspack/binding@1.6.8': - resolution: {integrity: sha512-lUeL4mbwGo+nqRKqFDCm9vH2jv9FNMVt1X8jqayWRcOCPlj/2UVMEFgqjR7Pp2vlvnTKq//31KbDBJmDZq31RQ==} - '@rspack/binding@1.7.0': resolution: {integrity: sha512-xO+pZKG2dvU9CuRTTi+DcCc4p+CZhBJlvuYikBja/0a62cTntQV2PWV+/xU1a6Vbo89yNz158LR05nvjtKVwTw==} '@rspack/binding@1.7.1': resolution: {integrity: sha512-qVTV1/UWpMSZktvK5A8+HolgR1Qf0nYR3Gg4Vax5x3/BcHDpwGZ0fbdFRUirGVWH/XwxZ81zoI6F2SZq7xbX+w==} - '@rspack/core@1.6.8': - resolution: {integrity: sha512-FolcIAH5FW4J2FET+qwjd1kNeFbCkd0VLuIHO0thyolEjaPSxw5qxG67DA7BZGm6PVcoiSgPLks1DL6eZ8c+fA==} - engines: {node: '>=18.12.0'} - peerDependencies: - '@swc/helpers': '>=0.5.1' - peerDependenciesMeta: - '@swc/helpers': - optional: true - '@rspack/core@1.7.0': resolution: {integrity: sha512-uDxPQsPh/+2DnOISuKnUiXZ9M0y2G1BOsI0IesxPJGp42ME2QW7axbJfUqD3bwp4bi3RN2zqh56NgxU/XETQvA==} engines: {node: '>=18.12.0'} @@ -3485,8 +3427,8 @@ packages: webpack-hot-middleware: optional: true - '@rspress/core@2.0.0-rc.4': - resolution: {integrity: sha512-EHJjbc8yA/La6sJN3bjZus24KhSCdh5lEIVtjt7EBEnLteDN+wULzO1sFKj8agH3BXYE0XOuz2W1HbTTGfcGJQ==} + '@rspress/core@2.0.0-rc.5': + resolution: {integrity: sha512-T5WF7CxAAlt0HAeugbaQAk0BKm3NGrfaxYyrij7nLHRSBZPkY4sO8p3IHfLfmxKCvFogpskmd5F+hBXhow7rxg==} engines: {node: '>=20.9.0'} hasBin: true @@ -3542,45 +3484,41 @@ packages: resolution: {integrity: sha512-NpNhTKBIlV3O6ADhoZkgHvBFvXMW2TYlIWmIT1ysJESUBqDpaN9H3Teve5fugjU2pQ2ORBZO6SQGKliMw/8m/Q==} engines: {node: '>= 10'} - '@rspress/plugin-algolia@2.0.0-rc.4': - resolution: {integrity: sha512-rW/XRs/W7llAwdYusBqMLt8jo39+oYtdtMpyrRq/d3h0WE/xXMSSnAp24BrcjE6forWke4pxra1I20wUeGcRGw==} + '@rspress/plugin-algolia@2.0.0-rc.5': + resolution: {integrity: sha512-+SFsyqqN6ykeFPXng0ZcaBEERscvXnlihpmX87fwbwR56NFlHl+5mPaTFbsCQInlEViFXY9Fbcl6OqblF2ATRg==} engines: {node: '>=20.9.0'} peerDependencies: - '@rspress/core': ^2.0.0-rc.4 + '@rspress/core': ^2.0.0-rc.5 - '@rspress/plugin-client-redirects@2.0.0-rc.4': - resolution: {integrity: sha512-hBoXexZUk9HB2NR+QWH9E2oDZe887tq5wsqG0crZlLL1ehyShsVXhofUH9ROciScmWYfJvcbTfdvTnIWTrrk8g==} + '@rspress/plugin-client-redirects@2.0.0-rc.5': + resolution: {integrity: sha512-RRbZ2Hw1l5JpkFUDcghaBP8V6WP3p0Q2ka0A/NaB8Jx/5oDIl8SVO4e1Pqyyi7SYIq5Byq9wO2TBd/PJ5RKm9w==} engines: {node: '>=20.9.0'} peerDependencies: - '@rspress/core': ^2.0.0-rc.4 + '@rspress/core': ^2.0.0-rc.5 - '@rspress/plugin-llms@2.0.0-rc.4': - resolution: {integrity: sha512-PSG8JOO2EOqCeViif48puAeiP2pBhe//v0sC8dm9wGmQsrq8xbx2rH1aiQElZIwcoximqukzHavrU6O3qPW2NA==} + '@rspress/plugin-llms@2.0.0-rc.5': + resolution: {integrity: sha512-7FevOhOsPBMAln/vgxY0gE0oQIIUdATE91d1zof5LgUuocV26od362KTlvAzOK0VsFKTwuJGEOgx2uDU6LzejA==} engines: {node: '>=20.9.0'} peerDependencies: - '@rspress/core': ^2.0.0-rc.4 + '@rspress/core': ^2.0.0-rc.5 - '@rspress/plugin-rss@2.0.0-rc.4': - resolution: {integrity: sha512-eF6926NnQGV2SPhbz6RruiGnBgcjsDW+ow5sVePWdltHUQdo1wQCnLUnJdaCjek5Jx+wtJViNMT2dhXu/NUVYQ==} + '@rspress/plugin-rss@2.0.0-rc.5': + resolution: {integrity: sha512-TGIC/36+yyJofF2nkWUs3cNmjPASl6Wk+breT1RxBbXGV5NkDVipqxgGoB4JrABKZMi2wHP3CPFzqagWpjsPdw==} engines: {node: '>=20.9.0'} peerDependencies: - '@rspress/core': ^2.0.0-rc.4 + '@rspress/core': ^2.0.0-rc.5 - '@rspress/plugin-sitemap@2.0.0-rc.4': - resolution: {integrity: sha512-sr900krxs9ZVfbV+b/ig7t8mAPaMOonWz2Qj9zXg4TgEgnh+LnNtHQpHYeFbiTF5WAozVxdu5lJ1E36oh231pQ==} + '@rspress/plugin-sitemap@2.0.0-rc.5': + resolution: {integrity: sha512-jUPMiwoYMTozv3swMlo/n4vws9uoHpGJNz/T+C/EkVZpgFxO4h8qJDQrFczdxPKWnhKNnBPFoBHBfKTutb78Eg==} engines: {node: '>=20.9.0'} peerDependencies: - '@rspress/core': ^2.0.0-rc.4 - - '@rspress/runtime@2.0.0-rc.4': - resolution: {integrity: sha512-BcNs6zpIXcWfhXGCDS525HDwSgLXO+S+q2Ty6sQPmyYJzOg+V9tHIlulKTOfuBCyEhTZeTAJofP4+rG4EZBUgw==} - engines: {node: '>=20.9.0'} + '@rspress/core': ^2.0.0-rc.5 - '@rspress/shared@2.0.0-rc.4': - resolution: {integrity: sha512-46jTwxV8SRLMbe3euCEMWQudmdYE2Tf+EN/5l6EP10i6QICOXMIzUFFWfr0LOTr4aZCSTSJu7Tp6Xxml6JbheA==} + '@rspress/shared@2.0.0-rc.5': + resolution: {integrity: sha512-bPM+3hkh923HEq7UKbeY4CCokeh1ilXGvk+Kxm1LwT51CJH5Jt3aKhzzWLr//+OuaFcSUaO0sWiUQbJU7JaqWA==} - '@rstack-dev/doc-ui@1.12.2': - resolution: {integrity: sha512-4C+tfhODxCp81ohCik9baOdbhYGNFqdwcwQMAESncF0YX3EawdNCORI1E26DqkY/F3ggfKG4qOlEAu+oOxrPxg==} + '@rstack-dev/doc-ui@1.12.3': + resolution: {integrity: sha512-5W70pjRxxwyNT3R4kTYDE8cPaMjsJKXMeZQn7+Q54+RCJ1ahN4pADnpaY7WvSEBWkjXdI4IR4GGvBs7nSU/8MA==} '@rstest/core@0.7.9': resolution: {integrity: sha512-RHNPS1MDUxtf+1Z0YZi+vIQ13SdvCbcbpzDA7XHcPziTRy2mAPg8nfcms+XzbIp95KXH75ucAhgAKNFO0QgARA==} @@ -3912,8 +3850,8 @@ packages: '@types/node-forge@1.3.14': resolution: {integrity: sha512-mhVF2BnD4BO+jtOp7z1CdzaK4mbuK0LLQYAvdOLqHTavxFNq4zA1EmYkpnFjP8HOUzedfQkRnp0E2ulSAYSzAw==} - '@types/node@20.19.27': - resolution: {integrity: sha512-N2clP5pJhB2YnZJ3PIHFk5RkygRX5WO/5f0WC08tp0wd+sv0rsJk3MqWn3CbNmT2J505a5336jaQj4ph1AdMug==} + '@types/node@20.19.29': + resolution: {integrity: sha512-YrT9ArrGaHForBaCNwFjoqJWmn8G1Pr7+BH/vwyLHciA9qT/wSiuOhxGCT50JA5xLvFBd6PIiGkE3afxcPE1nw==} '@types/qs@6.14.0': resolution: {integrity: sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==} @@ -3926,8 +3864,8 @@ packages: peerDependencies: '@types/react': ^19.2.0 - '@types/react@19.2.7': - resolution: {integrity: sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==} + '@types/react@19.2.8': + resolution: {integrity: sha512-3MbSL37jEchWZz2p2mjntRZtPt837ij10ApxKfgmXCTuHWagYg7iA5bqPw6C8BMPfwidlvfPI/fxOc42HLhcyg==} '@types/retry@0.12.2': resolution: {integrity: sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==} @@ -3980,8 +3918,8 @@ packages: '@ungap/structured-clone@1.3.0': resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} - '@unhead/react@2.0.19': - resolution: {integrity: sha512-pW00tkOneGGTEJp5UeVkVWmti4VecLj0rIje5AqcBs0AoglSxc18LGGKi9Exd098++GzVouhkGo1Ch02YnZS7g==} + '@unhead/react@2.1.2': + resolution: {integrity: sha512-VNKa0JJZq5Jp28VuiOMfjAA7CTLHI0SdW/Hs1ZPq2PsNV/cgxGv8quFBGXWx4gfoHB52pejO929RKjIpYX5+iQ==} peerDependencies: react: '>=18.3.1' @@ -5832,8 +5770,8 @@ packages: hmac-drbg@1.0.1: resolution: {integrity: sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==} - hookable@5.5.3: - resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==} + hookable@6.0.1: + resolution: {integrity: sha512-uKGyY8BuzN/a5gvzvA+3FVWo0+wUjgtfSdnmjtrOVwQCZPHpHDH2WRO3VZSOeluYrHoDCiXFffZXs8Dj1ULWtw==} hpack.js@2.1.6: resolution: {integrity: sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==} @@ -5948,8 +5886,8 @@ packages: resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} engines: {node: '>=0.10.0'} - iconv-lite@0.7.1: - resolution: {integrity: sha512-2Tth85cXwGFHfvRgZWszZSvdo+0Xsqmw8k8ZwxScfcBneNUraK+dxRxRm24nszx80Y0TVio8kKLt5sLE7ZCLlw==} + iconv-lite@0.7.2: + resolution: {integrity: sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==} engines: {node: '>=0.10.0'} icss-utils@5.1.0: @@ -6465,8 +6403,8 @@ packages: markdown-table@3.0.4: resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==} - markdown-to-jsx@9.5.0: - resolution: {integrity: sha512-6PhWz9md8btrE52LDM4KHSzXf2HKCG+2oGNVw/eQhMP6h51dfZVHb9mt1zWYvQ7wM+xOK8WWaijzEhjB0qIpUg==} + markdown-to-jsx@9.5.7: + resolution: {integrity: sha512-0RO+9IgcURudRI6tmsKFt0S9fCHeUMFzfWmJ84XOKOQ+CEb8pARtWHAxpCPmlbDIs2HAlOXjJKJz4oOwAZBGRg==} engines: {node: '>= 18'} peerDependencies: react: '>= 16.0.0' @@ -7553,8 +7491,8 @@ packages: rrweb-cssom@0.8.0: resolution: {integrity: sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==} - rsbuild-plugin-dts@0.19.1: - resolution: {integrity: sha512-LaK1RAvHPrb/ulfwvZckeui5qkQSKxf1RD7rzBTgK2UY8fMTQgsxsvun/XzfzAOKqdagzIohhnmNd5+j2Niqww==} + rsbuild-plugin-dts@0.19.2: + resolution: {integrity: sha512-neuTRt+H/isd2FDYMigF5TEoLUoR/hF0RKdVv1U7nDz0CfLRUfL+NnxePv9nS7dU2VvM3CYcLH7tZs43ol7g4Q==} engines: {node: '>=18.12.0'} peerDependencies: '@microsoft/api-extractor': ^7 @@ -8335,8 +8273,8 @@ packages: resolution: {integrity: sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==} engines: {node: '>=14.0'} - unhead@2.0.19: - resolution: {integrity: sha512-gEEjkV11Aj+rBnY6wnRfsFtF2RxKOLaPN4i+Gx3UhBxnszvV6ApSNZbGk7WKyy/lErQ6ekPN63qdFL7sa1leow==} + unhead@2.1.2: + resolution: {integrity: sha512-vSihrxyb+zsEUfEbraZBCjdE0p/WSoc2NGDrpwwSNAwuPxhYK1nH3eegf02IENLpn1sUhL8IoO84JWmRQ6tILA==} unicorn-magic@0.1.0: resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==} @@ -8993,55 +8931,55 @@ snapshots: '@ast-grep/napi-darwin-arm64@0.37.0': optional: true - '@ast-grep/napi-darwin-arm64@0.40.4': + '@ast-grep/napi-darwin-arm64@0.40.5': optional: true '@ast-grep/napi-darwin-x64@0.37.0': optional: true - '@ast-grep/napi-darwin-x64@0.40.4': + '@ast-grep/napi-darwin-x64@0.40.5': optional: true '@ast-grep/napi-linux-arm64-gnu@0.37.0': optional: true - '@ast-grep/napi-linux-arm64-gnu@0.40.4': + '@ast-grep/napi-linux-arm64-gnu@0.40.5': optional: true '@ast-grep/napi-linux-arm64-musl@0.37.0': optional: true - '@ast-grep/napi-linux-arm64-musl@0.40.4': + '@ast-grep/napi-linux-arm64-musl@0.40.5': optional: true '@ast-grep/napi-linux-x64-gnu@0.37.0': optional: true - '@ast-grep/napi-linux-x64-gnu@0.40.4': + '@ast-grep/napi-linux-x64-gnu@0.40.5': optional: true '@ast-grep/napi-linux-x64-musl@0.37.0': optional: true - '@ast-grep/napi-linux-x64-musl@0.40.4': + '@ast-grep/napi-linux-x64-musl@0.40.5': optional: true '@ast-grep/napi-win32-arm64-msvc@0.37.0': optional: true - '@ast-grep/napi-win32-arm64-msvc@0.40.4': + '@ast-grep/napi-win32-arm64-msvc@0.40.5': optional: true '@ast-grep/napi-win32-ia32-msvc@0.37.0': optional: true - '@ast-grep/napi-win32-ia32-msvc@0.40.4': + '@ast-grep/napi-win32-ia32-msvc@0.40.5': optional: true '@ast-grep/napi-win32-x64-msvc@0.37.0': optional: true - '@ast-grep/napi-win32-x64-msvc@0.40.4': + '@ast-grep/napi-win32-x64-msvc@0.40.5': optional: true '@ast-grep/napi@0.37.0': @@ -9056,37 +8994,45 @@ snapshots: '@ast-grep/napi-win32-ia32-msvc': 0.37.0 '@ast-grep/napi-win32-x64-msvc': 0.37.0 - '@ast-grep/napi@0.40.4': + '@ast-grep/napi@0.40.5': optionalDependencies: - '@ast-grep/napi-darwin-arm64': 0.40.4 - '@ast-grep/napi-darwin-x64': 0.40.4 - '@ast-grep/napi-linux-arm64-gnu': 0.40.4 - '@ast-grep/napi-linux-arm64-musl': 0.40.4 - '@ast-grep/napi-linux-x64-gnu': 0.40.4 - '@ast-grep/napi-linux-x64-musl': 0.40.4 - '@ast-grep/napi-win32-arm64-msvc': 0.40.4 - '@ast-grep/napi-win32-ia32-msvc': 0.40.4 - '@ast-grep/napi-win32-x64-msvc': 0.40.4 + '@ast-grep/napi-darwin-arm64': 0.40.5 + '@ast-grep/napi-darwin-x64': 0.40.5 + '@ast-grep/napi-linux-arm64-gnu': 0.40.5 + '@ast-grep/napi-linux-arm64-musl': 0.40.5 + '@ast-grep/napi-linux-x64-gnu': 0.40.5 + '@ast-grep/napi-linux-x64-musl': 0.40.5 + '@ast-grep/napi-win32-arm64-msvc': 0.40.5 + '@ast-grep/napi-win32-ia32-msvc': 0.40.5 + '@ast-grep/napi-win32-x64-msvc': 0.40.5 '@babel/code-frame@7.27.1': dependencies: - '@babel/helper-validator-identifier': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/code-frame@7.28.6': + dependencies: + '@babel/helper-validator-identifier': 7.28.5 js-tokens: 4.0.0 picocolors: 1.1.1 '@babel/compat-data@7.28.4': {} + '@babel/compat-data@7.28.6': {} + '@babel/core@7.28.4': dependencies: '@babel/code-frame': 7.27.1 - '@babel/generator': 7.28.5 + '@babel/generator': 7.28.6 '@babel/helper-compilation-targets': 7.27.2 '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.4) '@babel/helpers': 7.28.4 - '@babel/parser': 7.28.5 + '@babel/parser': 7.28.6 '@babel/template': 7.27.2 - '@babel/traverse': 7.28.5 - '@babel/types': 7.28.5 + '@babel/traverse': 7.28.6 + '@babel/types': 7.28.6 '@jridgewell/remapping': 2.3.5 convert-source-map: 2.0.0 debug: 4.4.3 @@ -9096,17 +9042,17 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/core@7.28.5': - dependencies: - '@babel/code-frame': 7.27.1 - '@babel/generator': 7.28.5 - '@babel/helper-compilation-targets': 7.27.2 - '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.5) - '@babel/helpers': 7.28.4 - '@babel/parser': 7.28.5 - '@babel/template': 7.27.2 - '@babel/traverse': 7.28.5 - '@babel/types': 7.28.5 + '@babel/core@7.28.6': + dependencies: + '@babel/code-frame': 7.28.6 + '@babel/generator': 7.28.6 + '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-module-transforms': 7.28.6(@babel/core@7.28.6) + '@babel/helpers': 7.28.6 + '@babel/parser': 7.28.6 + '@babel/template': 7.28.6 + '@babel/traverse': 7.28.6 + '@babel/types': 7.28.6 '@jridgewell/remapping': 2.3.5 convert-source-map: 2.0.0 debug: 4.4.3 @@ -9116,17 +9062,17 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/generator@7.28.5': + '@babel/generator@7.28.6': dependencies: - '@babel/parser': 7.28.5 - '@babel/types': 7.28.5 + '@babel/parser': 7.28.6 + '@babel/types': 7.28.6 '@jridgewell/gen-mapping': 0.3.13 '@jridgewell/trace-mapping': 0.3.31 jsesc: 3.1.0 '@babel/helper-annotate-as-pure@7.27.3': dependencies: - '@babel/types': 7.28.5 + '@babel/types': 7.28.6 '@babel/helper-compilation-targets@7.27.2': dependencies: @@ -9136,12 +9082,27 @@ snapshots: lru-cache: 5.1.1 semver: 6.3.1 + '@babel/helper-compilation-targets@7.28.6': + dependencies: + '@babel/compat-data': 7.28.6 + '@babel/helper-validator-option': 7.27.1 + browserslist: 4.26.3 + lru-cache: 5.1.1 + semver: 6.3.1 + '@babel/helper-globals@7.28.0': {} '@babel/helper-module-imports@7.27.1': dependencies: - '@babel/traverse': 7.28.5 - '@babel/types': 7.28.5 + '@babel/traverse': 7.28.6 + '@babel/types': 7.28.6 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-imports@7.28.6': + dependencies: + '@babel/traverse': 7.28.6 + '@babel/types': 7.28.6 transitivePeerDependencies: - supports-color @@ -9149,17 +9110,17 @@ snapshots: dependencies: '@babel/core': 7.28.4 '@babel/helper-module-imports': 7.27.1 - '@babel/helper-validator-identifier': 7.27.1 - '@babel/traverse': 7.28.5 + '@babel/helper-validator-identifier': 7.28.5 + '@babel/traverse': 7.28.6 transitivePeerDependencies: - supports-color - '@babel/helper-module-transforms@7.28.3(@babel/core@7.28.5)': + '@babel/helper-module-transforms@7.28.6(@babel/core@7.28.6)': dependencies: - '@babel/core': 7.28.5 - '@babel/helper-module-imports': 7.27.1 - '@babel/helper-validator-identifier': 7.27.1 - '@babel/traverse': 7.28.5 + '@babel/core': 7.28.6 + '@babel/helper-module-imports': 7.28.6 + '@babel/helper-validator-identifier': 7.28.5 + '@babel/traverse': 7.28.6 transitivePeerDependencies: - supports-color @@ -9167,8 +9128,6 @@ snapshots: '@babel/helper-string-parser@7.27.1': {} - '@babel/helper-validator-identifier@7.27.1': {} - '@babel/helper-validator-identifier@7.28.5': {} '@babel/helper-validator-option@7.27.1': {} @@ -9176,11 +9135,16 @@ snapshots: '@babel/helpers@7.28.4': dependencies: '@babel/template': 7.27.2 - '@babel/types': 7.28.5 + '@babel/types': 7.28.6 - '@babel/parser@7.28.5': + '@babel/helpers@7.28.6': dependencies: - '@babel/types': 7.28.5 + '@babel/template': 7.28.6 + '@babel/types': 7.28.6 + + '@babel/parser@7.28.6': + dependencies: + '@babel/types': 7.28.6 '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.28.4)': dependencies: @@ -9222,9 +9186,9 @@ snapshots: '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.28.5)': + '@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.28.6)': dependencies: - '@babel/core': 7.28.5 + '@babel/core': 7.28.6 '@babel/helper-plugin-utils': 7.27.1 '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.28.4)': @@ -9272,66 +9236,72 @@ snapshots: '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-react-display-name@7.28.0(@babel/core@7.28.5)': + '@babel/plugin-transform-react-display-name@7.28.0(@babel/core@7.28.6)': dependencies: - '@babel/core': 7.28.5 + '@babel/core': 7.28.6 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-react-jsx-development@7.27.1(@babel/core@7.28.5)': + '@babel/plugin-transform-react-jsx-development@7.27.1(@babel/core@7.28.6)': dependencies: - '@babel/core': 7.28.5 - '@babel/plugin-transform-react-jsx': 7.27.1(@babel/core@7.28.5) + '@babel/core': 7.28.6 + '@babel/plugin-transform-react-jsx': 7.27.1(@babel/core@7.28.6) transitivePeerDependencies: - supports-color - '@babel/plugin-transform-react-jsx@7.27.1(@babel/core@7.28.5)': + '@babel/plugin-transform-react-jsx@7.27.1(@babel/core@7.28.6)': dependencies: - '@babel/core': 7.28.5 + '@babel/core': 7.28.6 '@babel/helper-annotate-as-pure': 7.27.3 '@babel/helper-module-imports': 7.27.1 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.5) - '@babel/types': 7.28.5 + '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.6) + '@babel/types': 7.28.6 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-react-pure-annotations@7.27.1(@babel/core@7.28.5)': + '@babel/plugin-transform-react-pure-annotations@7.27.1(@babel/core@7.28.6)': dependencies: - '@babel/core': 7.28.5 + '@babel/core': 7.28.6 '@babel/helper-annotate-as-pure': 7.27.3 '@babel/helper-plugin-utils': 7.27.1 - '@babel/preset-react@7.28.5(@babel/core@7.28.5)': + '@babel/preset-react@7.28.5(@babel/core@7.28.6)': dependencies: - '@babel/core': 7.28.5 + '@babel/core': 7.28.6 '@babel/helper-plugin-utils': 7.27.1 '@babel/helper-validator-option': 7.27.1 - '@babel/plugin-transform-react-display-name': 7.28.0(@babel/core@7.28.5) - '@babel/plugin-transform-react-jsx': 7.27.1(@babel/core@7.28.5) - '@babel/plugin-transform-react-jsx-development': 7.27.1(@babel/core@7.28.5) - '@babel/plugin-transform-react-pure-annotations': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-react-display-name': 7.28.0(@babel/core@7.28.6) + '@babel/plugin-transform-react-jsx': 7.27.1(@babel/core@7.28.6) + '@babel/plugin-transform-react-jsx-development': 7.27.1(@babel/core@7.28.6) + '@babel/plugin-transform-react-pure-annotations': 7.27.1(@babel/core@7.28.6) transitivePeerDependencies: - supports-color '@babel/template@7.27.2': dependencies: '@babel/code-frame': 7.27.1 - '@babel/parser': 7.28.5 - '@babel/types': 7.28.5 + '@babel/parser': 7.28.6 + '@babel/types': 7.28.6 - '@babel/traverse@7.28.5': + '@babel/template@7.28.6': dependencies: - '@babel/code-frame': 7.27.1 - '@babel/generator': 7.28.5 + '@babel/code-frame': 7.28.6 + '@babel/parser': 7.28.6 + '@babel/types': 7.28.6 + + '@babel/traverse@7.28.6': + dependencies: + '@babel/code-frame': 7.28.6 + '@babel/generator': 7.28.6 '@babel/helper-globals': 7.28.0 - '@babel/parser': 7.28.5 - '@babel/template': 7.27.2 - '@babel/types': 7.28.5 + '@babel/parser': 7.28.6 + '@babel/template': 7.28.6 + '@babel/types': 7.28.6 debug: 4.4.3 transitivePeerDependencies: - supports-color - '@babel/types@7.28.5': + '@babel/types@7.28.6': dependencies: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.28.5 @@ -9401,11 +9371,11 @@ snapshots: transitivePeerDependencies: - debug - '@codspeed/vitest-plugin@4.0.1(vite@7.1.7(@types/node@20.19.27)(jiti@2.6.1)(less@4.4.2)(sass-embedded@1.93.2)(sass@1.93.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(vitest@3.2.4(@types/debug@4.1.12)(@types/node@20.19.27)(jiti@2.6.1)(jsdom@26.1.0)(less@4.4.2)(sass-embedded@1.93.2)(sass@1.93.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': + '@codspeed/vitest-plugin@4.0.1(vite@7.1.7(@types/node@20.19.29)(jiti@2.6.1)(less@4.4.2)(sass-embedded@1.93.2)(sass@1.93.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(vitest@3.2.4(@types/debug@4.1.12)(@types/node@20.19.29)(jiti@2.6.1)(jsdom@26.1.0)(less@4.4.2)(sass-embedded@1.93.2)(sass@1.93.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': dependencies: '@codspeed/core': 4.0.1 - vite: 7.1.7(@types/node@20.19.27)(jiti@2.6.1)(less@4.4.2)(sass-embedded@1.93.2)(sass@1.93.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) - vitest: 3.2.4(@types/debug@4.1.12)(@types/node@20.19.27)(jiti@2.6.1)(jsdom@26.1.0)(less@4.4.2)(sass-embedded@1.93.2)(sass@1.93.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + vite: 7.1.7(@types/node@20.19.29)(jiti@2.6.1)(less@4.4.2)(sass-embedded@1.93.2)(sass@1.93.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + vitest: 3.2.4(@types/debug@4.1.12)(@types/node@20.19.29)(jiti@2.6.1)(jsdom@26.1.0)(less@4.4.2)(sass-embedded@1.93.2)(sass@1.93.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) transitivePeerDependencies: - debug @@ -9649,26 +9619,26 @@ snapshots: '@discoveryjs/json-ext@0.5.7': {} - '@docsearch/core@4.4.0(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + '@docsearch/core@4.4.0(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': optionalDependencies: - '@types/react': 19.2.7 + '@types/react': 19.2.8 react: 19.2.3 react-dom: 19.2.3(react@19.2.3) '@docsearch/css@4.4.0': {} - '@docsearch/react@4.4.0(@algolia/client-search@5.39.0)(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(search-insights@2.17.3)': + '@docsearch/react@4.4.0(@algolia/client-search@5.39.0)(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(search-insights@2.17.3)': dependencies: '@ai-sdk/react': 2.0.59(react@19.2.3)(zod@4.1.12) '@algolia/autocomplete-core': 1.19.2(@algolia/client-search@5.39.0)(algoliasearch@5.39.0)(search-insights@2.17.3) - '@docsearch/core': 4.4.0(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@docsearch/core': 4.4.0(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@docsearch/css': 4.4.0 ai: 5.0.59(zod@4.1.12) algoliasearch: 5.39.0 marked: 16.3.0 zod: 4.1.12 optionalDependencies: - '@types/react': 19.2.7 + '@types/react': 19.2.8 react: 19.2.3 react-dom: 19.2.3(react@19.2.3) search-insights: 2.17.3 @@ -9867,128 +9837,128 @@ snapshots: '@inquirer/ansi@1.0.0': {} - '@inquirer/checkbox@4.2.4(@types/node@20.19.27)': + '@inquirer/checkbox@4.2.4(@types/node@20.19.29)': dependencies: '@inquirer/ansi': 1.0.0 - '@inquirer/core': 10.2.2(@types/node@20.19.27) + '@inquirer/core': 10.2.2(@types/node@20.19.29) '@inquirer/figures': 1.0.13 - '@inquirer/type': 3.0.8(@types/node@20.19.27) + '@inquirer/type': 3.0.8(@types/node@20.19.29) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 20.19.27 + '@types/node': 20.19.29 - '@inquirer/confirm@5.1.18(@types/node@20.19.27)': + '@inquirer/confirm@5.1.18(@types/node@20.19.29)': dependencies: - '@inquirer/core': 10.2.2(@types/node@20.19.27) - '@inquirer/type': 3.0.8(@types/node@20.19.27) + '@inquirer/core': 10.2.2(@types/node@20.19.29) + '@inquirer/type': 3.0.8(@types/node@20.19.29) optionalDependencies: - '@types/node': 20.19.27 + '@types/node': 20.19.29 - '@inquirer/core@10.2.2(@types/node@20.19.27)': + '@inquirer/core@10.2.2(@types/node@20.19.29)': dependencies: '@inquirer/ansi': 1.0.0 '@inquirer/figures': 1.0.13 - '@inquirer/type': 3.0.8(@types/node@20.19.27) + '@inquirer/type': 3.0.8(@types/node@20.19.29) cli-width: 4.1.0 mute-stream: 2.0.0 signal-exit: 4.1.0 wrap-ansi: 6.2.0 yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 20.19.27 + '@types/node': 20.19.29 - '@inquirer/editor@4.2.20(@types/node@20.19.27)': + '@inquirer/editor@4.2.20(@types/node@20.19.29)': dependencies: - '@inquirer/core': 10.2.2(@types/node@20.19.27) - '@inquirer/external-editor': 1.0.2(@types/node@20.19.27) - '@inquirer/type': 3.0.8(@types/node@20.19.27) + '@inquirer/core': 10.2.2(@types/node@20.19.29) + '@inquirer/external-editor': 1.0.2(@types/node@20.19.29) + '@inquirer/type': 3.0.8(@types/node@20.19.29) optionalDependencies: - '@types/node': 20.19.27 + '@types/node': 20.19.29 - '@inquirer/expand@4.0.20(@types/node@20.19.27)': + '@inquirer/expand@4.0.20(@types/node@20.19.29)': dependencies: - '@inquirer/core': 10.2.2(@types/node@20.19.27) - '@inquirer/type': 3.0.8(@types/node@20.19.27) + '@inquirer/core': 10.2.2(@types/node@20.19.29) + '@inquirer/type': 3.0.8(@types/node@20.19.29) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 20.19.27 + '@types/node': 20.19.29 - '@inquirer/external-editor@1.0.2(@types/node@20.19.27)': + '@inquirer/external-editor@1.0.2(@types/node@20.19.29)': dependencies: chardet: 2.1.0 - iconv-lite: 0.7.1 + iconv-lite: 0.7.2 optionalDependencies: - '@types/node': 20.19.27 + '@types/node': 20.19.29 '@inquirer/figures@1.0.13': {} - '@inquirer/input@4.2.4(@types/node@20.19.27)': + '@inquirer/input@4.2.4(@types/node@20.19.29)': dependencies: - '@inquirer/core': 10.2.2(@types/node@20.19.27) - '@inquirer/type': 3.0.8(@types/node@20.19.27) + '@inquirer/core': 10.2.2(@types/node@20.19.29) + '@inquirer/type': 3.0.8(@types/node@20.19.29) optionalDependencies: - '@types/node': 20.19.27 + '@types/node': 20.19.29 - '@inquirer/number@3.0.20(@types/node@20.19.27)': + '@inquirer/number@3.0.20(@types/node@20.19.29)': dependencies: - '@inquirer/core': 10.2.2(@types/node@20.19.27) - '@inquirer/type': 3.0.8(@types/node@20.19.27) + '@inquirer/core': 10.2.2(@types/node@20.19.29) + '@inquirer/type': 3.0.8(@types/node@20.19.29) optionalDependencies: - '@types/node': 20.19.27 + '@types/node': 20.19.29 - '@inquirer/password@4.0.20(@types/node@20.19.27)': + '@inquirer/password@4.0.20(@types/node@20.19.29)': dependencies: '@inquirer/ansi': 1.0.0 - '@inquirer/core': 10.2.2(@types/node@20.19.27) - '@inquirer/type': 3.0.8(@types/node@20.19.27) + '@inquirer/core': 10.2.2(@types/node@20.19.29) + '@inquirer/type': 3.0.8(@types/node@20.19.29) optionalDependencies: - '@types/node': 20.19.27 - - '@inquirer/prompts@7.8.6(@types/node@20.19.27)': - dependencies: - '@inquirer/checkbox': 4.2.4(@types/node@20.19.27) - '@inquirer/confirm': 5.1.18(@types/node@20.19.27) - '@inquirer/editor': 4.2.20(@types/node@20.19.27) - '@inquirer/expand': 4.0.20(@types/node@20.19.27) - '@inquirer/input': 4.2.4(@types/node@20.19.27) - '@inquirer/number': 3.0.20(@types/node@20.19.27) - '@inquirer/password': 4.0.20(@types/node@20.19.27) - '@inquirer/rawlist': 4.1.8(@types/node@20.19.27) - '@inquirer/search': 3.1.3(@types/node@20.19.27) - '@inquirer/select': 4.3.4(@types/node@20.19.27) + '@types/node': 20.19.29 + + '@inquirer/prompts@7.8.6(@types/node@20.19.29)': + dependencies: + '@inquirer/checkbox': 4.2.4(@types/node@20.19.29) + '@inquirer/confirm': 5.1.18(@types/node@20.19.29) + '@inquirer/editor': 4.2.20(@types/node@20.19.29) + '@inquirer/expand': 4.0.20(@types/node@20.19.29) + '@inquirer/input': 4.2.4(@types/node@20.19.29) + '@inquirer/number': 3.0.20(@types/node@20.19.29) + '@inquirer/password': 4.0.20(@types/node@20.19.29) + '@inquirer/rawlist': 4.1.8(@types/node@20.19.29) + '@inquirer/search': 3.1.3(@types/node@20.19.29) + '@inquirer/select': 4.3.4(@types/node@20.19.29) optionalDependencies: - '@types/node': 20.19.27 + '@types/node': 20.19.29 - '@inquirer/rawlist@4.1.8(@types/node@20.19.27)': + '@inquirer/rawlist@4.1.8(@types/node@20.19.29)': dependencies: - '@inquirer/core': 10.2.2(@types/node@20.19.27) - '@inquirer/type': 3.0.8(@types/node@20.19.27) + '@inquirer/core': 10.2.2(@types/node@20.19.29) + '@inquirer/type': 3.0.8(@types/node@20.19.29) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 20.19.27 + '@types/node': 20.19.29 - '@inquirer/search@3.1.3(@types/node@20.19.27)': + '@inquirer/search@3.1.3(@types/node@20.19.29)': dependencies: - '@inquirer/core': 10.2.2(@types/node@20.19.27) + '@inquirer/core': 10.2.2(@types/node@20.19.29) '@inquirer/figures': 1.0.13 - '@inquirer/type': 3.0.8(@types/node@20.19.27) + '@inquirer/type': 3.0.8(@types/node@20.19.29) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 20.19.27 + '@types/node': 20.19.29 - '@inquirer/select@4.3.4(@types/node@20.19.27)': + '@inquirer/select@4.3.4(@types/node@20.19.29)': dependencies: '@inquirer/ansi': 1.0.0 - '@inquirer/core': 10.2.2(@types/node@20.19.27) + '@inquirer/core': 10.2.2(@types/node@20.19.29) '@inquirer/figures': 1.0.13 - '@inquirer/type': 3.0.8(@types/node@20.19.27) + '@inquirer/type': 3.0.8(@types/node@20.19.29) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 20.19.27 + '@types/node': 20.19.29 - '@inquirer/type@3.0.8(@types/node@20.19.27)': + '@inquirer/type@3.0.8(@types/node@20.19.29)': optionalDependencies: - '@types/node': 20.19.27 + '@types/node': 20.19.29 '@isaacs/balanced-match@4.0.1': {} @@ -10033,7 +10003,7 @@ snapshots: '@jest/transform@29.7.0': dependencies: - '@babel/core': 7.28.5 + '@babel/core': 7.28.6 '@jest/types': 29.6.3 '@jridgewell/trace-mapping': 0.3.31 babel-plugin-istanbul: 6.1.1 @@ -10056,7 +10026,7 @@ snapshots: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 20.19.27 + '@types/node': 20.19.29 '@types/yargs': 17.0.33 chalk: 4.1.2 @@ -10156,33 +10126,33 @@ snapshots: transitivePeerDependencies: - supports-color - '@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.3)': + '@mdx-js/react@3.1.1(@types/react@19.2.8)(react@19.2.3)': dependencies: '@types/mdx': 2.0.13 - '@types/react': 19.2.7 + '@types/react': 19.2.8 react: 19.2.3 '@mermaid-js/parser@0.6.3': dependencies: langium: 3.3.1 - '@microsoft/api-extractor-model@7.32.2(@types/node@20.19.27)': + '@microsoft/api-extractor-model@7.32.2(@types/node@20.19.29)': dependencies: '@microsoft/tsdoc': 0.16.0 '@microsoft/tsdoc-config': 0.18.0 - '@rushstack/node-core-library': 5.19.1(@types/node@20.19.27) + '@rushstack/node-core-library': 5.19.1(@types/node@20.19.29) transitivePeerDependencies: - '@types/node' - '@microsoft/api-extractor@7.55.2(@types/node@20.19.27)': + '@microsoft/api-extractor@7.55.2(@types/node@20.19.29)': dependencies: - '@microsoft/api-extractor-model': 7.32.2(@types/node@20.19.27) + '@microsoft/api-extractor-model': 7.32.2(@types/node@20.19.29) '@microsoft/tsdoc': 0.16.0 '@microsoft/tsdoc-config': 0.18.0 - '@rushstack/node-core-library': 5.19.1(@types/node@20.19.27) + '@rushstack/node-core-library': 5.19.1(@types/node@20.19.29) '@rushstack/rig-package': 0.6.0 - '@rushstack/terminal': 0.19.5(@types/node@20.19.27) - '@rushstack/ts-command-line': 5.1.5(@types/node@20.19.27) + '@rushstack/terminal': 0.19.5(@types/node@20.19.29) + '@rushstack/ts-command-line': 5.1.5(@types/node@20.19.29) diff: 8.0.2 lodash: 4.17.21 minimatch: 10.0.3 @@ -10202,59 +10172,34 @@ snapshots: '@microsoft/tsdoc@0.16.0': {} - '@module-federation/error-codes@0.21.6': {} - '@module-federation/error-codes@0.22.0': {} - '@module-federation/runtime-core@0.21.6': - dependencies: - '@module-federation/error-codes': 0.21.6 - '@module-federation/sdk': 0.21.6 - '@module-federation/runtime-core@0.22.0': dependencies: '@module-federation/error-codes': 0.22.0 '@module-federation/sdk': 0.22.0 - '@module-federation/runtime-tools@0.21.6': - dependencies: - '@module-federation/runtime': 0.21.6 - '@module-federation/webpack-bundler-runtime': 0.21.6 - '@module-federation/runtime-tools@0.22.0': dependencies: '@module-federation/runtime': 0.22.0 '@module-federation/webpack-bundler-runtime': 0.22.0 - '@module-federation/runtime@0.21.6': - dependencies: - '@module-federation/error-codes': 0.21.6 - '@module-federation/runtime-core': 0.21.6 - '@module-federation/sdk': 0.21.6 - '@module-federation/runtime@0.22.0': dependencies: '@module-federation/error-codes': 0.22.0 '@module-federation/runtime-core': 0.22.0 '@module-federation/sdk': 0.22.0 - '@module-federation/sdk@0.21.6': {} - '@module-federation/sdk@0.22.0': {} - '@module-federation/webpack-bundler-runtime@0.21.6': - dependencies: - '@module-federation/runtime': 0.21.6 - '@module-federation/sdk': 0.21.6 - '@module-federation/webpack-bundler-runtime@0.22.0': dependencies: '@module-federation/runtime': 0.22.0 '@module-federation/sdk': 0.22.0 - '@napi-rs/cli@3.0.4(@emnapi/runtime@1.5.0)(@types/node@20.19.27)(emnapi@1.7.1(node-addon-api@7.1.1))': + '@napi-rs/cli@3.0.4(@emnapi/runtime@1.5.0)(@types/node@20.19.29)(emnapi@1.7.1(node-addon-api@7.1.1))': dependencies: - '@inquirer/prompts': 7.8.6(@types/node@20.19.27) + '@inquirer/prompts': 7.8.6(@types/node@20.19.29) '@napi-rs/cross-toolchain': 1.0.3 '@napi-rs/wasm-tools': 1.0.1 '@octokit/rest': 22.0.0 @@ -10780,14 +10725,6 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.53.3': optional: true - '@rsbuild/core@1.6.15': - dependencies: - '@rspack/core': 1.6.8(@swc/helpers@0.5.18) - '@rspack/lite-tapable': 1.1.0 - '@swc/helpers': 0.5.18 - core-js: 3.47.0 - jiti: 2.6.1 - '@rsbuild/core@1.7.1': dependencies: '@rspack/core': 1.7.0(@swc/helpers@0.5.18) @@ -10832,9 +10769,9 @@ snapshots: optionalDependencies: '@rsbuild/core': 1.7.2 - '@rsbuild/plugin-react@1.4.2(@rsbuild/core@1.6.15)': + '@rsbuild/plugin-react@1.4.2(@rsbuild/core@1.7.2)': dependencies: - '@rsbuild/core': 1.6.15 + '@rsbuild/core': 1.7.2 '@rspack/plugin-react-refresh': 1.6.0(react-refresh@0.18.0) react-refresh: 0.18.0 transitivePeerDependencies: @@ -10849,12 +10786,12 @@ snapshots: reduce-configs: 1.1.1 sass-embedded: 1.93.2 - '@rslib/core@0.19.1(@microsoft/api-extractor@7.55.2(@types/node@20.19.27))(typescript@5.9.3)': + '@rslib/core@0.19.2(@microsoft/api-extractor@7.55.2(@types/node@20.19.29))(typescript@5.9.3)': dependencies: - '@rsbuild/core': 1.7.2 - rsbuild-plugin-dts: 0.19.1(@microsoft/api-extractor@7.55.2(@types/node@20.19.27))(@rsbuild/core@1.7.2)(typescript@5.9.3) + '@rsbuild/core': 1.7.1 + rsbuild-plugin-dts: 0.19.2(@microsoft/api-extractor@7.55.2(@types/node@20.19.29))(@rsbuild/core@1.7.1)(typescript@5.9.3) optionalDependencies: - '@microsoft/api-extractor': 7.55.2(@types/node@20.19.27) + '@microsoft/api-extractor': 7.55.2(@types/node@20.19.29) typescript: 5.9.3 transitivePeerDependencies: - '@typescript/native-preview' @@ -10886,65 +10823,42 @@ snapshots: '@rslint/win32-x64@0.1.13': optional: true - '@rspack/binding-darwin-arm64@1.6.8': - optional: true - '@rspack/binding-darwin-arm64@1.7.0': optional: true '@rspack/binding-darwin-arm64@1.7.1': optional: true - '@rspack/binding-darwin-x64@1.6.8': - optional: true - '@rspack/binding-darwin-x64@1.7.0': optional: true '@rspack/binding-darwin-x64@1.7.1': optional: true - '@rspack/binding-linux-arm64-gnu@1.6.8': - optional: true - '@rspack/binding-linux-arm64-gnu@1.7.0': optional: true '@rspack/binding-linux-arm64-gnu@1.7.1': optional: true - '@rspack/binding-linux-arm64-musl@1.6.8': - optional: true - '@rspack/binding-linux-arm64-musl@1.7.0': optional: true '@rspack/binding-linux-arm64-musl@1.7.1': optional: true - '@rspack/binding-linux-x64-gnu@1.6.8': - optional: true - '@rspack/binding-linux-x64-gnu@1.7.0': optional: true '@rspack/binding-linux-x64-gnu@1.7.1': optional: true - '@rspack/binding-linux-x64-musl@1.6.8': - optional: true - '@rspack/binding-linux-x64-musl@1.7.0': optional: true '@rspack/binding-linux-x64-musl@1.7.1': optional: true - '@rspack/binding-wasm32-wasi@1.6.8': - dependencies: - '@napi-rs/wasm-runtime': 1.0.7 - optional: true - '@rspack/binding-wasm32-wasi@1.7.0': dependencies: '@napi-rs/wasm-runtime': 1.0.7 @@ -10955,46 +10869,24 @@ snapshots: '@napi-rs/wasm-runtime': 1.0.7 optional: true - '@rspack/binding-win32-arm64-msvc@1.6.8': - optional: true - '@rspack/binding-win32-arm64-msvc@1.7.0': optional: true '@rspack/binding-win32-arm64-msvc@1.7.1': optional: true - '@rspack/binding-win32-ia32-msvc@1.6.8': - optional: true - '@rspack/binding-win32-ia32-msvc@1.7.0': optional: true '@rspack/binding-win32-ia32-msvc@1.7.1': optional: true - '@rspack/binding-win32-x64-msvc@1.6.8': - optional: true - '@rspack/binding-win32-x64-msvc@1.7.0': optional: true '@rspack/binding-win32-x64-msvc@1.7.1': optional: true - '@rspack/binding@1.6.8': - optionalDependencies: - '@rspack/binding-darwin-arm64': 1.6.8 - '@rspack/binding-darwin-x64': 1.6.8 - '@rspack/binding-linux-arm64-gnu': 1.6.8 - '@rspack/binding-linux-arm64-musl': 1.6.8 - '@rspack/binding-linux-x64-gnu': 1.6.8 - '@rspack/binding-linux-x64-musl': 1.6.8 - '@rspack/binding-wasm32-wasi': 1.6.8 - '@rspack/binding-win32-arm64-msvc': 1.6.8 - '@rspack/binding-win32-ia32-msvc': 1.6.8 - '@rspack/binding-win32-x64-msvc': 1.6.8 - '@rspack/binding@1.7.0': optionalDependencies: '@rspack/binding-darwin-arm64': 1.7.0 @@ -11021,14 +10913,6 @@ snapshots: '@rspack/binding-win32-ia32-msvc': 1.7.1 '@rspack/binding-win32-x64-msvc': 1.7.1 - '@rspack/core@1.6.8(@swc/helpers@0.5.18)': - dependencies: - '@module-federation/runtime-tools': 0.21.6 - '@rspack/binding': 1.6.8 - '@rspack/lite-tapable': 1.1.0 - optionalDependencies: - '@swc/helpers': 0.5.18 - '@rspack/core@1.7.0(@swc/helpers@0.5.18)': dependencies: '@module-federation/runtime-tools': 0.22.0 @@ -11092,18 +10976,17 @@ snapshots: html-entities: 2.6.0 react-refresh: 0.18.0 - '@rspress/core@2.0.0-rc.4(@types/react@19.2.7)': + '@rspress/core@2.0.0-rc.5(@types/react@19.2.8)': dependencies: '@mdx-js/mdx': 3.1.1 - '@mdx-js/react': 3.1.1(@types/react@19.2.7)(react@19.2.3) - '@rsbuild/core': 1.6.15 - '@rsbuild/plugin-react': 1.4.2(@rsbuild/core@1.6.15) + '@mdx-js/react': 3.1.1(@types/react@19.2.8)(react@19.2.3) + '@rsbuild/core': 1.7.2 + '@rsbuild/plugin-react': 1.4.2(@rsbuild/core@1.7.2) '@rspress/mdx-rs': 0.6.6 - '@rspress/runtime': 2.0.0-rc.4 - '@rspress/shared': 2.0.0-rc.4 + '@rspress/shared': 2.0.0-rc.5 '@shikijs/rehype': 3.20.0 '@types/unist': 3.0.3 - '@unhead/react': 2.0.19(react@19.2.3) + '@unhead/react': 2.1.2(react@19.2.3) body-scroll-lock: 4.0.0-beta.0 cac: 6.7.14 chokidar: 3.6.0 @@ -11177,11 +11060,11 @@ snapshots: '@rspress/mdx-rs-win32-arm64-msvc': 0.6.6 '@rspress/mdx-rs-win32-x64-msvc': 0.6.6 - '@rspress/plugin-algolia@2.0.0-rc.4(@algolia/client-search@5.39.0)(@rspress/core@2.0.0-rc.4(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(search-insights@2.17.3)': + '@rspress/plugin-algolia@2.0.0-rc.5(@algolia/client-search@5.39.0)(@rspress/core@2.0.0-rc.5(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(search-insights@2.17.3)': dependencies: '@docsearch/css': 4.4.0 - '@docsearch/react': 4.4.0(@algolia/client-search@5.39.0)(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(search-insights@2.17.3) - '@rspress/core': 2.0.0-rc.4(@types/react@19.2.7) + '@docsearch/react': 4.4.0(@algolia/client-search@5.39.0)(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(search-insights@2.17.3) + '@rspress/core': 2.0.0-rc.5(@types/react@19.2.8) transitivePeerDependencies: - '@algolia/client-search' - '@types/react' @@ -11189,13 +11072,13 @@ snapshots: - react-dom - search-insights - '@rspress/plugin-client-redirects@2.0.0-rc.4(@rspress/core@2.0.0-rc.4(@types/react@19.2.7))': + '@rspress/plugin-client-redirects@2.0.0-rc.5(@rspress/core@2.0.0-rc.5(@types/react@19.2.8))': dependencies: - '@rspress/core': 2.0.0-rc.4(@types/react@19.2.7) + '@rspress/core': 2.0.0-rc.5(@types/react@19.2.8) - '@rspress/plugin-llms@2.0.0-rc.4(@rspress/core@2.0.0-rc.4(@types/react@19.2.7))': + '@rspress/plugin-llms@2.0.0-rc.5(@rspress/core@2.0.0-rc.5(@types/react@19.2.8))': dependencies: - '@rspress/core': 2.0.0-rc.4(@types/react@19.2.7) + '@rspress/core': 2.0.0-rc.5(@types/react@19.2.8) remark-mdx: 3.1.1 remark-parse: 11.0.0 remark-stringify: 11.0.0 @@ -11204,32 +11087,24 @@ snapshots: transitivePeerDependencies: - supports-color - '@rspress/plugin-rss@2.0.0-rc.4(@rspress/core@2.0.0-rc.4(@types/react@19.2.7))': + '@rspress/plugin-rss@2.0.0-rc.5(@rspress/core@2.0.0-rc.5(@types/react@19.2.8))': dependencies: - '@rspress/core': 2.0.0-rc.4(@types/react@19.2.7) + '@rspress/core': 2.0.0-rc.5(@types/react@19.2.8) feed: 4.2.2 - '@rspress/plugin-sitemap@2.0.0-rc.4(@rspress/core@2.0.0-rc.4(@types/react@19.2.7))': + '@rspress/plugin-sitemap@2.0.0-rc.5(@rspress/core@2.0.0-rc.5(@types/react@19.2.8))': dependencies: - '@rspress/core': 2.0.0-rc.4(@types/react@19.2.7) + '@rspress/core': 2.0.0-rc.5(@types/react@19.2.8) - '@rspress/runtime@2.0.0-rc.4': + '@rspress/shared@2.0.0-rc.5': dependencies: - '@rspress/shared': 2.0.0-rc.4 - '@unhead/react': 2.0.19(react@19.2.3) - react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) - react-router-dom: 7.11.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - - '@rspress/shared@2.0.0-rc.4': - dependencies: - '@rsbuild/core': 1.6.15 + '@rsbuild/core': 1.7.2 '@shikijs/rehype': 3.20.0 gray-matter: 4.0.3 lodash-es: 4.17.22 unified: 11.0.5 - '@rstack-dev/doc-ui@1.12.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + '@rstack-dev/doc-ui@1.12.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': dependencies: framer-motion: 12.23.26(react-dom@19.2.3(react@19.2.3))(react@19.2.3) transitivePeerDependencies: @@ -11245,7 +11120,7 @@ snapshots: optionalDependencies: jsdom: 26.1.0 - '@rushstack/node-core-library@5.19.1(@types/node@20.19.27)': + '@rushstack/node-core-library@5.19.1(@types/node@20.19.29)': dependencies: ajv: 8.13.0 ajv-draft-04: 1.0.0(ajv@8.13.0) @@ -11256,28 +11131,28 @@ snapshots: resolve: 1.22.11 semver: 7.5.4 optionalDependencies: - '@types/node': 20.19.27 + '@types/node': 20.19.29 - '@rushstack/problem-matcher@0.1.1(@types/node@20.19.27)': + '@rushstack/problem-matcher@0.1.1(@types/node@20.19.29)': optionalDependencies: - '@types/node': 20.19.27 + '@types/node': 20.19.29 '@rushstack/rig-package@0.6.0': dependencies: resolve: 1.22.11 strip-json-comments: 3.1.1 - '@rushstack/terminal@0.19.5(@types/node@20.19.27)': + '@rushstack/terminal@0.19.5(@types/node@20.19.29)': dependencies: - '@rushstack/node-core-library': 5.19.1(@types/node@20.19.27) - '@rushstack/problem-matcher': 0.1.1(@types/node@20.19.27) + '@rushstack/node-core-library': 5.19.1(@types/node@20.19.29) + '@rushstack/problem-matcher': 0.1.1(@types/node@20.19.29) supports-color: 8.1.1 optionalDependencies: - '@types/node': 20.19.27 + '@types/node': 20.19.29 - '@rushstack/ts-command-line@5.1.5(@types/node@20.19.27)': + '@rushstack/ts-command-line@5.1.5(@types/node@20.19.29)': dependencies: - '@rushstack/terminal': 0.19.5(@types/node@20.19.27) + '@rushstack/terminal': 0.19.5(@types/node@20.19.29) '@types/argparse': 1.0.38 argparse: 1.0.10 string-argv: 0.3.2 @@ -11392,20 +11267,20 @@ snapshots: '@types/babel__generator@7.27.0': dependencies: - '@babel/types': 7.28.5 + '@babel/types': 7.28.6 '@types/babel__traverse@7.28.0': dependencies: - '@babel/types': 7.28.5 + '@babel/types': 7.28.6 '@types/body-parser@1.19.6': dependencies: '@types/connect': 3.4.38 - '@types/node': 20.19.27 + '@types/node': 20.19.29 '@types/bonjour@3.5.13': dependencies: - '@types/node': 20.19.27 + '@types/node': 20.19.29 '@types/chai@5.2.2': dependencies: @@ -11419,11 +11294,11 @@ snapshots: '@types/connect-history-api-fallback@1.5.4': dependencies: '@types/express-serve-static-core': 4.19.6 - '@types/node': 20.19.27 + '@types/node': 20.19.29 '@types/connect@3.4.38': dependencies: - '@types/node': 20.19.27 + '@types/node': 20.19.29 '@types/d3-array@3.2.2': {} @@ -11566,7 +11441,7 @@ snapshots: '@types/express-serve-static-core@4.19.6': dependencies: - '@types/node': 20.19.27 + '@types/node': 20.19.29 '@types/qs': 6.14.0 '@types/range-parser': 1.2.7 '@types/send': 0.17.5 @@ -11581,13 +11456,13 @@ snapshots: '@types/fs-extra@11.0.4': dependencies: '@types/jsonfile': 6.1.4 - '@types/node': 20.19.27 + '@types/node': 20.19.29 '@types/geojson@7946.0.16': {} '@types/graceful-fs@4.1.9': dependencies: - '@types/node': 20.19.27 + '@types/node': 20.19.29 '@types/hast@3.0.4': dependencies: @@ -11599,7 +11474,7 @@ snapshots: '@types/http-proxy@1.17.16': dependencies: - '@types/node': 20.19.27 + '@types/node': 20.19.29 '@types/is-ci@3.0.4': dependencies: @@ -11619,7 +11494,7 @@ snapshots: '@types/jsdom@21.1.7': dependencies: - '@types/node': 20.19.27 + '@types/node': 20.19.29 '@types/tough-cookie': 4.0.5 parse5: 7.3.0 @@ -11627,7 +11502,7 @@ snapshots: '@types/jsonfile@6.1.4': dependencies: - '@types/node': 20.19.27 + '@types/node': 20.19.29 '@types/mdast@4.0.4': dependencies: @@ -11641,9 +11516,9 @@ snapshots: '@types/node-forge@1.3.14': dependencies: - '@types/node': 20.19.27 + '@types/node': 20.19.29 - '@types/node@20.19.27': + '@types/node@20.19.29': dependencies: undici-types: 6.21.0 @@ -11651,11 +11526,11 @@ snapshots: '@types/range-parser@1.2.7': {} - '@types/react-dom@19.2.3(@types/react@19.2.7)': + '@types/react-dom@19.2.3(@types/react@19.2.8)': dependencies: - '@types/react': 19.2.7 + '@types/react': 19.2.8 - '@types/react@19.2.7': + '@types/react@19.2.8': dependencies: csstype: 3.2.3 @@ -11666,7 +11541,7 @@ snapshots: '@types/send@0.17.5': dependencies: '@types/mime': 1.3.5 - '@types/node': 20.19.27 + '@types/node': 20.19.29 '@types/serve-index@1.9.4': dependencies: @@ -11675,12 +11550,12 @@ snapshots: '@types/serve-static@1.15.8': dependencies: '@types/http-errors': 2.0.5 - '@types/node': 20.19.27 + '@types/node': 20.19.29 '@types/send': 0.17.5 '@types/sockjs@0.3.36': dependencies: - '@types/node': 20.19.27 + '@types/node': 20.19.29 '@types/stack-utils@2.0.3': {} @@ -11696,11 +11571,11 @@ snapshots: '@types/watchpack@2.4.5': dependencies: '@types/graceful-fs': 4.1.9 - '@types/node': 20.19.27 + '@types/node': 20.19.29 '@types/webpack-bundle-analyzer@4.7.0': dependencies: - '@types/node': 20.19.27 + '@types/node': 20.19.29 tapable: 2.2.3 webpack: 5.99.9 transitivePeerDependencies: @@ -11711,7 +11586,7 @@ snapshots: '@types/ws@8.18.1': dependencies: - '@types/node': 20.19.27 + '@types/node': 20.19.29 '@types/yargs-parser@21.0.3': {} @@ -11721,10 +11596,10 @@ snapshots: '@ungap/structured-clone@1.3.0': {} - '@unhead/react@2.0.19(react@19.2.3)': + '@unhead/react@2.1.2(react@19.2.3)': dependencies: react: 19.2.3 - unhead: 2.0.19 + unhead: 2.1.2 '@vercel/ncc@0.38.4': {} @@ -11736,13 +11611,13 @@ snapshots: chai: 5.3.3 tinyrainbow: 2.0.0 - '@vitest/mocker@3.2.4(vite@7.1.7(@types/node@20.19.27)(jiti@2.6.1)(less@4.4.2)(sass-embedded@1.93.2)(sass@1.93.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': + '@vitest/mocker@3.2.4(vite@7.1.7(@types/node@20.19.29)(jiti@2.6.1)(less@4.4.2)(sass-embedded@1.93.2)(sass@1.93.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': dependencies: '@vitest/spy': 3.2.4 estree-walker: 3.0.3 magic-string: 0.30.19 optionalDependencies: - vite: 7.1.7(@types/node@20.19.27)(jiti@2.6.1)(less@4.4.2)(sass-embedded@1.93.2)(sass@1.93.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + vite: 7.1.7(@types/node@20.19.29)(jiti@2.6.1)(less@4.4.2)(sass-embedded@1.93.2)(sass@1.93.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) '@vitest/pretty-format@3.2.4': dependencies: @@ -11772,7 +11647,7 @@ snapshots: '@vue/compiler-core@3.5.26': dependencies: - '@babel/parser': 7.28.5 + '@babel/parser': 7.28.6 '@vue/shared': 3.5.26 entities: 7.0.0 estree-walker: 2.0.2 @@ -11785,7 +11660,7 @@ snapshots: '@vue/compiler-sfc@3.5.26': dependencies: - '@babel/parser': 7.28.5 + '@babel/parser': 7.28.6 '@vue/compiler-core': 3.5.26 '@vue/compiler-dom': 3.5.26 '@vue/compiler-ssr': 3.5.26 @@ -12097,9 +11972,9 @@ snapshots: transitivePeerDependencies: - debug - babel-loader@10.0.0(@babel/core@7.28.5)(webpack@5.102.1): + babel-loader@10.0.0(@babel/core@7.28.6)(webpack@5.102.1): dependencies: - '@babel/core': 7.28.5 + '@babel/core': 7.28.6 find-up: 5.0.0 webpack: 5.102.1 @@ -12140,7 +12015,7 @@ snapshots: babel-walk@3.0.0-canary-5: dependencies: - '@babel/types': 7.28.5 + '@babel/types': 7.28.6 bail@2.0.2: {} @@ -12544,8 +12419,8 @@ snapshots: constantinople@4.0.1: dependencies: - '@babel/parser': 7.28.5 - '@babel/types': 7.28.5 + '@babel/parser': 7.28.6 + '@babel/types': 7.28.6 constants-browserify@1.0.0: {} @@ -13929,7 +13804,7 @@ snapshots: minimalistic-assert: 1.0.1 minimalistic-crypto-utils: 1.0.1 - hookable@5.5.3: {} + hookable@6.0.1: {} hpack.js@2.1.6: dependencies: @@ -14076,7 +13951,7 @@ snapshots: dependencies: safer-buffer: 2.1.2 - iconv-lite@0.7.1: + iconv-lite@0.7.2: dependencies: safer-buffer: 2.1.2 @@ -14247,8 +14122,8 @@ snapshots: istanbul-lib-instrument@5.2.1: dependencies: - '@babel/core': 7.28.5 - '@babel/parser': 7.28.5 + '@babel/core': 7.28.6 + '@babel/parser': 7.28.6 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.2 semver: 6.3.1 @@ -14289,7 +14164,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@types/graceful-fs': 4.1.9 - '@types/node': 20.19.27 + '@types/node': 20.19.29 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -14325,10 +14200,10 @@ snapshots: jest-snapshot@29.7.0: dependencies: '@babel/core': 7.28.4 - '@babel/generator': 7.28.5 + '@babel/generator': 7.28.6 '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.4) '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.28.4) - '@babel/types': 7.28.5 + '@babel/types': 7.28.6 '@jest/expect-utils': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 @@ -14350,7 +14225,7 @@ snapshots: jest-util@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 20.19.27 + '@types/node': 20.19.29 chalk: 4.1.2 ci-info: 3.9.0 graceful-fs: 4.2.11 @@ -14358,13 +14233,13 @@ snapshots: jest-worker@27.5.1: dependencies: - '@types/node': 20.19.27 + '@types/node': 20.19.29 merge-stream: 2.0.0 supports-color: 8.1.1 jest-worker@29.7.0: dependencies: - '@types/node': 20.19.27 + '@types/node': 20.19.29 jest-util: 29.7.0 merge-stream: 2.0.0 supports-color: 8.1.1 @@ -14617,7 +14492,7 @@ snapshots: markdown-table@3.0.4: {} - markdown-to-jsx@9.5.0(react@19.2.3)(vue@3.5.26(typescript@5.9.3)): + markdown-to-jsx@9.5.7(react@19.2.3)(vue@3.5.26(typescript@5.9.3)): optionalDependencies: react: 19.2.3 vue: 3.5.26(typescript@5.9.3) @@ -15545,13 +15420,13 @@ snapshots: camelcase-css: 2.0.1 postcss: 8.5.6 - postcss-load-config@4.0.2(postcss@8.5.6)(ts-node@10.9.2(@types/node@20.19.27)(typescript@5.9.3)): + postcss-load-config@4.0.2(postcss@8.5.6)(ts-node@10.9.2(@types/node@20.19.29)(typescript@5.9.3)): dependencies: lilconfig: 3.1.3 yaml: 2.8.2 optionalDependencies: postcss: 8.5.6 - ts-node: 10.9.2(@types/node@20.19.27)(typescript@5.9.3) + ts-node: 10.9.2(@types/node@20.19.29)(typescript@5.9.3) postcss-loader@8.2.0(@rspack/core@packages+rspack)(postcss@8.5.6)(typescript@5.9.3)(webpack@5.102.1): dependencies: @@ -16093,12 +15968,12 @@ snapshots: rrweb-cssom@0.8.0: {} - rsbuild-plugin-dts@0.19.1(@microsoft/api-extractor@7.55.2(@types/node@20.19.27))(@rsbuild/core@1.7.2)(typescript@5.9.3): + rsbuild-plugin-dts@0.19.2(@microsoft/api-extractor@7.55.2(@types/node@20.19.29))(@rsbuild/core@1.7.1)(typescript@5.9.3): dependencies: '@ast-grep/napi': 0.37.0 - '@rsbuild/core': 1.7.2 + '@rsbuild/core': 1.7.1 optionalDependencies: - '@microsoft/api-extractor': 7.55.2(@types/node@20.19.27) + '@microsoft/api-extractor': 7.55.2(@types/node@20.19.29) typescript: 5.9.3 rsbuild-plugin-google-analytics@1.0.4(@rsbuild/core@1.7.2): @@ -16117,9 +15992,9 @@ snapshots: optionalDependencies: vue: 3.5.26(typescript@5.9.3) - rspress-plugin-font-open-sans@1.0.3(@rspress/core@2.0.0-rc.4(@types/react@19.2.7)): + rspress-plugin-font-open-sans@1.0.3(@rspress/core@2.0.0-rc.5(@types/react@19.2.8)): dependencies: - '@rspress/core': 2.0.0-rc.4(@types/react@19.2.7) + '@rspress/core': 2.0.0-rc.5(@types/react@19.2.8) run-applescript@7.1.0: {} @@ -16648,7 +16523,7 @@ snapshots: string-width: 4.2.3 strip-ansi: 6.0.1 - tailwindcss@3.4.19(ts-node@10.9.2(@types/node@20.19.27)(typescript@5.9.3)): + tailwindcss@3.4.19(ts-node@10.9.2(@types/node@20.19.29)(typescript@5.9.3)): dependencies: '@alloc/quick-lru': 5.2.0 arg: 5.0.2 @@ -16667,7 +16542,7 @@ snapshots: postcss: 8.5.6 postcss-import: 15.1.0(postcss@8.5.6) postcss-js: 4.1.0(postcss@8.5.6) - postcss-load-config: 4.0.2(postcss@8.5.6)(ts-node@10.9.2(@types/node@20.19.27)(typescript@5.9.3)) + postcss-load-config: 4.0.2(postcss@8.5.6)(ts-node@10.9.2(@types/node@20.19.29)(typescript@5.9.3)) postcss-nested: 6.2.0(postcss@8.5.6) postcss-selector-parser: 6.1.2 resolve: 1.22.11 @@ -16809,14 +16684,14 @@ snapshots: typescript: 5.9.3 webpack: 5.102.1 - ts-node@10.9.2(@types/node@20.19.27)(typescript@5.9.3): + ts-node@10.9.2(@types/node@20.19.29)(typescript@5.9.3): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.11 '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 - '@types/node': 20.19.27 + '@types/node': 20.19.29 acorn: 8.15.0 acorn-walk: 8.3.4 arg: 4.1.3 @@ -16871,9 +16746,9 @@ snapshots: dependencies: '@fastify/busboy': 2.1.1 - unhead@2.0.19: + unhead@2.1.2: dependencies: - hookable: 5.5.3 + hookable: 6.0.1 unicorn-magic@0.1.0: {} @@ -16999,13 +16874,13 @@ snapshots: '@types/unist': 3.0.3 vfile-message: 4.0.3 - vite-node@3.2.4(@types/node@20.19.27)(jiti@2.6.1)(less@4.4.2)(sass-embedded@1.93.2)(sass@1.93.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2): + vite-node@3.2.4(@types/node@20.19.29)(jiti@2.6.1)(less@4.4.2)(sass-embedded@1.93.2)(sass@1.93.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2): dependencies: cac: 6.7.14 debug: 4.4.3 es-module-lexer: 1.7.0 pathe: 2.0.3 - vite: 7.1.7(@types/node@20.19.27)(jiti@2.6.1)(less@4.4.2)(sass-embedded@1.93.2)(sass@1.93.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + vite: 7.1.7(@types/node@20.19.29)(jiti@2.6.1)(less@4.4.2)(sass-embedded@1.93.2)(sass@1.93.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) transitivePeerDependencies: - '@types/node' - jiti @@ -17020,7 +16895,7 @@ snapshots: - tsx - yaml - vite@7.1.7(@types/node@20.19.27)(jiti@2.6.1)(less@4.4.2)(sass-embedded@1.93.2)(sass@1.93.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2): + vite@7.1.7(@types/node@20.19.29)(jiti@2.6.1)(less@4.4.2)(sass-embedded@1.93.2)(sass@1.93.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2): dependencies: esbuild: 0.25.10 fdir: 6.5.0(picomatch@4.0.3) @@ -17029,7 +16904,7 @@ snapshots: rollup: 4.52.3 tinyglobby: 0.2.15 optionalDependencies: - '@types/node': 20.19.27 + '@types/node': 20.19.29 fsevents: 2.3.3 jiti: 2.6.1 less: 4.4.2 @@ -17039,11 +16914,11 @@ snapshots: tsx: 4.21.0 yaml: 2.8.2 - vitest@3.2.4(@types/debug@4.1.12)(@types/node@20.19.27)(jiti@2.6.1)(jsdom@26.1.0)(less@4.4.2)(sass-embedded@1.93.2)(sass@1.93.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2): + vitest@3.2.4(@types/debug@4.1.12)(@types/node@20.19.29)(jiti@2.6.1)(jsdom@26.1.0)(less@4.4.2)(sass-embedded@1.93.2)(sass@1.93.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2): dependencies: '@types/chai': 5.2.2 '@vitest/expect': 3.2.4 - '@vitest/mocker': 3.2.4(vite@7.1.7(@types/node@20.19.27)(jiti@2.6.1)(less@4.4.2)(sass-embedded@1.93.2)(sass@1.93.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + '@vitest/mocker': 3.2.4(vite@7.1.7(@types/node@20.19.29)(jiti@2.6.1)(less@4.4.2)(sass-embedded@1.93.2)(sass@1.93.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) '@vitest/pretty-format': 3.2.4 '@vitest/runner': 3.2.4 '@vitest/snapshot': 3.2.4 @@ -17061,12 +16936,12 @@ snapshots: tinyglobby: 0.2.15 tinypool: 1.1.1 tinyrainbow: 2.0.0 - vite: 7.1.7(@types/node@20.19.27)(jiti@2.6.1)(less@4.4.2)(sass-embedded@1.93.2)(sass@1.93.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) - vite-node: 3.2.4(@types/node@20.19.27)(jiti@2.6.1)(less@4.4.2)(sass-embedded@1.93.2)(sass@1.93.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + vite: 7.1.7(@types/node@20.19.29)(jiti@2.6.1)(less@4.4.2)(sass-embedded@1.93.2)(sass@1.93.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + vite-node: 3.2.4(@types/node@20.19.29)(jiti@2.6.1)(less@4.4.2)(sass-embedded@1.93.2)(sass@1.93.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) why-is-node-running: 2.3.0 optionalDependencies: '@types/debug': 4.1.12 - '@types/node': 20.19.27 + '@types/node': 20.19.29 jsdom: 26.1.0 transitivePeerDependencies: - jiti @@ -17375,8 +17250,8 @@ snapshots: with@7.0.2: dependencies: - '@babel/parser': 7.28.5 - '@babel/types': 7.28.5 + '@babel/parser': 7.28.6 + '@babel/types': 7.28.6 assert-never: 1.4.0 babel-walk: 3.0.0-canary-5 diff --git a/tests/bench/package.json b/tests/bench/package.json index a3417831cffa..84d089870b6c 100644 --- a/tests/bench/package.json +++ b/tests/bench/package.json @@ -11,7 +11,7 @@ "@rspack/cli": "workspace:*", "@rspack/core": "workspace:*", "@rspack/plugin-react-refresh": "^1.6.0", - "@types/react": "^19.2.7", + "@types/react": "^19.2.8", "@types/react-dom": "^19.2.3", "vitest": "^3.2.4" }, diff --git a/tests/e2e/package.json b/tests/e2e/package.json index e9de9b489e9b..69d3b0601d72 100644 --- a/tests/e2e/package.json +++ b/tests/e2e/package.json @@ -7,7 +7,7 @@ "test:CI": "CI=1 pnpm run test" }, "devDependencies": { - "@babel/core": "^7.28.5", + "@babel/core": "^7.28.6", "@babel/preset-react": "^7.28.5", "@playwright/test": "1.57.0", "core-js": "3.47.0", diff --git a/tests/rspack-test/package.json b/tests/rspack-test/package.json index fe7ec3a9c3b2..3678d5dd0f2e 100644 --- a/tests/rspack-test/package.json +++ b/tests/rspack-test/package.json @@ -26,7 +26,7 @@ "@types/babel__traverse": "7.28.0", "@types/fs-extra": "11.0.4", "@types/jsdom": "^21.1.7", - "@types/react": "^19.2.7", + "@types/react": "^19.2.8", "@types/react-dom": "^19.2.3", "@webdiscus/pug-loader": "^2.11.1", "acorn": "^8.15.0", @@ -75,7 +75,7 @@ "url-loader": "^4.1.1", "terser-webpack-plugin": "^5.3.16", "ts-loader": "^9.5.4", - "@babel/core": "^7.28.5", + "@babel/core": "^7.28.6", "date-fns": "^4.1.0", "fork-ts-checker-webpack-plugin": "^9.1.0", "json5": "^2.2.3", diff --git a/website/package.json b/website/package.json index 210d6464b294..96e9a1d63ea8 100644 --- a/website/package.json +++ b/website/package.json @@ -16,9 +16,9 @@ "sort-projects-words": "node ./sortProjectWords.js" }, "dependencies": { - "@rstack-dev/doc-ui": "1.12.2", + "@rstack-dev/doc-ui": "1.12.3", "axios": "^1.13.2", - "markdown-to-jsx": "^9.5.0", + "markdown-to-jsx": "^9.5.7", "mermaid": "^11.12.2", "react": "^19.2.3", "react-dom": "^19.2.3", @@ -27,15 +27,15 @@ }, "devDependencies": { "@rsbuild/plugin-sass": "^1.4.0", - "@rspress/core": "2.0.0-rc.4", - "@rspress/plugin-algolia": "2.0.0-rc.4", - "@rspress/plugin-client-redirects": "2.0.0-rc.4", - "@rspress/plugin-llms": "2.0.0-rc.4", - "@rspress/plugin-rss": "2.0.0-rc.4", - "@rspress/plugin-sitemap": "2.0.0-rc.4", + "@rspress/core": "2.0.0-rc.5", + "@rspress/plugin-algolia": "2.0.0-rc.5", + "@rspress/plugin-client-redirects": "2.0.0-rc.5", + "@rspress/plugin-llms": "2.0.0-rc.5", + "@rspress/plugin-rss": "2.0.0-rc.5", + "@rspress/plugin-sitemap": "2.0.0-rc.5", "@shikijs/transformers": "^3.21.0", - "@types/node": "^20.19.27", - "@types/react": "^19.2.7", + "@types/node": "^20.19.29", + "@types/react": "^19.2.8", "@types/semver": "^7.7.1", "case-police": "~2.1.1", "cspell": "^9.4.0", From d9915de43e528447ef50c85fa8bff4f84a0fb274 Mon Sep 17 00:00:00 2001 From: hardfist Date: Thu, 15 Jan 2026 09:32:14 +0800 Subject: [PATCH 61/87] refactor: move pass into separate folder and driven by run_passes (#12735) * chore: add rspack_passes.md * refactor: move pass into separate folder and drive by run_passes * chore: use function * refactor: move more into run_passes * chore: fix stats logging * chore: fix stats.logging --- .../src/compilation/after_seal/mod.rs | 20 + .../src/compilation/assign_runtime_ids/mod.rs | 42 + .../src/compilation/build_chunk_graph/mod.rs | 1 + .../src/compilation/build_chunk_graph/pass.rs | 26 + .../src/compilation/chunk_ids/mod.rs | 38 + .../src/compilation/code_generation/mod.rs | 208 ++ .../compilation/create_chunk_assets/mod.rs | 171 ++ .../src/compilation/create_hash/mod.rs | 452 ++++ .../compilation/create_module_assets/mod.rs | 53 + .../compilation/create_module_hashes/mod.rs | 141 ++ .../src/compilation/finish_module/mod.rs | 175 ++ crates/rspack_core/src/compilation/mod.rs | 1811 +---------------- .../src/compilation/module_ids/mod.rs | 31 + .../compilation/optimize_chunk_modules/mod.rs | 14 + .../src/compilation/optimize_chunks/mod.rs | 17 + .../optimize_code_generation/mod.rs | 18 + .../compilation/optimize_dependencies/mod.rs | 39 + .../src/compilation/optimize_modules/mod.rs | 25 + .../src/compilation/optimize_tree/mod.rs | 13 + .../src/compilation/process_assets/mod.rs | 43 + .../src/compilation/rspack_passes.md | 63 + .../rspack_core/src/compilation/run_passes.rs | 113 + .../compilation/runtime_requirements/mod.rs | 404 ++++ crates/rspack_core/src/compiler/mod.rs | 71 +- 24 files changed, 2135 insertions(+), 1854 deletions(-) create mode 100644 crates/rspack_core/src/compilation/after_seal/mod.rs create mode 100644 crates/rspack_core/src/compilation/assign_runtime_ids/mod.rs create mode 100644 crates/rspack_core/src/compilation/build_chunk_graph/pass.rs create mode 100644 crates/rspack_core/src/compilation/chunk_ids/mod.rs create mode 100644 crates/rspack_core/src/compilation/code_generation/mod.rs create mode 100644 crates/rspack_core/src/compilation/create_chunk_assets/mod.rs create mode 100644 crates/rspack_core/src/compilation/create_hash/mod.rs create mode 100644 crates/rspack_core/src/compilation/create_module_assets/mod.rs create mode 100644 crates/rspack_core/src/compilation/create_module_hashes/mod.rs create mode 100644 crates/rspack_core/src/compilation/finish_module/mod.rs create mode 100644 crates/rspack_core/src/compilation/module_ids/mod.rs create mode 100644 crates/rspack_core/src/compilation/optimize_chunk_modules/mod.rs create mode 100644 crates/rspack_core/src/compilation/optimize_chunks/mod.rs create mode 100644 crates/rspack_core/src/compilation/optimize_code_generation/mod.rs create mode 100644 crates/rspack_core/src/compilation/optimize_dependencies/mod.rs create mode 100644 crates/rspack_core/src/compilation/optimize_modules/mod.rs create mode 100644 crates/rspack_core/src/compilation/optimize_tree/mod.rs create mode 100644 crates/rspack_core/src/compilation/process_assets/mod.rs create mode 100644 crates/rspack_core/src/compilation/rspack_passes.md create mode 100644 crates/rspack_core/src/compilation/run_passes.rs create mode 100644 crates/rspack_core/src/compilation/runtime_requirements/mod.rs diff --git a/crates/rspack_core/src/compilation/after_seal/mod.rs b/crates/rspack_core/src/compilation/after_seal/mod.rs new file mode 100644 index 000000000000..fdda5bdb2163 --- /dev/null +++ b/crates/rspack_core/src/compilation/after_seal/mod.rs @@ -0,0 +1,20 @@ +use super::*; +use crate::logger::Logger; + +pub async fn after_seal_pass( + compilation: &mut Compilation, + plugin_driver: SharedPluginDriver, +) -> Result<()> { + let logger = compilation.get_logger("rspack.Compilation"); + let start = logger.time("after seal"); + compilation.after_seal(plugin_driver).await?; + logger.time_end(start); + Ok(()) +} + +impl Compilation { + #[instrument("Compilation:after_seal", target=TRACING_BENCH_TARGET,skip_all)] + async fn after_seal(&mut self, plugin_driver: SharedPluginDriver) -> Result<()> { + plugin_driver.compilation_hooks.after_seal.call(self).await + } +} diff --git a/crates/rspack_core/src/compilation/assign_runtime_ids/mod.rs b/crates/rspack_core/src/compilation/assign_runtime_ids/mod.rs new file mode 100644 index 000000000000..19f63e10730c --- /dev/null +++ b/crates/rspack_core/src/compilation/assign_runtime_ids/mod.rs @@ -0,0 +1,42 @@ +use super::*; + +pub fn assign_runtime_ids(compilation: &mut Compilation) { + fn process_entrypoint( + entrypoint_ukey: &ChunkGroupUkey, + chunk_group_by_ukey: &ChunkGroupByUkey, + chunk_by_ukey: &ChunkByUkey, + chunk_graph: &mut ChunkGraph, + ) { + let entrypoint = chunk_group_by_ukey.expect_get(entrypoint_ukey); + let runtime = entrypoint + .kind + .get_entry_options() + .and_then(|o| match &o.runtime { + Some(EntryRuntime::String(s)) => Some(s.to_owned()), + _ => None, + }) + .or(entrypoint.name().map(|n| n.to_string())); + if let (Some(runtime), Some(chunk)) = ( + runtime, + chunk_by_ukey.get(&entrypoint.get_runtime_chunk(chunk_group_by_ukey)), + ) { + chunk_graph.set_runtime_id(runtime, chunk.id().map(|id| id.to_string())); + } + } + for i in compilation.entrypoints.iter() { + process_entrypoint( + i.1, + &compilation.chunk_group_by_ukey, + &compilation.chunk_by_ukey, + &mut compilation.chunk_graph, + ) + } + for i in compilation.async_entrypoints.iter() { + process_entrypoint( + i, + &compilation.chunk_group_by_ukey, + &compilation.chunk_by_ukey, + &mut compilation.chunk_graph, + ) + } +} diff --git a/crates/rspack_core/src/compilation/build_chunk_graph/mod.rs b/crates/rspack_core/src/compilation/build_chunk_graph/mod.rs index a2a60e24b443..e64652e1f4e7 100644 --- a/crates/rspack_core/src/compilation/build_chunk_graph/mod.rs +++ b/crates/rspack_core/src/compilation/build_chunk_graph/mod.rs @@ -7,6 +7,7 @@ use crate::{Compilation, incremental::IncrementalPasses}; pub(crate) mod artifact; pub(crate) mod code_splitter; pub(crate) mod incremental; +pub(crate) mod pass; #[instrument("Compilation:build_chunk_graph", skip_all)] pub fn build_chunk_graph(compilation: &mut Compilation) -> rspack_error::Result<()> { diff --git a/crates/rspack_core/src/compilation/build_chunk_graph/pass.rs b/crates/rspack_core/src/compilation/build_chunk_graph/pass.rs new file mode 100644 index 000000000000..f6a5380e1368 --- /dev/null +++ b/crates/rspack_core/src/compilation/build_chunk_graph/pass.rs @@ -0,0 +1,26 @@ +use rspack_error::Result; + +use crate::{ + compilation::{ + Compilation, + build_chunk_graph::{artifact::use_code_splitting_cache, build_chunk_graph}, + }, + logger::Logger, +}; + +pub async fn build_chunk_graph_pass(compilation: &mut Compilation) -> Result<()> { + let logger = compilation.get_logger("rspack.Compilation"); + compilation.module_graph_cache_artifact.freeze(); + use_code_splitting_cache(compilation, |compilation| async { + let start = logger.time("rebuild chunk graph"); + build_chunk_graph(compilation)?; + compilation + .chunk_graph + .generate_dot(compilation, "after-code-splitting") + .await; + logger.time_end(start); + Ok(compilation) + }) + .await?; + Ok(()) +} diff --git a/crates/rspack_core/src/compilation/chunk_ids/mod.rs b/crates/rspack_core/src/compilation/chunk_ids/mod.rs new file mode 100644 index 000000000000..900093978765 --- /dev/null +++ b/crates/rspack_core/src/compilation/chunk_ids/mod.rs @@ -0,0 +1,38 @@ +use super::*; +use crate::logger::Logger; + +pub async fn chunk_ids_pass( + compilation: &mut Compilation, + plugin_driver: SharedPluginDriver, +) -> Result<()> { + let logger = compilation.get_logger("rspack.Compilation"); + let start = logger.time("chunk ids"); + + // Check if CHUNK_IDS pass is disabled, and clear artifact if needed + if !compilation + .incremental + .passes_enabled(IncrementalPasses::CHUNK_IDS) + { + compilation.named_chunk_ids_artifact.clear(); + } + + let mut diagnostics = vec![]; + let mut chunk_by_ukey = mem::take(&mut compilation.chunk_by_ukey); + let mut named_chunk_ids_artifact = mem::take(&mut compilation.named_chunk_ids_artifact); + plugin_driver + .compilation_hooks + .chunk_ids + .call( + compilation, + &mut chunk_by_ukey, + &mut named_chunk_ids_artifact, + &mut diagnostics, + ) + .await + .map_err(|e| e.wrap_err("caused by plugins in Compilation.hooks.chunkIds"))?; + compilation.chunk_by_ukey = chunk_by_ukey; + compilation.named_chunk_ids_artifact = named_chunk_ids_artifact; + compilation.extend_diagnostics(diagnostics); + logger.time_end(start); + Ok(()) +} diff --git a/crates/rspack_core/src/compilation/code_generation/mod.rs b/crates/rspack_core/src/compilation/code_generation/mod.rs new file mode 100644 index 000000000000..cc8922cf06be --- /dev/null +++ b/crates/rspack_core/src/compilation/code_generation/mod.rs @@ -0,0 +1,208 @@ +use super::*; +use crate::logger::Logger; + +pub async fn code_generation_pass( + compilation: &mut Compilation, + plugin_driver: SharedPluginDriver, +) -> Result<()> { + let logger = compilation.get_logger("rspack.Compilation"); + let start = logger.time("code generation"); + let code_generation_modules = if let Some(mutations) = compilation + .incremental + .mutations_read(IncrementalPasses::MODULES_CODEGEN) + && !compilation.code_generation_results.is_empty() + { + let revoked_modules = mutations.iter().filter_map(|mutation| match mutation { + Mutation::ModuleRemove { module } => Some(*module), + _ => None, + }); + for revoked_module in revoked_modules { + compilation.code_generation_results.remove(&revoked_module); + } + let modules: IdentifierSet = mutations + .iter() + .filter_map(|mutation| match mutation { + Mutation::ModuleSetHashes { module } => Some(*module), + _ => None, + }) + .collect(); + // also cleanup for updated modules, for `insert(); insert();` the second insert() won't override the first insert() on code_generation_results + for module in &modules { + compilation.code_generation_results.remove(module); + } + tracing::debug!(target: incremental::TRACING_TARGET, passes = %IncrementalPasses::MODULES_CODEGEN, %mutations); + let logger = compilation.get_logger("rspack.incremental.modulesCodegen"); + logger.log(format!( + "{} modules are affected, {} in total", + modules.len(), + compilation.get_module_graph().modules().len() + )); + modules + } else { + compilation.code_generation_results = Default::default(); + compilation + .get_module_graph() + .modules() + .keys() + .copied() + .collect() + }; + compilation.code_generation(code_generation_modules).await?; + + let mut diagnostics = vec![]; + plugin_driver + .compilation_hooks + .after_code_generation + .call(compilation, &mut diagnostics) + .await + .map_err(|e| e.wrap_err("caused by plugins in Compilation.hooks.afterCodeGeneration"))?; + compilation.extend_diagnostics(diagnostics); + + logger.time_end(start); + Ok(()) +} + +impl Compilation { + #[instrument("Compilation:code_generation",target=TRACING_BENCH_TARGET, skip_all)] + async fn code_generation(&mut self, modules: IdentifierSet) -> Result<()> { + let logger = self.get_logger("rspack.Compilation"); + let mut codegen_cache_counter = match self.options.cache { + CacheOptions::Disabled => None, + _ => Some(logger.cache("module code generation cache")), + }; + + let module_graph = self.get_module_graph(); + let mut no_codegen_dependencies_modules = IdentifierSet::default(); + let mut has_codegen_dependencies_modules = IdentifierSet::default(); + for module_identifier in modules { + let module = module_graph + .module_by_identifier(&module_identifier) + .expect("should have module"); + if module.get_code_generation_dependencies().is_none() { + no_codegen_dependencies_modules.insert(module_identifier); + } else { + has_codegen_dependencies_modules.insert(module_identifier); + } + } + + self + .code_generation_modules(&mut codegen_cache_counter, no_codegen_dependencies_modules) + .await?; + self + .code_generation_modules(&mut codegen_cache_counter, has_codegen_dependencies_modules) + .await?; + + if let Some(counter) = codegen_cache_counter { + logger.cache_end(counter); + } + + Ok(()) + } + + pub(crate) async fn code_generation_modules( + &mut self, + cache_counter: &mut Option, + modules: IdentifierSet, + ) -> Result<()> { + let chunk_graph = &self.chunk_graph; + let module_graph = self.get_module_graph(); + let mut jobs = Vec::new(); + for module in modules { + let mut map: HashMap = HashMap::default(); + for runtime in chunk_graph.get_module_runtimes_iter(module, &self.chunk_by_ukey) { + let hash = ChunkGraph::get_module_hash(self, module, runtime) + .expect("should have cgm.hash in code generation"); + let scope = self + .plugin_driver + .compilation_hooks + .concatenation_scope + .call(self, module) + .await?; + if let Some(job) = map.get_mut(hash) { + job.runtimes.push(runtime.clone()); + } else { + map.insert( + hash.clone(), + CodeGenerationJob { + module, + hash: hash.clone(), + runtime: runtime.clone(), + runtimes: vec![runtime.clone()], + scope, + }, + ); + } + } + jobs.extend(map.into_values()); + } + + let results = rspack_futures::scope::<_, _>(|token| { + jobs.into_iter().for_each(|job| { + // SAFETY: await immediately and trust caller to poll future entirely + let s = unsafe { token.used((&self, &module_graph, job)) }; + + s.spawn(|(this, module_graph, job)| async { + let options = &this.options; + let old_cache = &this.old_cache; + + let module = module_graph + .module_by_identifier(&job.module) + .expect("should have module"); + let codegen_res = old_cache + .code_generate_occasion + .use_cache(&job, || async { + module + .code_generation(this, Some(&job.runtime), job.scope.clone()) + .await + .map(|mut codegen_res| { + codegen_res.set_hash( + &options.output.hash_function, + &options.output.hash_digest, + &options.output.hash_salt, + ); + codegen_res + }) + }) + .await; + + (job.module, job.runtimes, codegen_res) + }) + }) + }) + .await; + let results = results + .into_iter() + .map(|res| res.to_rspack_result()) + .collect::>>()?; + + for (module, runtimes, (codegen_res, from_cache)) in results { + if let Some(counter) = cache_counter { + if from_cache { + counter.hit(); + } else { + counter.miss(); + } + } + let codegen_res = match codegen_res { + Ok(codegen_res) => codegen_res, + Err(err) => { + let mut diagnostic = Diagnostic::from(err); + diagnostic.module_identifier = Some(module); + self.push_diagnostic(diagnostic); + let mut codegen_res = CodeGenerationResult::default(); + codegen_res.set_hash( + &self.options.output.hash_function, + &self.options.output.hash_digest, + &self.options.output.hash_salt, + ); + codegen_res + } + }; + self + .code_generation_results + .insert(module, codegen_res, runtimes); + self.code_generated_modules.insert(module); + } + Ok(()) + } +} diff --git a/crates/rspack_core/src/compilation/create_chunk_assets/mod.rs b/crates/rspack_core/src/compilation/create_chunk_assets/mod.rs new file mode 100644 index 000000000000..d26ec44ff4b4 --- /dev/null +++ b/crates/rspack_core/src/compilation/create_chunk_assets/mod.rs @@ -0,0 +1,171 @@ +use super::*; +use crate::logger::Logger; + +pub async fn create_chunk_assets_pass( + compilation: &mut Compilation, + plugin_driver: SharedPluginDriver, +) -> Result<()> { + let logger = compilation.get_logger("rspack.Compilation"); + let start = logger.time("create chunk assets"); + compilation.create_chunk_assets(plugin_driver).await?; + logger.time_end(start); + Ok(()) +} + +impl Compilation { + #[instrument("Compilation::create_chunk_assets",target=TRACING_BENCH_TARGET, skip_all)] + async fn create_chunk_assets(&mut self, plugin_driver: SharedPluginDriver) -> Result<()> { + if (self.options.output.filename.has_hash_placeholder() + || self.options.output.chunk_filename.has_hash_placeholder() + || self.options.output.css_filename.has_hash_placeholder() + || self + .options + .output + .css_chunk_filename + .has_hash_placeholder()) + && let Some(diagnostic) = self.incremental.disable_passes( + IncrementalPasses::CHUNKS_RENDER, + "Chunk filename that dependent on full hash", + "chunk filename that dependent on full hash is not supported in incremental compilation", + ) + && let Some(diagnostic) = diagnostic + { + self.push_diagnostic(diagnostic); + } + + // Check if CHUNKS_RENDER pass is disabled, and clear artifact if needed + if !self + .incremental + .passes_enabled(IncrementalPasses::CHUNKS_RENDER) + { + self.chunk_render_artifact.clear(); + } + + let chunks = if let Some(mutations) = self + .incremental + .mutations_read(IncrementalPasses::CHUNKS_RENDER) + && !self.chunk_render_artifact.is_empty() + { + let removed_chunks = mutations.iter().filter_map(|mutation| match mutation { + Mutation::ChunkRemove { chunk } => Some(*chunk), + _ => None, + }); + for removed_chunk in removed_chunks { + self.chunk_render_artifact.remove(&removed_chunk); + } + self + .chunk_render_artifact + .retain(|chunk, _| self.chunk_by_ukey.contains(chunk)); + let chunks: UkeySet = mutations + .iter() + .filter_map(|mutation| match mutation { + Mutation::ChunkSetHashes { chunk } => Some(*chunk), + _ => None, + }) + .collect(); + tracing::debug!(target: incremental::TRACING_TARGET, passes = %IncrementalPasses::CHUNKS_RENDER, %mutations); + let logger = self.get_logger("rspack.incremental.chunksRender"); + logger.log(format!( + "{} chunks are affected, {} in total", + chunks.len(), + self.chunk_by_ukey.len() + )); + chunks + } else { + self.chunk_by_ukey.keys().copied().collect() + }; + let results = rspack_futures::scope::<_, Result<_>>(|token| { + chunks.iter().for_each(|chunk| { + // SAFETY: await immediately and trust caller to poll future entirely + let s = unsafe { token.used((&self, &plugin_driver, chunk)) }; + + s.spawn(|(this, plugin_driver, chunk)| async { + let mut manifests = Vec::new(); + let mut diagnostics = Vec::new(); + plugin_driver + .compilation_hooks + .render_manifest + .call(this, chunk, &mut manifests, &mut diagnostics) + .await?; + + rspack_error::Result::Ok(( + *chunk, + ChunkRenderResult { + manifests, + diagnostics, + }, + )) + }); + }) + }) + .await; + + let mut chunk_render_results: UkeyMap = Default::default(); + for result in results { + let item = result.to_rspack_result()?; + let (key, value) = item?; + chunk_render_results.insert(key, value); + } + let chunk_ukey_and_manifest = if self + .incremental + .passes_enabled(IncrementalPasses::CHUNKS_RENDER) + { + self.chunk_render_artifact.extend(chunk_render_results); + self.chunk_render_artifact.clone() + } else { + chunk_render_results + }; + + for ( + chunk_ukey, + ChunkRenderResult { + manifests, + diagnostics, + }, + ) in chunk_ukey_and_manifest + { + self.extend_diagnostics(diagnostics); + + for file_manifest in manifests { + let filename = file_manifest.filename; + let current_chunk = self.chunk_by_ukey.expect_get_mut(&chunk_ukey); + + current_chunk.set_rendered(true); + if file_manifest.auxiliary { + current_chunk.add_auxiliary_file(filename.clone()); + } else { + current_chunk.add_file(filename.clone()); + } + + self.emit_asset( + filename.clone(), + CompilationAsset::new(Some(file_manifest.source), file_manifest.info), + ); + + _ = self + .chunk_asset(chunk_ukey, &filename, plugin_driver.clone()) + .await; + } + } + + Ok(()) + } + + // #[instrument( + // name = "Compilation:chunk_asset", + // skip(self, plugin_driver, chunk_ukey) + // )] + async fn chunk_asset( + &self, + chunk_ukey: ChunkUkey, + filename: &str, + plugin_driver: SharedPluginDriver, + ) -> Result<()> { + plugin_driver + .compilation_hooks + .chunk_asset + .call(self, &chunk_ukey, filename) + .await?; + Ok(()) + } +} diff --git a/crates/rspack_core/src/compilation/create_hash/mod.rs b/crates/rspack_core/src/compilation/create_hash/mod.rs new file mode 100644 index 000000000000..25ab646b16d4 --- /dev/null +++ b/crates/rspack_core/src/compilation/create_hash/mod.rs @@ -0,0 +1,452 @@ +use super::*; +use crate::logger::Logger; + +pub struct ChunkHashResult { + pub hash: RspackHashDigest, + pub content_hash: ChunkContentHash, +} + +pub async fn create_hash_pass( + compilation: &mut Compilation, + plugin_driver: SharedPluginDriver, +) -> Result<()> { + let logger = compilation.get_logger("rspack.Compilation"); + let start = logger.time("hashing"); + compilation.create_hash(plugin_driver).await?; + compilation.runtime_modules_code_generation().await?; + logger.time_end(start); + Ok(()) +} + +impl Compilation { + #[instrument(name = "Compilation:create_hash",target=TRACING_BENCH_TARGET, skip_all)] + pub async fn create_hash(&mut self, plugin_driver: SharedPluginDriver) -> Result<()> { + let logger = self.get_logger("rspack.Compilation"); + + // Check if there are any chunks that depend on full hash, usually only runtime chunks are + // possible to depend on full hash, but for library type commonjs/module, it's possible to + // have non-runtime chunks depend on full hash, the library format plugin is using + // dependent_full_hash hook to declare it. + let mut full_hash_chunks = UkeySet::default(); + for chunk_ukey in self.chunk_by_ukey.keys() { + let chunk_dependent_full_hash = plugin_driver + .compilation_hooks + .dependent_full_hash + .call(self, chunk_ukey) + .await? + .unwrap_or_default(); + if chunk_dependent_full_hash { + full_hash_chunks.insert(*chunk_ukey); + } + } + if !full_hash_chunks.is_empty() + && let Some(diagnostic) = self.incremental.disable_passes( + IncrementalPasses::CHUNKS_HASHES, + "Chunk content that dependent on full hash", + "it requires calculating the hashes of all the chunks, which is a global effect", + ) + && let Some(diagnostic) = diagnostic + { + self.push_diagnostic(diagnostic); + } + if !self + .incremental + .passes_enabled(IncrementalPasses::CHUNKS_HASHES) + { + self.chunk_hashes_artifact.clear(); + } + + let create_hash_chunks = if let Some(mutations) = self + .incremental + .mutations_read(IncrementalPasses::CHUNKS_HASHES) + && !self.chunk_hashes_artifact.is_empty() + { + let removed_chunks = mutations.iter().filter_map(|mutation| match mutation { + Mutation::ChunkRemove { chunk } => Some(*chunk), + _ => None, + }); + for removed_chunk in removed_chunks { + self.chunk_hashes_artifact.remove(&removed_chunk); + } + self + .chunk_hashes_artifact + .retain(|chunk, _| self.chunk_by_ukey.contains(chunk)); + let chunks = mutations.get_affected_chunks_with_chunk_graph(self); + tracing::debug!(target: incremental::TRACING_TARGET, passes = %IncrementalPasses::CHUNKS_HASHES, %mutations, ?chunks); + let logger = self.get_logger("rspack.incremental.chunksHashes"); + logger.log(format!( + "{} chunks are affected, {} in total", + chunks.len(), + self.chunk_by_ukey.len(), + )); + chunks + } else { + self.chunk_by_ukey.keys().copied().collect() + }; + + let mut compilation_hasher = RspackHash::from(&self.options.output); + + fn try_process_chunk_hash_results( + compilation: &mut Compilation, + chunk_hash_results: Vec>, + ) -> Result<()> { + for hash_result in chunk_hash_results { + let (chunk_ukey, chunk_hash_result) = hash_result?; + let chunk = compilation.chunk_by_ukey.expect_get(&chunk_ukey); + let chunk_hashes_changed = chunk.set_hashes( + &mut compilation.chunk_hashes_artifact, + chunk_hash_result.hash, + chunk_hash_result.content_hash, + ); + if chunk_hashes_changed + && let Some(mut mutations) = compilation.incremental.mutations_write() + { + mutations.add(Mutation::ChunkSetHashes { chunk: chunk_ukey }); + } + } + Ok(()) + } + + let unordered_runtime_chunks: UkeySet = self.get_chunk_graph_entries().collect(); + let start = logger.time("hashing: hash chunks"); + let other_chunks: Vec<_> = create_hash_chunks + .iter() + .filter(|key| !unordered_runtime_chunks.contains(key)) + .collect(); + + // create hash for runtime modules in other chunks + let other_chunk_runtime_module_hashes = rspack_futures::scope::<_, Result<_>>(|token| { + other_chunks + .iter() + .flat_map(|chunk| self.chunk_graph.get_chunk_runtime_modules_iterable(chunk)) + .for_each(|runtime_module_identifier| { + let s = unsafe { token.used((&self, runtime_module_identifier)) }; + s.spawn(|(compilation, runtime_module_identifier)| async { + let runtime_module = &compilation.runtime_modules[runtime_module_identifier]; + let digest = runtime_module.get_runtime_hash(compilation, None).await?; + Ok((*runtime_module_identifier, digest)) + }); + }) + }) + .await + .into_iter() + .map(|res| res.to_rspack_result()) + .collect::>>()?; + + for res in other_chunk_runtime_module_hashes { + let (runtime_module_identifier, digest) = res?; + self + .runtime_modules_hash + .insert(runtime_module_identifier, digest); + } + + // create hash for other chunks + let other_chunks_hash_results = rspack_futures::scope::<_, Result<_>>(|token| { + for chunk in other_chunks { + let s = unsafe { token.used((&self, chunk, &plugin_driver)) }; + s.spawn(|(compilation, chunk, plugin_driver)| async { + let hash_result = compilation + .process_chunk_hash(*chunk, plugin_driver) + .await?; + Ok((*chunk, hash_result)) + }); + } + }) + .await + .into_iter() + .map(|res| res.to_rspack_result()) + .collect::>>()?; + + try_process_chunk_hash_results(self, other_chunks_hash_results)?; + logger.time_end(start); + + // collect references for runtime chunks + let mut runtime_chunks_map: HashMap, u32)> = + unordered_runtime_chunks + .into_iter() + .map(|runtime_chunk| (runtime_chunk, (Vec::new(), 0))) + .collect(); + let mut remaining: u32 = 0; + for runtime_chunk_ukey in runtime_chunks_map.keys().copied().collect::>() { + let runtime_chunk = self.chunk_by_ukey.expect_get(&runtime_chunk_ukey); + let groups = runtime_chunk.get_all_referenced_async_entrypoints(&self.chunk_group_by_ukey); + for other in groups + .into_iter() + .map(|group| self.chunk_group_by_ukey.expect_get(&group)) + .map(|group| group.get_runtime_chunk(&self.chunk_group_by_ukey)) + { + let (other_referenced_by, _) = runtime_chunks_map + .get_mut(&other) + .expect("should in runtime_chunks_map"); + other_referenced_by.push(runtime_chunk_ukey); + let info = runtime_chunks_map + .get_mut(&runtime_chunk_ukey) + .expect("should in runtime_chunks_map"); + info.1 += 1; + remaining += 1; + } + } + // sort runtime chunks by its references + let mut runtime_chunks = Vec::with_capacity(runtime_chunks_map.len()); + for (runtime_chunk, (_, remaining)) in &runtime_chunks_map { + if *remaining == 0 { + runtime_chunks.push(*runtime_chunk); + } + } + let mut ready_chunks = Vec::new(); + + let mut i = 0; + while i < runtime_chunks.len() { + let chunk_ukey = runtime_chunks[i]; + let has_full_hash_modules = full_hash_chunks.contains(&chunk_ukey) + || self + .chunk_graph + .has_chunk_full_hash_modules(&chunk_ukey, &self.runtime_modules); + if has_full_hash_modules { + full_hash_chunks.insert(chunk_ukey); + } + let referenced_by = runtime_chunks_map + .get(&chunk_ukey) + .expect("should in runtime_chunks_map") + .0 + .clone(); + for other in referenced_by { + if has_full_hash_modules { + for runtime_module in self.chunk_graph.get_chunk_runtime_modules_iterable(&other) { + let runtime_module = self + .runtime_modules + .get(runtime_module) + .expect("should have runtime_module"); + if runtime_module.dependent_hash() { + full_hash_chunks.insert(other); + break; + } + } + } + remaining -= 1; + let (_, other_remaining) = runtime_chunks_map + .get_mut(&other) + .expect("should in runtime_chunks_map"); + *other_remaining -= 1; + if *other_remaining == 0 { + ready_chunks.push(other); + } + } + if !ready_chunks.is_empty() { + runtime_chunks.append(&mut ready_chunks); + } + i += 1; + } + // create warning for remaining circular references + if remaining > 0 { + let mut circular: Vec<_> = runtime_chunks_map + .iter() + .filter(|(_, (_, remaining))| *remaining != 0) + .map(|(chunk_ukey, _)| self.chunk_by_ukey.expect_get(chunk_ukey)) + .collect(); + circular.sort_unstable_by(|a, b| a.id().cmp(&b.id())); + runtime_chunks.extend(circular.iter().map(|chunk| chunk.ukey())); + let circular_names = circular + .iter() + .map(|chunk| { + chunk + .name() + .or(chunk.id().map(|id| id.as_str())) + .unwrap_or("no id chunk") + }) + .join(", "); + let error = rspack_error::Error::warning(format!( + "Circular dependency between chunks with runtime ({circular_names})\nThis prevents using hashes of each other and should be avoided." + )); + self.push_diagnostic(error.into()); + } + + // create hash for runtime chunks and the runtime modules within them + // The subsequent runtime chunks and runtime modules will depend on + // the hash results of the previous runtime chunks and runtime modules. + // Therefore, create hashes one by one in sequence. + let start = logger.time("hashing: hash runtime chunks"); + for runtime_chunk_ukey in runtime_chunks { + let runtime_module_hashes = rspack_futures::scope::<_, Result<_>>(|token| { + self + .chunk_graph + .get_chunk_runtime_modules_iterable(&runtime_chunk_ukey) + .for_each(|runtime_module_identifier| { + let s = unsafe { token.used((&self, runtime_module_identifier)) }; + s.spawn(|(compilation, runtime_module_identifier)| async { + let runtime_module = &compilation.runtime_modules[runtime_module_identifier]; + let digest = runtime_module.get_runtime_hash(compilation, None).await?; + Ok((*runtime_module_identifier, digest)) + }); + }) + }) + .await + .into_iter() + .map(|res| res.to_rspack_result()) + .collect::>>()?; + + for res in runtime_module_hashes { + let (mid, digest) = res?; + self.runtime_modules_hash.insert(mid, digest); + } + + let chunk_hash_result = self + .process_chunk_hash(runtime_chunk_ukey, &plugin_driver) + .await?; + let chunk = self.chunk_by_ukey.expect_get(&runtime_chunk_ukey); + let chunk_hashes_changed = chunk.set_hashes( + &mut self.chunk_hashes_artifact, + chunk_hash_result.hash, + chunk_hash_result.content_hash, + ); + if chunk_hashes_changed && let Some(mut mutations) = self.incremental.mutations_write() { + mutations.add(Mutation::ChunkSetHashes { + chunk: runtime_chunk_ukey, + }); + } + } + logger.time_end(start); + + // create full hash + self + .chunk_by_ukey + .values() + .sorted_unstable_by_key(|chunk| chunk.ukey()) + .filter_map(|chunk| chunk.hash(&self.chunk_hashes_artifact)) + .for_each(|hash| { + hash.hash(&mut compilation_hasher); + }); + self.hot_index.hash(&mut compilation_hasher); + self.hash = Some(compilation_hasher.digest(&self.options.output.hash_digest)); + + // re-create runtime chunk hash that depend on full hash + let start = logger.time("hashing: process full hash chunks"); + for chunk_ukey in full_hash_chunks { + for runtime_module_identifier in self + .chunk_graph + .get_chunk_runtime_modules_iterable(&chunk_ukey) + { + let runtime_module = &self.runtime_modules[runtime_module_identifier]; + if runtime_module.full_hash() || runtime_module.dependent_hash() { + let digest = runtime_module.get_runtime_hash(self, None).await?; + self + .runtime_modules_hash + .insert(*runtime_module_identifier, digest); + } + } + let chunk = self.chunk_by_ukey.expect_get(&chunk_ukey); + let new_chunk_hash = { + let chunk_hash = chunk + .hash(&self.chunk_hashes_artifact) + .expect("should have chunk hash"); + let mut hasher = RspackHash::from(&self.options.output); + chunk_hash.hash(&mut hasher); + self.hash.hash(&mut hasher); + hasher.digest(&self.options.output.hash_digest) + }; + let new_content_hash = { + let content_hash = chunk + .content_hash(&self.chunk_hashes_artifact) + .expect("should have content hash"); + content_hash + .iter() + .map(|(source_type, content_hash)| { + let mut hasher = RspackHash::from(&self.options.output); + content_hash.hash(&mut hasher); + self.hash.hash(&mut hasher); + ( + *source_type, + hasher.digest(&self.options.output.hash_digest), + ) + }) + .collect() + }; + let chunk_hashes_changed = chunk.set_hashes( + &mut self.chunk_hashes_artifact, + new_chunk_hash, + new_content_hash, + ); + if chunk_hashes_changed && let Some(mut mutations) = self.incremental.mutations_write() { + mutations.add(Mutation::ChunkSetHashes { chunk: chunk_ukey }); + } + } + logger.time_end(start); + Ok(()) + } + + #[instrument(skip_all)] + pub async fn runtime_modules_code_generation(&mut self) -> Result<()> { + let results = rspack_futures::scope::<_, Result<_>>(|token| { + self + .runtime_modules + .iter() + .for_each(|(runtime_module_identifier, runtime_module)| { + let s = unsafe { token.used((&self, runtime_module_identifier, runtime_module)) }; + s.spawn( + |(compilation, runtime_module_identifier, runtime_module)| async { + let result = runtime_module + .code_generation(compilation, None, None) + .await?; + let source = result + .get(&SourceType::Runtime) + .expect("should have source"); + Ok((*runtime_module_identifier, source.clone())) + }, + ) + }) + }) + .await + .into_iter() + .map(|res| res.to_rspack_result()) + .collect::>>()?; + + let mut runtime_module_sources = IdentifierMap::::default(); + for result in results { + let (runtime_module_identifier, source) = result?; + runtime_module_sources.insert(runtime_module_identifier, source); + } + + self.runtime_modules_code_generation_source = runtime_module_sources; + self + .code_generated_modules + .extend(self.runtime_modules.keys().copied()); + Ok(()) + } + + async fn process_chunk_hash( + &self, + chunk_ukey: ChunkUkey, + plugin_driver: &SharedPluginDriver, + ) -> Result { + let mut hasher = RspackHash::from(&self.options.output); + if let Some(chunk) = self.chunk_by_ukey.get(&chunk_ukey) { + chunk.update_hash(&mut hasher, self); + } + plugin_driver + .compilation_hooks + .chunk_hash + .call(self, &chunk_ukey, &mut hasher) + .await?; + let chunk_hash = hasher.digest(&self.options.output.hash_digest); + + let mut content_hashes: HashMap = HashMap::default(); + plugin_driver + .compilation_hooks + .content_hash + .call(self, &chunk_ukey, &mut content_hashes) + .await?; + + let content_hashes = content_hashes + .into_iter() + .map(|(t, mut hasher)| { + chunk_hash.hash(&mut hasher); + (t, hasher.digest(&self.options.output.hash_digest)) + }) + .collect(); + + Ok(ChunkHashResult { + hash: chunk_hash, + content_hash: content_hashes, + }) + } +} diff --git a/crates/rspack_core/src/compilation/create_module_assets/mod.rs b/crates/rspack_core/src/compilation/create_module_assets/mod.rs new file mode 100644 index 000000000000..1d029caa1138 --- /dev/null +++ b/crates/rspack_core/src/compilation/create_module_assets/mod.rs @@ -0,0 +1,53 @@ +use super::*; +use crate::logger::Logger; + +pub async fn create_module_assets_pass( + compilation: &mut Compilation, + plugin_driver: SharedPluginDriver, +) -> Result<()> { + let logger = compilation.get_logger("rspack.Compilation"); + let start = logger.time("create module assets"); + compilation.create_module_assets(plugin_driver).await; + logger.time_end(start); + Ok(()) +} + +impl Compilation { + #[instrument("Compilation:create_module_assets",target=TRACING_BENCH_TARGET, skip_all)] + async fn create_module_assets(&mut self, _plugin_driver: SharedPluginDriver) { + let mut chunk_asset_map = vec![]; + let mut module_assets = vec![]; + let mg = self.get_module_graph(); + for (identifier, module) in mg.modules() { + let assets = &module.build_info().assets; + if assets.is_empty() { + continue; + } + + for (name, asset) in assets.as_ref() { + module_assets.push((name.clone(), asset.clone())); + } + // assets of executed modules are not in this compilation + if self + .chunk_graph + .chunk_graph_module_by_module_identifier + .contains_key(&identifier) + { + for chunk in self.chunk_graph.get_module_chunks(identifier).iter() { + for name in assets.keys() { + chunk_asset_map.push((*chunk, name.clone())) + } + } + } + } + + for (name, asset) in module_assets { + self.emit_asset(name, asset); + } + + for (chunk, asset_name) in chunk_asset_map { + let chunk = self.chunk_by_ukey.expect_get_mut(&chunk); + chunk.add_auxiliary_file(asset_name); + } + } +} diff --git a/crates/rspack_core/src/compilation/create_module_hashes/mod.rs b/crates/rspack_core/src/compilation/create_module_hashes/mod.rs new file mode 100644 index 000000000000..282833f8cbb1 --- /dev/null +++ b/crates/rspack_core/src/compilation/create_module_hashes/mod.rs @@ -0,0 +1,141 @@ +use super::*; +use crate::logger::Logger; + +pub async fn create_module_hashes_pass(compilation: &mut Compilation) -> Result<()> { + // Check if MODULES_HASHES pass is disabled, and clear artifact if needed + if !compilation + .incremental + .passes_enabled(IncrementalPasses::MODULES_HASHES) + { + compilation.cgm_hash_artifact.clear(); + } + + let create_module_hashes_modules = if let Some(mutations) = compilation + .incremental + .mutations_read(IncrementalPasses::MODULES_HASHES) + && !compilation.cgm_hash_artifact.is_empty() + { + let revoked_modules = mutations.iter().filter_map(|mutation| match mutation { + Mutation::ModuleRemove { module } => Some(*module), + _ => None, + }); + for revoked_module in revoked_modules { + compilation.cgm_hash_artifact.remove(&revoked_module); + } + let mut modules = mutations.get_affected_modules_with_chunk_graph(compilation); + + // check if module runtime changes + let mg = compilation.get_module_graph(); + for mi in mg.modules().keys() { + let module_runtimes = compilation + .chunk_graph + .get_module_runtimes(*mi, &compilation.chunk_by_ukey); + let module_runtime_keys = module_runtimes + .values() + .map(get_runtime_key) + .collect::>(); + + if let Some(runtime_map) = compilation.cgm_hash_artifact.get_runtime_map(mi) { + if module_runtimes.is_empty() { + // module has no runtime, skip + continue; + } + if module_runtimes.len() == 1 { + // single runtime + if !matches!(runtime_map.mode, RuntimeMode::SingleEntry) + || runtime_map + .single_runtime + .as_ref() + .expect("should have single runtime for single entry") + != module_runtimes + .values() + .next() + .expect("should have at least one runtime") + { + modules.insert(*mi); + } + } else { + // multiple runtimes + if matches!(runtime_map.mode, RuntimeMode::SingleEntry) { + modules.insert(*mi); + continue; + } + + if runtime_map.map.len() != module_runtimes.len() { + modules.insert(*mi); + continue; + } + + for runtime_key in runtime_map.map.keys() { + if !module_runtime_keys.contains(runtime_key) { + modules.insert(*mi); + break; + } + } + } + } + } + + tracing::debug!(target: incremental::TRACING_TARGET, passes = %IncrementalPasses::MODULES_HASHES, %mutations, ?modules); + let logger = compilation.get_logger("rspack.incremental.modulesHashes"); + logger.log(format!( + "{} modules are affected, {} in total", + modules.len(), + mg.modules().len() + )); + + modules + } else { + compilation + .get_module_graph() + .modules() + .keys() + .copied() + .collect() + }; + compilation + .create_module_hashes(create_module_hashes_modules) + .await +} + +impl Compilation { + #[instrument("Compilation:create_module_hashes", skip_all)] + pub async fn create_module_hashes(&mut self, modules: IdentifierSet) -> Result<()> { + let mg = self.get_module_graph(); + let chunk_graph = &self.chunk_graph; + let chunk_by_ukey = &self.chunk_by_ukey; + + let results = rspack_futures::scope::<_, Result<_>>(|token| { + for module_identifier in modules { + let s = unsafe { token.used((&*self, &mg, chunk_graph, chunk_by_ukey)) }; + s.spawn( + move |(compilation, mg, chunk_graph, chunk_by_ukey)| async move { + let mut hashes = RuntimeSpecMap::new(); + let module = mg + .module_by_identifier(&module_identifier) + .expect("should have module"); + for runtime in chunk_graph.get_module_runtimes_iter(module_identifier, chunk_by_ukey) { + let hash = module.get_runtime_hash(compilation, Some(runtime)).await?; + hashes.set(runtime.clone(), hash); + } + Ok((module_identifier, hashes)) + }, + ); + } + }) + .await + .into_iter() + .map(|r| r.to_rspack_result()) + .collect::>>()?; + + for result in results { + let (module, hashes) = result?; + if ChunkGraph::set_module_hashes(self, module, hashes) + && let Some(mut mutations) = self.incremental.mutations_write() + { + mutations.add(Mutation::ModuleSetHashes { module }); + } + } + Ok(()) + } +} diff --git a/crates/rspack_core/src/compilation/finish_module/mod.rs b/crates/rspack_core/src/compilation/finish_module/mod.rs new file mode 100644 index 000000000000..23549acbc18b --- /dev/null +++ b/crates/rspack_core/src/compilation/finish_module/mod.rs @@ -0,0 +1,175 @@ +use super::*; +use crate::logger::Logger; + +impl Compilation { + #[instrument("Compilation:finish",target=TRACING_BENCH_TARGET, skip_all)] + pub async fn finish_build_module_graph(&mut self) -> Result<()> { + self.in_finish_make.store(false, Ordering::Release); + // clean up the entry deps + let make_artifact = self.build_module_graph_artifact.take(); + self + .build_module_graph_artifact + .replace(finish_build_module_graph(self, make_artifact).await?); + // sync assets to module graph from module_executor + if let Some(module_executor) = &mut self.module_executor { + let mut module_executor = std::mem::take(module_executor); + module_executor.hook_after_finish_modules(self).await?; + self.module_executor = Some(module_executor); + } + // make finished, make artifact should be readonly thereafter. + Ok(()) + } + + #[tracing::instrument("Compilation:collect_build_module_graph_effects", skip_all)] + pub async fn collect_build_module_graph_effects( + &mut self, + dependencies_diagnostics_artifact: &mut DependenciesDiagnosticsArtifact, + async_modules_artifact: &mut AsyncModulesArtifact, + ) -> Result> { + let logger = self.get_logger("rspack.Compilation"); + if let Some(mut mutations) = self.incremental.mutations_write() { + mutations.extend( + self + .build_module_graph_artifact + .affected_dependencies + .updated() + .iter() + .map(|&dependency| Mutation::DependencyUpdate { dependency }), + ); + mutations.extend( + self + .build_module_graph_artifact + .affected_modules + .removed() + .iter() + .map(|&module| Mutation::ModuleRemove { module }), + ); + mutations.extend( + self + .build_module_graph_artifact + .affected_modules + .updated() + .iter() + .map(|&module| Mutation::ModuleUpdate { module }), + ); + mutations.extend( + self + .build_module_graph_artifact + .affected_modules + .added() + .iter() + .map(|&module| Mutation::ModuleAdd { module }), + ); + tracing::debug!(target: incremental::TRACING_TARGET, passes = %IncrementalPasses::MAKE, %mutations); + } + + let start = logger.time("finish modules"); + // finish_modules means the module graph (modules, connections, dependencies) are + // frozen and start to optimize (provided exports, infer async, etc.) based on the + // module graph, so any kind of change that affect these should be done before the + // finish_modules + self + .plugin_driver + .clone() + .compilation_hooks + .finish_modules + .call(self, async_modules_artifact) + .await?; + + logger.time_end(start); + + // https://github.com/webpack/webpack/blob/19ca74127f7668aaf60d59f4af8fcaee7924541a/lib/Compilation.js#L2988 + self.module_graph_cache_artifact.freeze(); + // Collect dependencies diagnostics at here to make sure: + // 1. after finish_modules: has provide exports info + // 2. before optimize dependencies: side effects free module hasn't been skipped + let mut all_diagnostics = + self.collect_dependencies_diagnostics(dependencies_diagnostics_artifact); + self.module_graph_cache_artifact.unfreeze(); + + // take make diagnostics + let diagnostics = self.build_module_graph_artifact.diagnostics(); + all_diagnostics.extend(diagnostics); + Ok(all_diagnostics) + } + + #[tracing::instrument("Compilation:collect_dependencies_diagnostics", skip_all)] + fn collect_dependencies_diagnostics( + &self, + dependencies_diagnostics_artifact: &mut DependenciesDiagnosticsArtifact, + ) -> Vec { + // Compute modules while holding the lock, then release it + let (modules, has_mutations) = { + let mutations = self + .incremental + .mutations_read(IncrementalPasses::DEPENDENCIES_DIAGNOSTICS); + + // TODO move diagnostic collect to make + if let Some(mutations) = mutations { + if !dependencies_diagnostics_artifact.is_empty() { + let revoked_modules = mutations.iter().filter_map(|mutation| match mutation { + Mutation::ModuleRemove { module } => Some(*module), + _ => None, + }); + for revoked_module in revoked_modules { + dependencies_diagnostics_artifact.remove(&revoked_module); + } + let modules = mutations.get_affected_modules_with_module_graph(self.get_module_graph()); + let logger = self.get_logger("rspack.incremental.dependenciesDiagnostics"); + logger.log(format!( + "{} modules are affected, {} in total", + modules.len(), + self.get_module_graph().modules().len() + )); + (modules, true) + } else { + ( + self.get_module_graph().modules().keys().copied().collect(), + true, + ) + } + } else { + ( + self.get_module_graph().modules().keys().copied().collect(), + false, + ) + } + }; + + let module_graph = self.get_module_graph(); + let module_graph_cache = &self.module_graph_cache_artifact; + let dependencies_diagnostics: DependenciesDiagnosticsArtifact = modules + .par_iter() + .map(|module_identifier| { + let mgm = module_graph + .module_graph_module_by_identifier(module_identifier) + .expect("should have mgm"); + let diagnostics = mgm + .all_dependencies + .iter() + .filter_map(|dependency_id| { + let dependency = module_graph.dependency_by_id(dependency_id); + dependency + .get_diagnostics(module_graph, module_graph_cache) + .map(|diagnostics| { + diagnostics.into_iter().map(|mut diagnostic| { + diagnostic.module_identifier = Some(*module_identifier); + diagnostic.loc = dependency.loc(); + diagnostic + }) + }) + }) + .flatten() + .collect::>(); + (*module_identifier, diagnostics) + }) + .collect(); + let all_modules_diagnostics = if has_mutations { + dependencies_diagnostics_artifact.extend(dependencies_diagnostics); + dependencies_diagnostics_artifact.clone() + } else { + dependencies_diagnostics + }; + all_modules_diagnostics.into_values().flatten().collect() + } +} diff --git a/crates/rspack_core/src/compilation/mod.rs b/crates/rspack_core/src/compilation/mod.rs index f124be2ee07b..b1e18cc9bbee 100644 --- a/crates/rspack_core/src/compilation/mod.rs +++ b/crates/rspack_core/src/compilation/mod.rs @@ -1,5 +1,24 @@ +mod after_seal; +mod assign_runtime_ids; pub mod build_chunk_graph; pub mod build_module_graph; +mod chunk_ids; +mod code_generation; +mod create_chunk_assets; +mod create_hash; +mod create_module_assets; +mod create_module_hashes; +mod finish_module; +mod module_ids; +mod optimize_chunk_modules; +mod optimize_chunks; +mod optimize_code_generation; +mod optimize_dependencies; +mod optimize_modules; +mod optimize_tree; +mod process_assets; +mod run_passes; +mod runtime_requirements; use std::{ collections::{VecDeque, hash_map}, fmt::{self, Debug}, @@ -12,7 +31,6 @@ use std::{ }; use atomic_refcell::AtomicRefCell; -use build_chunk_graph::{artifact::use_code_splitting_cache, build_chunk_graph}; use dashmap::DashSet; use futures::future::BoxFuture; use indexmap::IndexMap; @@ -49,7 +67,7 @@ use crate::{ DependenciesDiagnosticsArtifact, DependencyCodeGeneration, DependencyTemplate, DependencyTemplateType, DependencyType, DerefOption, Entry, EntryData, EntryOptions, EntryRuntime, Entrypoint, ExecuteModuleId, Filename, ImportPhase, ImportVarMap, - ImportedByDeferModulesArtifact, Logger, MemoryGCStorage, ModuleFactory, ModuleGraph, + ImportedByDeferModulesArtifact, MemoryGCStorage, ModuleFactory, ModuleGraph, ModuleGraphCacheArtifact, ModuleIdentifier, ModuleIdsArtifact, ModuleStaticCacheArtifact, PathData, ResolverFactory, RuntimeGlobals, RuntimeKeyMap, RuntimeMode, RuntimeModule, RuntimeSpec, RuntimeSpecMap, RuntimeTemplate, SharedPluginDriver, SideEffectsOptimizeArtifact, @@ -163,49 +181,6 @@ static COMPILATION_ID: AtomicU32 = AtomicU32::new(0); /// Use macro to prevent cargo shear from failing and reporting errors /// due to the inability to parse the async closure syntax /// https://github.com/Boshen/cargo-shear/issues/143 -macro_rules! process_runtime_requirement_hook_macro { - ($name: ident, $s: ty, $c: ty) => { - async fn $name( - self: $s, - requirements: &mut RuntimeGlobals, - call_hook: impl for<'a> Fn( - $c, - &'a RuntimeGlobals, - &'a RuntimeGlobals, - &'a mut RuntimeGlobals, - ) -> BoxFuture<'a, Result<()>>, - ) -> Result<()> { - let mut runtime_requirements_mut = *requirements; - let mut runtime_requirements; - - loop { - runtime_requirements = runtime_requirements_mut; - runtime_requirements_mut = RuntimeGlobals::default(); - // runtime_requirements: rt_requirements of last time - // runtime_requirements_mut: changed rt_requirements - // requirements: all rt_requirements - call_hook( - self, - requirements, - &runtime_requirements, - &mut runtime_requirements_mut, - ) - .await?; - - // check if we have changes to runtime_requirements - runtime_requirements_mut = - runtime_requirements_mut.difference(requirements.intersection(runtime_requirements_mut)); - if runtime_requirements_mut.is_empty() { - break; - } else { - requirements.insert(runtime_requirements_mut); - } - } - Ok(()) - } - }; -} - #[derive(Debug)] pub struct Compilation { /// get_compilation_hooks(compilation.id) @@ -1060,372 +1035,6 @@ impl Compilation { .collect::>())) } - #[instrument("Compilation:code_generation",target=TRACING_BENCH_TARGET, skip_all)] - async fn code_generation(&mut self, modules: IdentifierSet) -> Result<()> { - let logger = self.get_logger("rspack.Compilation"); - let mut codegen_cache_counter = match self.options.cache { - CacheOptions::Disabled => None, - _ => Some(logger.cache("module code generation cache")), - }; - - let module_graph = self.get_module_graph(); - let mut no_codegen_dependencies_modules = IdentifierSet::default(); - let mut has_codegen_dependencies_modules = IdentifierSet::default(); - for module_identifier in modules { - let module = module_graph - .module_by_identifier(&module_identifier) - .expect("should have module"); - if module.get_code_generation_dependencies().is_none() { - no_codegen_dependencies_modules.insert(module_identifier); - } else { - has_codegen_dependencies_modules.insert(module_identifier); - } - } - - self - .code_generation_modules(&mut codegen_cache_counter, no_codegen_dependencies_modules) - .await?; - self - .code_generation_modules(&mut codegen_cache_counter, has_codegen_dependencies_modules) - .await?; - - if let Some(counter) = codegen_cache_counter { - logger.cache_end(counter); - } - - Ok(()) - } - - pub(crate) async fn code_generation_modules( - &mut self, - cache_counter: &mut Option, - modules: IdentifierSet, - ) -> Result<()> { - let chunk_graph = &self.chunk_graph; - let module_graph = self.get_module_graph(); - let mut jobs = Vec::new(); - for module in modules { - let mut map: HashMap = HashMap::default(); - for runtime in chunk_graph.get_module_runtimes_iter(module, &self.chunk_by_ukey) { - let hash = ChunkGraph::get_module_hash(self, module, runtime) - .expect("should have cgm.hash in code generation"); - let scope = self - .plugin_driver - .compilation_hooks - .concatenation_scope - .call(self, module) - .await?; - if let Some(job) = map.get_mut(hash) { - job.runtimes.push(runtime.clone()); - } else { - map.insert( - hash.clone(), - CodeGenerationJob { - module, - hash: hash.clone(), - runtime: runtime.clone(), - runtimes: vec![runtime.clone()], - scope, - }, - ); - } - } - jobs.extend(map.into_values()); - } - - let results = rspack_futures::scope::<_, _>(|token| { - jobs.into_iter().for_each(|job| { - // SAFETY: await immediately and trust caller to poll future entirely - let s = unsafe { token.used((&self, &module_graph, job)) }; - - s.spawn(|(this, module_graph, job)| async { - let options = &this.options; - let old_cache = &this.old_cache; - - let module = module_graph - .module_by_identifier(&job.module) - .expect("should have module"); - let codegen_res = old_cache - .code_generate_occasion - .use_cache(&job, || async { - module - .code_generation(this, Some(&job.runtime), job.scope.clone()) - .await - .map(|mut codegen_res| { - codegen_res.set_hash( - &options.output.hash_function, - &options.output.hash_digest, - &options.output.hash_salt, - ); - codegen_res - }) - }) - .await; - - (job.module, job.runtimes, codegen_res) - }) - }) - }) - .await; - let results = results - .into_iter() - .map(|res| res.to_rspack_result()) - .collect::>>()?; - - for (module, runtimes, (codegen_res, from_cache)) in results { - if let Some(counter) = cache_counter { - if from_cache { - counter.hit(); - } else { - counter.miss(); - } - } - let codegen_res = match codegen_res { - Ok(codegen_res) => codegen_res, - Err(err) => { - let mut diagnostic = Diagnostic::from(err); - diagnostic.module_identifier = Some(module); - self.push_diagnostic(diagnostic); - let mut codegen_res = CodeGenerationResult::default(); - codegen_res.set_hash( - &self.options.output.hash_function, - &self.options.output.hash_digest, - &self.options.output.hash_salt, - ); - codegen_res - } - }; - self - .code_generation_results - .insert(module, codegen_res, runtimes); - self.code_generated_modules.insert(module); - } - Ok(()) - } - - #[instrument("Compilation:create_module_assets",target=TRACING_BENCH_TARGET, skip_all)] - async fn create_module_assets(&mut self, _plugin_driver: SharedPluginDriver) { - let mut chunk_asset_map = vec![]; - let mut module_assets = vec![]; - let mg = self.get_module_graph(); - for (identifier, module) in mg.modules() { - let assets = &module.build_info().assets; - if assets.is_empty() { - continue; - } - - for (name, asset) in assets.as_ref() { - module_assets.push((name.clone(), asset.clone())); - } - // assets of executed modules are not in this compilation - if self - .chunk_graph - .chunk_graph_module_by_module_identifier - .contains_key(&identifier) - { - for chunk in self.chunk_graph.get_module_chunks(identifier).iter() { - for name in assets.keys() { - chunk_asset_map.push((*chunk, name.clone())) - } - } - } - } - - for (name, asset) in module_assets { - self.emit_asset(name, asset); - } - - for (chunk, asset_name) in chunk_asset_map { - let chunk = self.chunk_by_ukey.expect_get_mut(&chunk); - chunk.add_auxiliary_file(asset_name); - } - } - - #[instrument("Compilation::create_chunk_assets",target=TRACING_BENCH_TARGET, skip_all)] - async fn create_chunk_assets(&mut self, plugin_driver: SharedPluginDriver) -> Result<()> { - if (self.options.output.filename.has_hash_placeholder() - || self.options.output.chunk_filename.has_hash_placeholder() - || self.options.output.css_filename.has_hash_placeholder() - || self - .options - .output - .css_chunk_filename - .has_hash_placeholder()) - && let Some(diagnostic) = self.incremental.disable_passes( - IncrementalPasses::CHUNKS_RENDER, - "Chunk filename that dependent on full hash", - "chunk filename that dependent on full hash is not supported in incremental compilation", - ) - && let Some(diagnostic) = diagnostic - { - self.push_diagnostic(diagnostic); - } - - // Check if CHUNKS_RENDER pass is disabled, and clear artifact if needed - if !self - .incremental - .passes_enabled(IncrementalPasses::CHUNKS_RENDER) - { - self.chunk_render_artifact.clear(); - } - - let chunks = if let Some(mutations) = self - .incremental - .mutations_read(IncrementalPasses::CHUNKS_RENDER) - && !self.chunk_render_artifact.is_empty() - { - let removed_chunks = mutations.iter().filter_map(|mutation| match mutation { - Mutation::ChunkRemove { chunk } => Some(*chunk), - _ => None, - }); - for removed_chunk in removed_chunks { - self.chunk_render_artifact.remove(&removed_chunk); - } - self - .chunk_render_artifact - .retain(|chunk, _| self.chunk_by_ukey.contains(chunk)); - let chunks: UkeySet = mutations - .iter() - .filter_map(|mutation| match mutation { - Mutation::ChunkSetHashes { chunk } => Some(*chunk), - _ => None, - }) - .collect(); - tracing::debug!(target: incremental::TRACING_TARGET, passes = %IncrementalPasses::CHUNKS_RENDER, %mutations); - let logger = self.get_logger("rspack.incremental.chunksRender"); - logger.log(format!( - "{} chunks are affected, {} in total", - chunks.len(), - self.chunk_by_ukey.len() - )); - chunks - } else { - self.chunk_by_ukey.keys().copied().collect() - }; - let results = rspack_futures::scope::<_, Result<_>>(|token| { - chunks.iter().for_each(|chunk| { - // SAFETY: await immediately and trust caller to poll future entirely - let s = unsafe { token.used((&self, &plugin_driver, chunk)) }; - - s.spawn(|(this, plugin_driver, chunk)| async { - let mut manifests = Vec::new(); - let mut diagnostics = Vec::new(); - plugin_driver - .compilation_hooks - .render_manifest - .call(this, chunk, &mut manifests, &mut diagnostics) - .await?; - - rspack_error::Result::Ok(( - *chunk, - ChunkRenderResult { - manifests, - diagnostics, - }, - )) - }); - }) - }) - .await; - - let mut chunk_render_results: UkeyMap = Default::default(); - for result in results { - let item = result.to_rspack_result()?; - let (key, value) = item?; - chunk_render_results.insert(key, value); - } - let chunk_ukey_and_manifest = if self - .incremental - .passes_enabled(IncrementalPasses::CHUNKS_RENDER) - { - self.chunk_render_artifact.extend(chunk_render_results); - self.chunk_render_artifact.clone() - } else { - chunk_render_results - }; - - for ( - chunk_ukey, - ChunkRenderResult { - manifests, - diagnostics, - }, - ) in chunk_ukey_and_manifest - { - self.extend_diagnostics(diagnostics); - - for file_manifest in manifests { - let filename = file_manifest.filename; - let current_chunk = self.chunk_by_ukey.expect_get_mut(&chunk_ukey); - - current_chunk.set_rendered(true); - if file_manifest.auxiliary { - current_chunk.add_auxiliary_file(filename.clone()); - } else { - current_chunk.add_file(filename.clone()); - } - - self.emit_asset( - filename.clone(), - CompilationAsset::new(Some(file_manifest.source), file_manifest.info), - ); - - _ = self - .chunk_asset(chunk_ukey, &filename, plugin_driver.clone()) - .await; - } - } - - Ok(()) - } - - #[instrument("Compilation:process_assets",target=TRACING_BENCH_TARGET, skip_all)] - async fn process_assets(&mut self, plugin_driver: SharedPluginDriver) -> Result<()> { - plugin_driver - .compilation_hooks - .process_assets - .call(self) - .await - .map_err(|e| e.wrap_err("caused by plugins in Compilation.hooks.processAssets")) - } - - #[instrument("Compilation:after_process_assets", skip_all)] - async fn after_process_assets(&mut self, plugin_driver: SharedPluginDriver) -> Result<()> { - let mut diagnostics: Vec = vec![]; - - let res = plugin_driver - .compilation_hooks - .after_process_assets - .call(self, &mut diagnostics) - .await; - - self.extend_diagnostics(diagnostics); - res - } - - #[instrument("Compilation:after_seal", target=TRACING_BENCH_TARGET,skip_all)] - async fn after_seal(&mut self, plugin_driver: SharedPluginDriver) -> Result<()> { - plugin_driver.compilation_hooks.after_seal.call(self).await - } - - // #[instrument( - // name = "Compilation:chunk_asset", - // skip(self, plugin_driver, chunk_ukey) - // )] - async fn chunk_asset( - &self, - chunk_ukey: ChunkUkey, - filename: &str, - plugin_driver: SharedPluginDriver, - ) -> Result<()> { - plugin_driver - .compilation_hooks - .chunk_asset - .call(self, &chunk_ukey, filename) - .await?; - Ok(()) - } - pub fn entry_modules(&self) -> IdentifierSet { let module_graph = self.get_module_graph(); self @@ -1453,660 +1062,6 @@ impl Compilation { self.chunk_group_by_ukey.expect_get_mut(ukey) } - #[instrument("Compilation:finish",target=TRACING_BENCH_TARGET, skip_all)] - pub async fn finish_build_module_graph(&mut self) -> Result<()> { - self.in_finish_make.store(false, Ordering::Release); - // clean up the entry deps - let make_artifact = self.build_module_graph_artifact.take(); - self - .build_module_graph_artifact - .replace(finish_build_module_graph(self, make_artifact).await?); - // sync assets to module graph from module_executor - if let Some(module_executor) = &mut self.module_executor { - let mut module_executor = std::mem::take(module_executor); - module_executor.hook_after_finish_modules(self).await?; - self.module_executor = Some(module_executor); - } - // make finished, make artifact should be readonly thereafter. - Ok(()) - } - // collect build module graph effects for incremental compilation - #[tracing::instrument("Compilation:collect_build_module_graph_effects", skip_all)] - pub async fn collect_build_module_graph_effects( - &mut self, - dependencies_diagnostics_artifact: &mut DependenciesDiagnosticsArtifact, - async_modules_artifact: &mut AsyncModulesArtifact, - ) -> Result> { - let logger = self.get_logger("rspack.Compilation"); - if let Some(mut mutations) = self.incremental.mutations_write() { - mutations.extend( - self - .build_module_graph_artifact - .affected_dependencies - .updated() - .iter() - .map(|&dependency| Mutation::DependencyUpdate { dependency }), - ); - mutations.extend( - self - .build_module_graph_artifact - .affected_modules - .removed() - .iter() - .map(|&module| Mutation::ModuleRemove { module }), - ); - mutations.extend( - self - .build_module_graph_artifact - .affected_modules - .updated() - .iter() - .map(|&module| Mutation::ModuleUpdate { module }), - ); - mutations.extend( - self - .build_module_graph_artifact - .affected_modules - .added() - .iter() - .map(|&module| Mutation::ModuleAdd { module }), - ); - tracing::debug!(target: incremental::TRACING_TARGET, passes = %IncrementalPasses::MAKE, %mutations); - } - - let start = logger.time("finish modules"); - // finish_modules means the module graph (modules, connections, dependencies) are - // frozen and start to optimize (provided exports, infer async, etc.) based on the - // module graph, so any kind of change that affect these should be done before the - // finish_modules - self - .plugin_driver - .clone() - .compilation_hooks - .finish_modules - .call(self, async_modules_artifact) - .await?; - - logger.time_end(start); - - // https://github.com/webpack/webpack/blob/19ca74127f7668aaf60d59f4af8fcaee7924541a/lib/Compilation.js#L2988 - self.module_graph_cache_artifact.freeze(); - // Collect dependencies diagnostics at here to make sure: - // 1. after finish_modules: has provide exports info - // 2. before optimize dependencies: side effects free module hasn't been skipped - let mut all_diagnostics = - self.collect_dependencies_diagnostics(dependencies_diagnostics_artifact); - self.module_graph_cache_artifact.unfreeze(); - - // take make diagnostics - let diagnostics = self.build_module_graph_artifact.diagnostics(); - all_diagnostics.extend(diagnostics); - Ok(all_diagnostics) - } - #[tracing::instrument("Compilation:collect_dependencies_diagnostics", skip_all)] - fn collect_dependencies_diagnostics( - &self, - dependencies_diagnostics_artifact: &mut DependenciesDiagnosticsArtifact, - ) -> Vec { - // Compute modules while holding the lock, then release it - let (modules, has_mutations) = { - let mutations = self - .incremental - .mutations_read(IncrementalPasses::DEPENDENCIES_DIAGNOSTICS); - - // TODO move diagnostic collect to make - if let Some(mutations) = mutations { - if !dependencies_diagnostics_artifact.is_empty() { - let revoked_modules = mutations.iter().filter_map(|mutation| match mutation { - Mutation::ModuleRemove { module } => Some(*module), - _ => None, - }); - for revoked_module in revoked_modules { - dependencies_diagnostics_artifact.remove(&revoked_module); - } - let modules = mutations.get_affected_modules_with_module_graph(self.get_module_graph()); - let logger = self.get_logger("rspack.incremental.dependenciesDiagnostics"); - logger.log(format!( - "{} modules are affected, {} in total", - modules.len(), - self.get_module_graph().modules().len() - )); - (modules, true) - } else { - ( - self.get_module_graph().modules().keys().copied().collect(), - true, - ) - } - } else { - ( - self.get_module_graph().modules().keys().copied().collect(), - false, - ) - } - }; - - let module_graph = self.get_module_graph(); - let module_graph_cache = &self.module_graph_cache_artifact; - let dependencies_diagnostics: DependenciesDiagnosticsArtifact = modules - .par_iter() - .map(|module_identifier| { - let mgm = module_graph - .module_graph_module_by_identifier(module_identifier) - .expect("should have mgm"); - let diagnostics = mgm - .all_dependencies - .iter() - .filter_map(|dependency_id| { - let dependency = module_graph.dependency_by_id(dependency_id); - dependency - .get_diagnostics(module_graph, module_graph_cache) - .map(|diagnostics| { - diagnostics.into_iter().map(|mut diagnostic| { - diagnostic.module_identifier = Some(*module_identifier); - diagnostic.loc = dependency.loc(); - diagnostic - }) - }) - }) - .flatten() - .collect::>(); - (*module_identifier, diagnostics) - }) - .collect(); - let all_modules_diagnostics = if has_mutations { - dependencies_diagnostics_artifact.extend(dependencies_diagnostics); - dependencies_diagnostics_artifact.clone() - } else { - dependencies_diagnostics - }; - all_modules_diagnostics.into_values().flatten().collect() - } - - #[instrument("Compilation:seal", skip_all)] - pub async fn seal(&mut self, plugin_driver: SharedPluginDriver) -> Result<()> { - // add a checkpoint here since we may modify module graph later in incremental compilation - // and we can recover to this checkpoint in the future - if self.incremental.passes_enabled(IncrementalPasses::MAKE) { - self.build_module_graph_artifact.module_graph.checkpoint(); - } - - if !self.options.mode.is_development() { - self.module_static_cache_artifact.freeze(); - } - - let logger = self.get_logger("rspack.Compilation"); - - // https://github.com/webpack/webpack/blob/main/lib/Compilation.js#L2809 - plugin_driver - .compilation_hooks - .seal - .call(self) - .await - .map_err(|e| e.wrap_err("caused by plugins in Compilation.hooks.seal"))?; - - let start = logger.time("optimize dependencies"); - // https://github.com/webpack/webpack/blob/d15c73469fd71cf98734685225250148b68ddc79/lib/Compilation.js#L2812-L2814 - - let mut diagnostics: Vec = vec![]; - let mut side_effects_optimize_artifact = self.side_effects_optimize_artifact.take(); - let mut build_module_graph_artifact = self.build_module_graph_artifact.take(); - while matches!( - plugin_driver - .compilation_hooks - .optimize_dependencies - .call( - self, - &mut side_effects_optimize_artifact, - &mut build_module_graph_artifact, - &mut diagnostics - ) - .await - .map_err(|e| e.wrap_err("caused by plugins in Compilation.hooks.optimizeDependencies"))?, - Some(true) - ) {} - self - .side_effects_optimize_artifact - .replace(side_effects_optimize_artifact); - self - .build_module_graph_artifact - .replace(build_module_graph_artifact); - self.extend_diagnostics(diagnostics); - - logger.time_end(start); - - // ModuleGraph is frozen for now on, we have a module graph that won't change - // so now we can start to create a chunk graph based on the module graph - - let start = logger.time("create chunks"); - self.module_graph_cache_artifact.freeze(); - use_code_splitting_cache(self, |compilation| async { - let start = logger.time("rebuild chunk graph"); - build_chunk_graph(compilation)?; - compilation - .chunk_graph - .generate_dot(compilation, "after-code-splitting") - .await; - logger.time_end(start); - Ok(compilation) - }) - .await?; - - let mut diagnostics = vec![]; - while matches!( - plugin_driver - .compilation_hooks - .optimize_modules - .call(self, &mut diagnostics) - .await - .map_err(|e| e.wrap_err("caused by plugins in Compilation.hooks.optimizeModules"))?, - Some(true) - ) {} - self.extend_diagnostics(diagnostics); - - plugin_driver - .compilation_hooks - .after_optimize_modules - .call(self) - .await - .map_err(|e| e.wrap_err("caused by plugins in Compilation.hooks.afterOptimizeModules"))?; - - while matches!( - plugin_driver - .compilation_hooks - .optimize_chunks - .call(self) - .await - .map_err(|e| e.wrap_err("caused by plugins in Compilation.hooks.optimizeChunks"))?, - Some(true) - ) {} - - logger.time_end(start); - - let start = logger.time("optimize"); - plugin_driver - .compilation_hooks - .optimize_tree - .call(self) - .await - .map_err(|e| e.wrap_err("caused by plugins in Compilation.hooks.optimizeTree"))?; - - plugin_driver - .compilation_hooks - .optimize_chunk_modules - .call(self) - .await - .map_err(|e| e.wrap_err("caused by plugins in Compilation.hooks.optimizeChunkModules"))?; - logger.time_end(start); - - // ChunkGraph is frozen for now on, we have a chunk graph that won't change - // so now we can start to generate assets based on the chunk graph - - let start = logger.time("module ids"); - - // Check if MODULE_IDS pass is disabled, and clear artifact if needed - if !self - .incremental - .passes_enabled(IncrementalPasses::MODULE_IDS) - { - self.module_ids_artifact.clear(); - } - - let mut diagnostics = vec![]; - let mut module_ids_artifact = mem::take(&mut self.module_ids_artifact); - plugin_driver - .compilation_hooks - .module_ids - .call(self, &mut module_ids_artifact, &mut diagnostics) - .await - .map_err(|e| e.wrap_err("caused by plugins in Compilation.hooks.moduleIds"))?; - self.module_ids_artifact = module_ids_artifact; - self.extend_diagnostics(diagnostics); - logger.time_end(start); - - let start = logger.time("chunk ids"); - - // Check if CHUNK_IDS pass is disabled, and clear artifact if needed - if !self - .incremental - .passes_enabled(IncrementalPasses::CHUNK_IDS) - { - self.named_chunk_ids_artifact.clear(); - } - - let mut diagnostics = vec![]; - let mut chunk_by_ukey = mem::take(&mut self.chunk_by_ukey); - let mut named_chunk_ids_artifact = mem::take(&mut self.named_chunk_ids_artifact); - plugin_driver - .compilation_hooks - .chunk_ids - .call( - self, - &mut chunk_by_ukey, - &mut named_chunk_ids_artifact, - &mut diagnostics, - ) - .await - .map_err(|e| e.wrap_err("caused by plugins in Compilation.hooks.chunkIds"))?; - self.chunk_by_ukey = chunk_by_ukey; - self.named_chunk_ids_artifact = named_chunk_ids_artifact; - self.extend_diagnostics(diagnostics); - logger.time_end(start); - - self.assign_runtime_ids(); - - let start = logger.time("optimize code generation"); - plugin_driver - .compilation_hooks - .optimize_code_generation - .call(self) - .await - .map_err(|e| e.wrap_err("caused by plugins in Compilation.hooks.optimizeCodeGeneration"))?; - logger.time_end(start); - - // Check if MODULES_HASHES pass is disabled, and clear artifact if needed - if !self - .incremental - .passes_enabled(IncrementalPasses::MODULES_HASHES) - { - self.cgm_hash_artifact.clear(); - } - - let create_module_hashes_modules = if let Some(mutations) = self - .incremental - .mutations_read(IncrementalPasses::MODULES_HASHES) - && !self.cgm_hash_artifact.is_empty() - { - let revoked_modules = mutations.iter().filter_map(|mutation| match mutation { - Mutation::ModuleRemove { module } => Some(*module), - _ => None, - }); - for revoked_module in revoked_modules { - self.cgm_hash_artifact.remove(&revoked_module); - } - let mut modules = mutations.get_affected_modules_with_chunk_graph(self); - - // check if module runtime changes - let mg = self.get_module_graph(); - for mi in mg.modules().keys() { - let module_runtimes = self - .chunk_graph - .get_module_runtimes(*mi, &self.chunk_by_ukey); - let module_runtime_keys = module_runtimes - .values() - .map(get_runtime_key) - .collect::>(); - - if let Some(runtime_map) = self.cgm_hash_artifact.get_runtime_map(mi) { - if module_runtimes.is_empty() { - // module has no runtime, skip - continue; - } - if module_runtimes.len() == 1 { - // single runtime - if !matches!(runtime_map.mode, RuntimeMode::SingleEntry) - || runtime_map - .single_runtime - .as_ref() - .expect("should have single runtime for single entry") - != module_runtimes - .values() - .next() - .expect("should have at least one runtime") - { - modules.insert(*mi); - } - } else { - // multiple runtimes - if matches!(runtime_map.mode, RuntimeMode::SingleEntry) { - modules.insert(*mi); - continue; - } - - if runtime_map.map.len() != module_runtimes.len() { - modules.insert(*mi); - continue; - } - - for runtime_key in runtime_map.map.keys() { - if !module_runtime_keys.contains(runtime_key) { - modules.insert(*mi); - break; - } - } - } - } - } - - tracing::debug!(target: incremental::TRACING_TARGET, passes = %IncrementalPasses::MODULES_HASHES, %mutations, ?modules); - let logger = self.get_logger("rspack.incremental.modulesHashes"); - logger.log(format!( - "{} modules are affected, {} in total", - modules.len(), - mg.modules().len() - )); - - modules - } else { - self.get_module_graph().modules().keys().copied().collect() - }; - self - .create_module_hashes(create_module_hashes_modules) - .await?; - - let start = logger.time("code generation"); - let code_generation_modules = if let Some(mutations) = self - .incremental - .mutations_read(IncrementalPasses::MODULES_CODEGEN) - && !self.code_generation_results.is_empty() - { - let revoked_modules = mutations.iter().filter_map(|mutation| match mutation { - Mutation::ModuleRemove { module } => Some(*module), - _ => None, - }); - for revoked_module in revoked_modules { - self.code_generation_results.remove(&revoked_module); - } - let modules: IdentifierSet = mutations - .iter() - .filter_map(|mutation| match mutation { - Mutation::ModuleSetHashes { module } => Some(*module), - _ => None, - }) - .collect(); - // also cleanup for updated modules, for `insert(); insert();` the second insert() won't override the first insert() on code_generation_results - for module in &modules { - self.code_generation_results.remove(module); - } - tracing::debug!(target: incremental::TRACING_TARGET, passes = %IncrementalPasses::MODULES_CODEGEN, %mutations); - let logger = self.get_logger("rspack.incremental.modulesCodegen"); - logger.log(format!( - "{} modules are affected, {} in total", - modules.len(), - self.get_module_graph().modules().len() - )); - modules - } else { - self.code_generation_results = Default::default(); - self.get_module_graph().modules().keys().copied().collect() - }; - self.code_generation(code_generation_modules).await?; - - let mut diagnostics = vec![]; - plugin_driver - .compilation_hooks - .after_code_generation - .call(self, &mut diagnostics) - .await - .map_err(|e| e.wrap_err("caused by plugins in Compilation.hooks.afterCodeGeneration"))?; - self.extend_diagnostics(diagnostics); - - logger.time_end(start); - - let start = logger.time("runtime requirements"); - let process_runtime_requirements_modules = if let Some(mutations) = self - .incremental - .mutations_read(IncrementalPasses::MODULES_RUNTIME_REQUIREMENTS) - && !self.cgm_runtime_requirements_artifact.is_empty() - { - let revoked_modules = mutations.iter().filter_map(|mutation| match mutation { - Mutation::ModuleRemove { module } => Some(*module), - _ => None, - }); - for revoked_module in revoked_modules { - self - .cgm_runtime_requirements_artifact - .remove(&revoked_module); - } - let modules: IdentifierSet = mutations - .iter() - .filter_map(|mutation| match mutation { - Mutation::ModuleSetHashes { module } => Some(*module), - _ => None, - }) - .collect(); - let logger = self.get_logger("rspack.incremental.modulesRuntimeRequirements"); - logger.log(format!( - "{} modules are affected, {} in total", - modules.len(), - self.get_module_graph().modules().len() - )); - modules - } else { - self.cgm_runtime_requirements_artifact = Default::default(); - self.get_module_graph().modules().keys().copied().collect() - }; - self - .process_modules_runtime_requirements( - process_runtime_requirements_modules, - plugin_driver.clone(), - ) - .await?; - let runtime_chunks = self.get_chunk_graph_entries().collect(); - - // Check if CHUNKS_RUNTIME_REQUIREMENTS pass is disabled, and clear artifact if needed - if !self - .incremental - .passes_enabled(IncrementalPasses::CHUNKS_RUNTIME_REQUIREMENTS) - { - self.cgc_runtime_requirements_artifact.clear(); - } - - let process_runtime_requirements_chunks = if let Some(mutations) = self - .incremental - .mutations_read(IncrementalPasses::CHUNKS_RUNTIME_REQUIREMENTS) - && !self.cgc_runtime_requirements_artifact.is_empty() - { - let removed_chunks = mutations.iter().filter_map(|mutation| match mutation { - Mutation::ChunkRemove { chunk } => Some(chunk), - _ => None, - }); - for removed_chunk in removed_chunks { - self.cgc_runtime_requirements_artifact.remove(removed_chunk); - } - let affected_chunks = mutations.get_affected_chunks_with_chunk_graph(self); - for affected_chunk in &affected_chunks { - self - .cgc_runtime_requirements_artifact - .remove(affected_chunk); - } - for runtime_chunk in &runtime_chunks { - self.cgc_runtime_requirements_artifact.remove(runtime_chunk); - } - self - .cgc_runtime_requirements_artifact - .retain(|chunk, _| self.chunk_by_ukey.contains(chunk)); - let logger = self.get_logger("rspack.incremental.chunksRuntimeRequirements"); - logger.log(format!( - "{} chunks are affected, {} in total", - affected_chunks.len(), - self.chunk_by_ukey.len() - )); - affected_chunks - } else { - self.chunk_by_ukey.keys().copied().collect() - }; - self - .process_chunks_runtime_requirements( - process_runtime_requirements_chunks, - runtime_chunks, - plugin_driver.clone(), - ) - .await?; - logger.time_end(start); - - let start = logger.time("hashing"); - self.create_hash(plugin_driver.clone()).await?; - self.runtime_modules_code_generation().await?; - logger.time_end(start); - - let start = logger.time("create module assets"); - self.create_module_assets(plugin_driver.clone()).await; - logger.time_end(start); - - let start = logger.time("create chunk assets"); - self.create_chunk_assets(plugin_driver.clone()).await?; - logger.time_end(start); - - let start = logger.time("process assets"); - self.process_assets(plugin_driver.clone()).await?; - logger.time_end(start); - - let start = logger.time("after process assets"); - self.after_process_assets(plugin_driver.clone()).await?; - logger.time_end(start); - - let start = logger.time("after seal"); - self.after_seal(plugin_driver).await?; - logger.time_end(start); - - if !self.options.mode.is_development() { - self.module_static_cache_artifact.unfreeze(); - } - Ok(()) - } - - pub fn assign_runtime_ids(&mut self) { - fn process_entrypoint( - entrypoint_ukey: &ChunkGroupUkey, - chunk_group_by_ukey: &ChunkGroupByUkey, - chunk_by_ukey: &ChunkByUkey, - chunk_graph: &mut ChunkGraph, - ) { - let entrypoint = chunk_group_by_ukey.expect_get(entrypoint_ukey); - let runtime = entrypoint - .kind - .get_entry_options() - .and_then(|o| match &o.runtime { - Some(EntryRuntime::String(s)) => Some(s.to_owned()), - _ => None, - }) - .or(entrypoint.name().map(|n| n.to_string())); - if let (Some(runtime), Some(chunk)) = ( - runtime, - chunk_by_ukey.get(&entrypoint.get_runtime_chunk(chunk_group_by_ukey)), - ) { - chunk_graph.set_runtime_id(runtime, chunk.id().map(|id| id.to_string())); - } - } - for i in self.entrypoints.iter() { - process_entrypoint( - i.1, - &self.chunk_group_by_ukey, - &self.chunk_by_ukey, - &mut self.chunk_graph, - ) - } - for i in self.async_entrypoints.iter() { - process_entrypoint( - i, - &self.chunk_group_by_ukey, - &self.chunk_by_ukey, - &mut self.chunk_graph, - ) - } - } - pub fn get_chunk_graph_entries(&self) -> impl Iterator + use<'_> { let entries = self.entrypoints.values().map(|entrypoint_ukey| { let entrypoint = self.chunk_group_by_ukey.expect_get(entrypoint_ukey); @@ -2118,727 +1073,6 @@ impl Compilation { }); entries.chain(async_entries) } - - #[instrument("Compilation:process_modules_runtime_requirements", skip_all)] - pub async fn process_modules_runtime_requirements( - &mut self, - modules: IdentifierSet, - plugin_driver: SharedPluginDriver, - ) -> Result<()> { - let logger = self.get_logger("rspack.Compilation"); - let start = logger.time("runtime requirements.modules"); - - let module_results = rspack_futures::scope::<_, Result<_>>(|token| { - modules - .into_iter() - .filter(|module| self.chunk_graph.get_number_of_module_chunks(*module) > 0) - .for_each(|module| { - let s = unsafe { token.used((&self, &plugin_driver)) }; - s.spawn(move |(compilation, plugin_driver)| async move { - let mut map = RuntimeSpecMap::new(); - let runtimes = compilation - .chunk_graph - .get_module_runtimes_iter(module, &compilation.chunk_by_ukey); - for runtime in runtimes { - let runtime_requirements = compilation - .old_cache - .process_runtime_requirements_occasion - .use_cache(module, runtime, compilation, || async { - let mut runtime_requirements = compilation - .code_generation_results - .get_runtime_requirements(&module, Some(runtime)); - - plugin_driver - .compilation_hooks - .additional_module_runtime_requirements - .call(compilation, &module, &mut runtime_requirements) - .await - .map_err(|e| e.wrap_err("caused by plugins in Compilation.hooks.additionalModuleRuntimeRequirements"))?; - - compilation - .process_runtime_requirement_hook(&mut runtime_requirements, { - let plugin_driver = plugin_driver.clone(); - move |compilation, - all_runtime_requirements, - runtime_requirements, - runtime_requirements_mut| { - Box::pin({ - let plugin_driver = plugin_driver.clone(); - async move { - plugin_driver - .compilation_hooks - .runtime_requirement_in_module - .call( - compilation, - &module, - all_runtime_requirements, - runtime_requirements, - runtime_requirements_mut, - ) - .await - .map_err(|e| e.wrap_err("caused by plugins in Compilation.hooks.runtimeRequirementInModule"))?; - Ok(()) - }}) - } - }) - .await?; - Ok(runtime_requirements) - }) - .await?; - map.set(runtime.clone(), runtime_requirements); - } - Ok((module, map)) - }); - }); - }) - .await - .into_iter() - .map(|r| r.to_rspack_result()) - .collect::>>()?; - - for entry in module_results { - let (module, map) = entry?; - ChunkGraph::set_module_runtime_requirements(self, module, map); - } - logger.time_end(start); - Ok(()) - } - - #[instrument(name = "Compilation:process_chunks_runtime_requirements", target=TRACING_BENCH_TARGET skip_all)] - pub async fn process_chunks_runtime_requirements( - &mut self, - chunks: UkeySet, - entries: UkeySet, - plugin_driver: SharedPluginDriver, - ) -> Result<()> { - let logger = self.get_logger("rspack.Compilation"); - let start = logger.time("runtime requirements.chunks"); - let chunk_requirements = chunks - .iter() - .chain(entries.iter()) - .par_bridge() - .map(|chunk_ukey| { - let mut set = RuntimeGlobals::default(); - for mid in self.chunk_graph.get_chunk_modules_identifier(chunk_ukey) { - let chunk = self.chunk_by_ukey.expect_get(chunk_ukey); - if let Some(runtime_requirements) = - ChunkGraph::get_module_runtime_requirements(self, *mid, chunk.runtime()) - { - set.insert(*runtime_requirements); - } - } - - (*chunk_ukey, set) - }) - .collect::>(); - - for (chunk_ukey, mut set) in chunk_requirements { - plugin_driver - .compilation_hooks - .additional_chunk_runtime_requirements - .call(self, &chunk_ukey, &mut set) - .await - .map_err(|e| { - e.wrap_err("caused by plugins in Compilation.hooks.additionalChunkRuntimeRequirements") - })?; - - self - .process_runtime_requirement_hook_mut(&mut set, { - let plugin_driver = plugin_driver.clone(); - move |compilation, - all_runtime_requirements, - runtime_requirements, - runtime_requirements_mut| { - Box::pin({ - let plugin_driver = plugin_driver.clone(); - async move { - plugin_driver - .compilation_hooks - .runtime_requirement_in_chunk - .call( - compilation, - &chunk_ukey, - all_runtime_requirements, - runtime_requirements, - runtime_requirements_mut, - ) - .await - .map_err(|e| { - e.wrap_err("caused by plugins in Compilation.hooks.runtimeRequirementInChunk") - })?; - Ok(()) - } - }) - } - }) - .await?; - - ChunkGraph::set_chunk_runtime_requirements(self, chunk_ukey, set); - } - logger.time_end(start); - - let start = logger.time("runtime requirements.entries"); - for &entry_ukey in &entries { - let entry = self.chunk_by_ukey.expect_get(&entry_ukey); - let mut set = RuntimeGlobals::default(); - for chunk_ukey in entry - .get_all_referenced_chunks(&self.chunk_group_by_ukey) - .iter() - { - let runtime_requirements = ChunkGraph::get_chunk_runtime_requirements(self, chunk_ukey); - set.insert(*runtime_requirements); - } - - plugin_driver - .compilation_hooks - .additional_tree_runtime_requirements - .call(self, &entry_ukey, &mut set) - .await - .map_err(|e| { - e.wrap_err("caused by plugins in Compilation.hooks.additionalTreeRuntimeRequirements") - })?; - - self - .process_runtime_requirement_hook_mut(&mut set, { - let plugin_driver = plugin_driver.clone(); - move |compilation, - all_runtime_requirements, - runtime_requirements, - runtime_requirements_mut| { - Box::pin({ - let plugin_driver = plugin_driver.clone(); - async move { - plugin_driver - .compilation_hooks - .runtime_requirement_in_tree - .call( - compilation, - &entry_ukey, - all_runtime_requirements, - runtime_requirements, - runtime_requirements_mut, - ) - .await - .map_err(|e| { - e.wrap_err("caused by plugins in Compilation.hooks.runtimeRequirementInTree") - })?; - Ok(()) - } - }) - } - }) - .await?; - - ChunkGraph::set_tree_runtime_requirements(self, entry_ukey, set); - } - - // NOTE: webpack runs hooks.runtime_module in compilation.add_runtime_module - // and overwrite the runtime_module.generate() to get new source in create_chunk_assets - // this needs full runtime requirements, so run hooks.runtime_module after runtime_requirements_in_tree - let mut runtime_modules = mem::take(&mut self.runtime_modules); - for entry_ukey in &entries { - let runtime_module_ids: Vec<_> = self - .chunk_graph - .get_chunk_runtime_modules_iterable(entry_ukey) - .copied() - .collect(); - for runtime_module_id in runtime_module_ids { - plugin_driver - .compilation_hooks - .runtime_module - .call(self, &runtime_module_id, entry_ukey, &mut runtime_modules) - .await - .map_err(|e| e.wrap_err("caused by plugins in Compilation.hooks.runtimeModule"))?; - } - } - self.runtime_modules = runtime_modules; - - logger.time_end(start); - Ok(()) - } - - process_runtime_requirement_hook_macro!( - process_runtime_requirement_hook, - &Compilation, - &'a Compilation - ); - process_runtime_requirement_hook_macro!( - process_runtime_requirement_hook_mut, - &mut Compilation, - &'a mut Compilation - ); - - #[instrument(name = "Compilation:create_hash",target=TRACING_BENCH_TARGET, skip_all)] - pub async fn create_hash(&mut self, plugin_driver: SharedPluginDriver) -> Result<()> { - let logger = self.get_logger("rspack.Compilation"); - - // Check if there are any chunks that depend on full hash, usually only runtime chunks are - // possible to depend on full hash, but for library type commonjs/module, it's possible to - // have non-runtime chunks depend on full hash, the library format plugin is using - // dependent_full_hash hook to declare it. - let mut full_hash_chunks = UkeySet::default(); - for chunk_ukey in self.chunk_by_ukey.keys() { - let chunk_dependent_full_hash = plugin_driver - .compilation_hooks - .dependent_full_hash - .call(self, chunk_ukey) - .await? - .unwrap_or_default(); - if chunk_dependent_full_hash { - full_hash_chunks.insert(*chunk_ukey); - } - } - if !full_hash_chunks.is_empty() - && let Some(diagnostic) = self.incremental.disable_passes( - IncrementalPasses::CHUNKS_HASHES, - "Chunk content that dependent on full hash", - "it requires calculating the hashes of all the chunks, which is a global effect", - ) - && let Some(diagnostic) = diagnostic - { - self.push_diagnostic(diagnostic); - } - if !self - .incremental - .passes_enabled(IncrementalPasses::CHUNKS_HASHES) - { - self.chunk_hashes_artifact.clear(); - } - - let create_hash_chunks = if let Some(mutations) = self - .incremental - .mutations_read(IncrementalPasses::CHUNKS_HASHES) - && !self.chunk_hashes_artifact.is_empty() - { - let removed_chunks = mutations.iter().filter_map(|mutation| match mutation { - Mutation::ChunkRemove { chunk } => Some(*chunk), - _ => None, - }); - for removed_chunk in removed_chunks { - self.chunk_hashes_artifact.remove(&removed_chunk); - } - self - .chunk_hashes_artifact - .retain(|chunk, _| self.chunk_by_ukey.contains(chunk)); - let chunks = mutations.get_affected_chunks_with_chunk_graph(self); - tracing::debug!(target: incremental::TRACING_TARGET, passes = %IncrementalPasses::CHUNKS_HASHES, %mutations, ?chunks); - let logger = self.get_logger("rspack.incremental.chunksHashes"); - logger.log(format!( - "{} chunks are affected, {} in total", - chunks.len(), - self.chunk_by_ukey.len(), - )); - chunks - } else { - self.chunk_by_ukey.keys().copied().collect() - }; - - let mut compilation_hasher = RspackHash::from(&self.options.output); - - fn try_process_chunk_hash_results( - compilation: &mut Compilation, - chunk_hash_results: Vec>, - ) -> Result<()> { - for hash_result in chunk_hash_results { - let (chunk_ukey, chunk_hash_result) = hash_result?; - let chunk = compilation.chunk_by_ukey.expect_get(&chunk_ukey); - let chunk_hashes_changed = chunk.set_hashes( - &mut compilation.chunk_hashes_artifact, - chunk_hash_result.hash, - chunk_hash_result.content_hash, - ); - if chunk_hashes_changed - && let Some(mut mutations) = compilation.incremental.mutations_write() - { - mutations.add(Mutation::ChunkSetHashes { chunk: chunk_ukey }); - } - } - Ok(()) - } - - let unordered_runtime_chunks: UkeySet = self.get_chunk_graph_entries().collect(); - let start = logger.time("hashing: hash chunks"); - let other_chunks: Vec<_> = create_hash_chunks - .iter() - .filter(|key| !unordered_runtime_chunks.contains(key)) - .collect(); - - // create hash for runtime modules in other chunks - let other_chunk_runtime_module_hashes = rspack_futures::scope::<_, Result<_>>(|token| { - other_chunks - .iter() - .flat_map(|chunk| self.chunk_graph.get_chunk_runtime_modules_iterable(chunk)) - .for_each(|runtime_module_identifier| { - let s = unsafe { token.used((&self, runtime_module_identifier)) }; - s.spawn(|(compilation, runtime_module_identifier)| async { - let runtime_module = &compilation.runtime_modules[runtime_module_identifier]; - let digest = runtime_module.get_runtime_hash(compilation, None).await?; - Ok((*runtime_module_identifier, digest)) - }); - }) - }) - .await - .into_iter() - .map(|res| res.to_rspack_result()) - .collect::>>()?; - - for res in other_chunk_runtime_module_hashes { - let (runtime_module_identifier, digest) = res?; - self - .runtime_modules_hash - .insert(runtime_module_identifier, digest); - } - - // create hash for other chunks - let other_chunks_hash_results = rspack_futures::scope::<_, Result<_>>(|token| { - for chunk in other_chunks { - let s = unsafe { token.used((&self, chunk, &plugin_driver)) }; - s.spawn(|(compilation, chunk, plugin_driver)| async { - let hash_result = compilation - .process_chunk_hash(*chunk, plugin_driver) - .await?; - Ok((*chunk, hash_result)) - }); - } - }) - .await - .into_iter() - .map(|res| res.to_rspack_result()) - .collect::>>()?; - - try_process_chunk_hash_results(self, other_chunks_hash_results)?; - logger.time_end(start); - - // collect references for runtime chunks - let mut runtime_chunks_map: HashMap, u32)> = - unordered_runtime_chunks - .into_iter() - .map(|runtime_chunk| (runtime_chunk, (Vec::new(), 0))) - .collect(); - let mut remaining: u32 = 0; - for runtime_chunk_ukey in runtime_chunks_map.keys().copied().collect::>() { - let runtime_chunk = self.chunk_by_ukey.expect_get(&runtime_chunk_ukey); - let groups = runtime_chunk.get_all_referenced_async_entrypoints(&self.chunk_group_by_ukey); - for other in groups - .into_iter() - .map(|group| self.chunk_group_by_ukey.expect_get(&group)) - .map(|group| group.get_runtime_chunk(&self.chunk_group_by_ukey)) - { - let (other_referenced_by, _) = runtime_chunks_map - .get_mut(&other) - .expect("should in runtime_chunks_map"); - other_referenced_by.push(runtime_chunk_ukey); - let info = runtime_chunks_map - .get_mut(&runtime_chunk_ukey) - .expect("should in runtime_chunks_map"); - info.1 += 1; - remaining += 1; - } - } - // sort runtime chunks by its references - let mut runtime_chunks = Vec::with_capacity(runtime_chunks_map.len()); - for (runtime_chunk, (_, remaining)) in &runtime_chunks_map { - if *remaining == 0 { - runtime_chunks.push(*runtime_chunk); - } - } - let mut ready_chunks = Vec::new(); - - let mut i = 0; - while i < runtime_chunks.len() { - let chunk_ukey = runtime_chunks[i]; - let has_full_hash_modules = full_hash_chunks.contains(&chunk_ukey) - || self - .chunk_graph - .has_chunk_full_hash_modules(&chunk_ukey, &self.runtime_modules); - if has_full_hash_modules { - full_hash_chunks.insert(chunk_ukey); - } - let referenced_by = runtime_chunks_map - .get(&chunk_ukey) - .expect("should in runtime_chunks_map") - .0 - .clone(); - for other in referenced_by { - if has_full_hash_modules { - for runtime_module in self.chunk_graph.get_chunk_runtime_modules_iterable(&other) { - let runtime_module = self - .runtime_modules - .get(runtime_module) - .expect("should have runtime_module"); - if runtime_module.dependent_hash() { - full_hash_chunks.insert(other); - break; - } - } - } - remaining -= 1; - let (_, other_remaining) = runtime_chunks_map - .get_mut(&other) - .expect("should in runtime_chunks_map"); - *other_remaining -= 1; - if *other_remaining == 0 { - ready_chunks.push(other); - } - } - if !ready_chunks.is_empty() { - runtime_chunks.append(&mut ready_chunks); - } - i += 1; - } - // create warning for remaining circular references - if remaining > 0 { - let mut circular: Vec<_> = runtime_chunks_map - .iter() - .filter(|(_, (_, remaining))| *remaining != 0) - .map(|(chunk_ukey, _)| self.chunk_by_ukey.expect_get(chunk_ukey)) - .collect(); - circular.sort_unstable_by(|a, b| a.id().cmp(&b.id())); - runtime_chunks.extend(circular.iter().map(|chunk| chunk.ukey())); - let circular_names = circular - .iter() - .map(|chunk| { - chunk - .name() - .or(chunk.id().map(|id| id.as_str())) - .unwrap_or("no id chunk") - }) - .join(", "); - let error = rspack_error::Error::warning(format!( - "Circular dependency between chunks with runtime ({circular_names})\nThis prevents using hashes of each other and should be avoided." - )); - self.push_diagnostic(error.into()); - } - - // create hash for runtime chunks and the runtime modules within them - // The subsequent runtime chunks and runtime modules will depend on - // the hash results of the previous runtime chunks and runtime modules. - // Therefore, create hashes one by one in sequence. - let start = logger.time("hashing: hash runtime chunks"); - for runtime_chunk_ukey in runtime_chunks { - let runtime_module_hashes = rspack_futures::scope::<_, Result<_>>(|token| { - self - .chunk_graph - .get_chunk_runtime_modules_iterable(&runtime_chunk_ukey) - .for_each(|runtime_module_identifier| { - let s = unsafe { token.used((&self, runtime_module_identifier)) }; - s.spawn(|(compilation, runtime_module_identifier)| async { - let runtime_module = &compilation.runtime_modules[runtime_module_identifier]; - let digest = runtime_module.get_runtime_hash(compilation, None).await?; - Ok((*runtime_module_identifier, digest)) - }); - }) - }) - .await - .into_iter() - .map(|res| res.to_rspack_result()) - .collect::>>()?; - - for res in runtime_module_hashes { - let (mid, digest) = res?; - self.runtime_modules_hash.insert(mid, digest); - } - - let chunk_hash_result = self - .process_chunk_hash(runtime_chunk_ukey, &plugin_driver) - .await?; - let chunk = self.chunk_by_ukey.expect_get(&runtime_chunk_ukey); - let chunk_hashes_changed = chunk.set_hashes( - &mut self.chunk_hashes_artifact, - chunk_hash_result.hash, - chunk_hash_result.content_hash, - ); - if chunk_hashes_changed && let Some(mut mutations) = self.incremental.mutations_write() { - mutations.add(Mutation::ChunkSetHashes { - chunk: runtime_chunk_ukey, - }); - } - } - logger.time_end(start); - - // create full hash - self - .chunk_by_ukey - .values() - .sorted_unstable_by_key(|chunk| chunk.ukey()) - .filter_map(|chunk| chunk.hash(&self.chunk_hashes_artifact)) - .for_each(|hash| { - hash.hash(&mut compilation_hasher); - }); - self.hot_index.hash(&mut compilation_hasher); - self.hash = Some(compilation_hasher.digest(&self.options.output.hash_digest)); - - // re-create runtime chunk hash that depend on full hash - let start = logger.time("hashing: process full hash chunks"); - for chunk_ukey in full_hash_chunks { - for runtime_module_identifier in self - .chunk_graph - .get_chunk_runtime_modules_iterable(&chunk_ukey) - { - let runtime_module = &self.runtime_modules[runtime_module_identifier]; - if runtime_module.full_hash() || runtime_module.dependent_hash() { - let digest = runtime_module.get_runtime_hash(self, None).await?; - self - .runtime_modules_hash - .insert(*runtime_module_identifier, digest); - } - } - let chunk = self.chunk_by_ukey.expect_get(&chunk_ukey); - let new_chunk_hash = { - let chunk_hash = chunk - .hash(&self.chunk_hashes_artifact) - .expect("should have chunk hash"); - let mut hasher = RspackHash::from(&self.options.output); - chunk_hash.hash(&mut hasher); - self.hash.hash(&mut hasher); - hasher.digest(&self.options.output.hash_digest) - }; - let new_content_hash = { - let content_hash = chunk - .content_hash(&self.chunk_hashes_artifact) - .expect("should have content hash"); - content_hash - .iter() - .map(|(source_type, content_hash)| { - let mut hasher = RspackHash::from(&self.options.output); - content_hash.hash(&mut hasher); - self.hash.hash(&mut hasher); - ( - *source_type, - hasher.digest(&self.options.output.hash_digest), - ) - }) - .collect() - }; - let chunk_hashes_changed = chunk.set_hashes( - &mut self.chunk_hashes_artifact, - new_chunk_hash, - new_content_hash, - ); - if chunk_hashes_changed && let Some(mut mutations) = self.incremental.mutations_write() { - mutations.add(Mutation::ChunkSetHashes { chunk: chunk_ukey }); - } - } - logger.time_end(start); - Ok(()) - } - - #[instrument(skip_all)] - pub async fn runtime_modules_code_generation(&mut self) -> Result<()> { - let results = rspack_futures::scope::<_, Result<_>>(|token| { - self - .runtime_modules - .iter() - .for_each(|(runtime_module_identifier, runtime_module)| { - let s = unsafe { token.used((&self, runtime_module_identifier, runtime_module)) }; - s.spawn( - |(compilation, runtime_module_identifier, runtime_module)| async { - let result = runtime_module - .code_generation(compilation, None, None) - .await?; - let source = result - .get(&SourceType::Runtime) - .expect("should have source"); - Ok((*runtime_module_identifier, source.clone())) - }, - ) - }) - }) - .await - .into_iter() - .map(|res| res.to_rspack_result()) - .collect::>>()?; - - let mut runtime_module_sources = IdentifierMap::::default(); - for result in results { - let (runtime_module_identifier, source) = result?; - runtime_module_sources.insert(runtime_module_identifier, source); - } - - self.runtime_modules_code_generation_source = runtime_module_sources; - self - .code_generated_modules - .extend(self.runtime_modules.keys().copied()); - Ok(()) - } - - async fn process_chunk_hash( - &self, - chunk_ukey: ChunkUkey, - plugin_driver: &SharedPluginDriver, - ) -> Result { - let mut hasher = RspackHash::from(&self.options.output); - if let Some(chunk) = self.chunk_by_ukey.get(&chunk_ukey) { - chunk.update_hash(&mut hasher, self); - } - plugin_driver - .compilation_hooks - .chunk_hash - .call(self, &chunk_ukey, &mut hasher) - .await?; - let chunk_hash = hasher.digest(&self.options.output.hash_digest); - - let mut content_hashes: HashMap = HashMap::default(); - plugin_driver - .compilation_hooks - .content_hash - .call(self, &chunk_ukey, &mut content_hashes) - .await?; - - let content_hashes = content_hashes - .into_iter() - .map(|(t, mut hasher)| { - chunk_hash.hash(&mut hasher); - (t, hasher.digest(&self.options.output.hash_digest)) - }) - .collect(); - - Ok(ChunkHashResult { - hash: chunk_hash, - content_hash: content_hashes, - }) - } - - #[instrument("Compilation:create_module_hashes", skip_all)] - pub async fn create_module_hashes(&mut self, modules: IdentifierSet) -> Result<()> { - let mg = self.get_module_graph(); - let chunk_graph = &self.chunk_graph; - let chunk_by_ukey = &self.chunk_by_ukey; - - let results = rspack_futures::scope::<_, Result<_>>(|token| { - for module_identifier in modules { - let s = unsafe { token.used((&*self, &mg, chunk_graph, chunk_by_ukey)) }; - s.spawn( - move |(compilation, mg, chunk_graph, chunk_by_ukey)| async move { - let mut hashes = RuntimeSpecMap::new(); - let module = mg - .module_by_identifier(&module_identifier) - .expect("should have module"); - for runtime in chunk_graph.get_module_runtimes_iter(module_identifier, chunk_by_ukey) { - let hash = module.get_runtime_hash(compilation, Some(runtime)).await?; - hashes.set(runtime.clone(), hash); - } - Ok((module_identifier, hashes)) - }, - ); - } - }) - .await - .into_iter() - .map(|r| r.to_rspack_result()) - .collect::>>()?; - - for result in results { - let (module, hashes) = result?; - if ChunkGraph::set_module_hashes(self, module, hashes) - && let Some(mut mutations) = self.incremental.mutations_write() - { - mutations.add(Mutation::ModuleSetHashes { module }); - } - } - Ok(()) - } - pub fn add_runtime_module( &mut self, chunk_ukey: &ChunkUkey, @@ -3206,11 +1440,6 @@ pub struct RenderManifestEntry { pub auxiliary: bool, } -pub struct ChunkHashResult { - pub hash: RspackHashDigest, - pub content_hash: ChunkContentHash, -} - #[cacheable] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] pub enum ManifestAssetType { diff --git a/crates/rspack_core/src/compilation/module_ids/mod.rs b/crates/rspack_core/src/compilation/module_ids/mod.rs new file mode 100644 index 000000000000..ecdf22998120 --- /dev/null +++ b/crates/rspack_core/src/compilation/module_ids/mod.rs @@ -0,0 +1,31 @@ +use super::*; +use crate::logger::Logger; + +pub async fn module_ids_pass( + compilation: &mut Compilation, + plugin_driver: SharedPluginDriver, +) -> Result<()> { + let logger = compilation.get_logger("rspack.Compilation"); + let start = logger.time("module ids"); + + // Check if MODULE_IDS pass is disabled, and clear artifact if needed + if !compilation + .incremental + .passes_enabled(IncrementalPasses::MODULE_IDS) + { + compilation.module_ids_artifact.clear(); + } + + let mut diagnostics = vec![]; + let mut module_ids_artifact = mem::take(&mut compilation.module_ids_artifact); + plugin_driver + .compilation_hooks + .module_ids + .call(compilation, &mut module_ids_artifact, &mut diagnostics) + .await + .map_err(|e| e.wrap_err("caused by plugins in Compilation.hooks.moduleIds"))?; + compilation.module_ids_artifact = module_ids_artifact; + compilation.extend_diagnostics(diagnostics); + logger.time_end(start); + Ok(()) +} diff --git a/crates/rspack_core/src/compilation/optimize_chunk_modules/mod.rs b/crates/rspack_core/src/compilation/optimize_chunk_modules/mod.rs new file mode 100644 index 000000000000..15b157d10de0 --- /dev/null +++ b/crates/rspack_core/src/compilation/optimize_chunk_modules/mod.rs @@ -0,0 +1,14 @@ +use super::*; + +pub async fn optimize_chunk_modules_pass( + compilation: &mut Compilation, + plugin_driver: SharedPluginDriver, +) -> Result<()> { + plugin_driver + .compilation_hooks + .optimize_chunk_modules + .call(compilation) + .await + .map(|_| ()) + .map_err(|e| e.wrap_err("caused by plugins in Compilation.hooks.optimizeChunkModules")) +} diff --git a/crates/rspack_core/src/compilation/optimize_chunks/mod.rs b/crates/rspack_core/src/compilation/optimize_chunks/mod.rs new file mode 100644 index 000000000000..6bc6a593c054 --- /dev/null +++ b/crates/rspack_core/src/compilation/optimize_chunks/mod.rs @@ -0,0 +1,17 @@ +use super::*; + +pub async fn optimize_chunks_pass( + compilation: &mut Compilation, + plugin_driver: SharedPluginDriver, +) -> Result<()> { + while matches!( + plugin_driver + .compilation_hooks + .optimize_chunks + .call(compilation) + .await + .map_err(|e| e.wrap_err("caused by plugins in Compilation.hooks.optimizeChunks"))?, + Some(true) + ) {} + Ok(()) +} diff --git a/crates/rspack_core/src/compilation/optimize_code_generation/mod.rs b/crates/rspack_core/src/compilation/optimize_code_generation/mod.rs new file mode 100644 index 000000000000..280b91cbb6ae --- /dev/null +++ b/crates/rspack_core/src/compilation/optimize_code_generation/mod.rs @@ -0,0 +1,18 @@ +use super::*; +use crate::logger::Logger; + +pub async fn optimize_code_generation_pass( + compilation: &mut Compilation, + plugin_driver: SharedPluginDriver, +) -> Result<()> { + let logger = compilation.get_logger("rspack.Compilation"); + let start = logger.time("optimize code generation"); + plugin_driver + .compilation_hooks + .optimize_code_generation + .call(compilation) + .await + .map_err(|e| e.wrap_err("caused by plugins in Compilation.hooks.optimizeCodeGeneration"))?; + logger.time_end(start); + Ok(()) +} diff --git a/crates/rspack_core/src/compilation/optimize_dependencies/mod.rs b/crates/rspack_core/src/compilation/optimize_dependencies/mod.rs new file mode 100644 index 000000000000..79f4ffc52bc5 --- /dev/null +++ b/crates/rspack_core/src/compilation/optimize_dependencies/mod.rs @@ -0,0 +1,39 @@ +use super::*; +use crate::logger::Logger; + +pub async fn optimize_dependencies_pass( + compilation: &mut Compilation, + plugin_driver: SharedPluginDriver, +) -> Result<()> { + let logger = compilation.get_logger("rspack.Compilation"); + let start = logger.time("optimize dependencies"); + // https://github.com/webpack/webpack/blob/d15c73469fd71cf98734685225250148b68ddc79/lib/Compilation.js#L2812-L2814 + + let mut diagnostics: Vec = vec![]; + let mut side_effects_optimize_artifact = compilation.side_effects_optimize_artifact.take(); + let mut build_module_graph_artifact = compilation.build_module_graph_artifact.take(); + while matches!( + plugin_driver + .compilation_hooks + .optimize_dependencies + .call( + compilation, + &mut side_effects_optimize_artifact, + &mut build_module_graph_artifact, + &mut diagnostics + ) + .await + .map_err(|e| e.wrap_err("caused by plugins in Compilation.hooks.optimizeDependencies"))?, + Some(true) + ) {} + compilation + .side_effects_optimize_artifact + .replace(side_effects_optimize_artifact); + compilation + .build_module_graph_artifact + .replace(build_module_graph_artifact); + compilation.extend_diagnostics(diagnostics); + + logger.time_end(start); + Ok(()) +} diff --git a/crates/rspack_core/src/compilation/optimize_modules/mod.rs b/crates/rspack_core/src/compilation/optimize_modules/mod.rs new file mode 100644 index 000000000000..72a6779165f3 --- /dev/null +++ b/crates/rspack_core/src/compilation/optimize_modules/mod.rs @@ -0,0 +1,25 @@ +use super::*; + +pub async fn optimize_modules_pass( + compilation: &mut Compilation, + plugin_driver: SharedPluginDriver, +) -> Result<()> { + let mut diagnostics = vec![]; + while matches!( + plugin_driver + .compilation_hooks + .optimize_modules + .call(compilation, &mut diagnostics) + .await + .map_err(|e| e.wrap_err("caused by plugins in Compilation.hooks.optimizeModules"))?, + Some(true) + ) {} + compilation.extend_diagnostics(diagnostics); + + plugin_driver + .compilation_hooks + .after_optimize_modules + .call(compilation) + .await + .map_err(|e| e.wrap_err("caused by plugins in Compilation.hooks.afterOptimizeModules")) +} diff --git a/crates/rspack_core/src/compilation/optimize_tree/mod.rs b/crates/rspack_core/src/compilation/optimize_tree/mod.rs new file mode 100644 index 000000000000..ff62eba916a2 --- /dev/null +++ b/crates/rspack_core/src/compilation/optimize_tree/mod.rs @@ -0,0 +1,13 @@ +use super::*; + +pub async fn optimize_tree_pass( + compilation: &mut Compilation, + plugin_driver: SharedPluginDriver, +) -> Result<()> { + plugin_driver + .compilation_hooks + .optimize_tree + .call(compilation) + .await + .map_err(|e| e.wrap_err("caused by plugins in Compilation.hooks.optimizeTree")) +} diff --git a/crates/rspack_core/src/compilation/process_assets/mod.rs b/crates/rspack_core/src/compilation/process_assets/mod.rs new file mode 100644 index 000000000000..3e3887944f9f --- /dev/null +++ b/crates/rspack_core/src/compilation/process_assets/mod.rs @@ -0,0 +1,43 @@ +use super::*; +use crate::logger::Logger; + +pub async fn process_assets_pass( + compilation: &mut Compilation, + plugin_driver: SharedPluginDriver, +) -> Result<()> { + let logger = compilation.get_logger("rspack.Compilation"); + let start = logger.time("process assets"); + compilation.process_assets(plugin_driver.clone()).await?; + logger.time_end(start); + + let start = logger.time("after process assets"); + compilation.after_process_assets(plugin_driver).await?; + logger.time_end(start); + Ok(()) +} + +impl Compilation { + #[instrument("Compilation:process_assets",target=TRACING_BENCH_TARGET, skip_all)] + async fn process_assets(&mut self, plugin_driver: SharedPluginDriver) -> Result<()> { + plugin_driver + .compilation_hooks + .process_assets + .call(self) + .await + .map_err(|e| e.wrap_err("caused by plugins in Compilation.hooks.processAssets")) + } + + #[instrument("Compilation:after_process_assets", skip_all)] + async fn after_process_assets(&mut self, plugin_driver: SharedPluginDriver) -> Result<()> { + let mut diagnostics: Vec = vec![]; + + let res = plugin_driver + .compilation_hooks + .after_process_assets + .call(self, &mut diagnostics) + .await; + + self.extend_diagnostics(diagnostics); + res + } +} diff --git a/crates/rspack_core/src/compilation/rspack_passes.md b/crates/rspack_core/src/compilation/rspack_passes.md new file mode 100644 index 000000000000..b849dd6a8545 --- /dev/null +++ b/crates/rspack_core/src/compilation/rspack_passes.md @@ -0,0 +1,63 @@ +# Compilation Passes Architecture + +This document describes the modular architecture of the compilation process in rspack. + +## Overview + +The compilation process is organized into independent modules, each responsible for a specific phase or pass. This modular design improves code maintainability, testability, and allows for better separation of concerns. + +## Module Structure + +``` +compilation/ +├── mod.rs # Main Compilation struct which exposes the public API +├── run_passes.rs # Pass driver invoked from Compiler that runs make + seal passes +├── build_module_graph/ # Module graph construction +│ └── finish_module/ # Finalize module graph, async modules, dependency diagnostics +├── optimize_dependencies/ # optimizeDependencies hook + side effects artifact +├── build_chunk_graph/ # Chunk graph construction (code splitting cache + pass wrapper) +├── optimize_modules/ # optimizeModules + afterOptimizeModules hooks +├── optimize_chunks/ # optimizeChunks hook +├── optimize_tree/ # optimizeTree hook +├── optimize_chunk_modules # optimizeChunkModules hook +├── module_ids/ # Module ID assignment + diagnostics +├── chunk_ids/ # Chunk ID assignment + diagnostics +├── assign_runtime_ids/ # Runtime ID assignment for runtime chunks +├── optimize_code_generation/ # optimizeCodeGeneration hook +├── create_module_hashes/ # Module hash computation (incremental aware) +├── code_generation/ # Module codegen + afterCodeGeneration hook +├── runtime_requirements/ # Module/chunk/tree runtime requirements + runtime modules +├── create_hash/ # Chunk hashing, runtime module hashes, full hash + runtime module codegen +├── create_module_assets/ # Emit module-declared assets and mark chunk auxiliary files +├── create_chunk_assets/ # Render manifests and emit chunk assets +├── process_assets/ # processAssets + afterProcessAssets hooks +└── after_seal/ # afterSeal hook +``` + +## Pass Entry + +- `Compiler::compile` builds `CompilationParams`, fires `thisCompilation` then `compilation` compiler hooks (binding safety for JS), and delegates to `Compilation::run_passes`. +- `Compilation::run_passes` performs the make and seal stages using the order below. + +## Pass Order (Compilation::run_passes) + +`run_passes` orchestrates the full pipeline (make + seal) in this order: + +1. Make: `make` hook → `build_module_graph` → `finish_make` hook → `finish_build_module_graph` +2. Collect make diagnostics (`collect_build_module_graph_effects`) +3. Incremental checkpoint (`module_graph`), freeze module static cache in production +4. Seal kickoff: `CompilationHooks::seal` +5. `optimize_dependencies_pass` +6. `build_chunk_graph_pass` → `optimize_modules_pass` → `optimize_chunks_pass` +7. `optimize_tree_pass` → `optimize_chunk_modules_pass` +8. `module_ids_pass` → `chunk_ids_pass` → `assign_runtime_ids` +9. `optimize_code_generation_pass` +10. `create_module_hashes_pass` +11. `code_generation_pass` +12. `runtime_requirements_pass` +13. `create_hash_pass` (also runs runtime module code generation) +14. `create_module_assets_pass` +15. `create_chunk_assets_pass` +16. `process_assets_pass` +17. `after_seal_pass` +18. Unfreeze module static cache in production diff --git a/crates/rspack_core/src/compilation/run_passes.rs b/crates/rspack_core/src/compilation/run_passes.rs new file mode 100644 index 000000000000..d6be8a9c4fba --- /dev/null +++ b/crates/rspack_core/src/compilation/run_passes.rs @@ -0,0 +1,113 @@ +use super::{ + after_seal::after_seal_pass, assign_runtime_ids::assign_runtime_ids, + build_chunk_graph::pass::build_chunk_graph_pass, chunk_ids::chunk_ids_pass, + code_generation::code_generation_pass, create_chunk_assets::create_chunk_assets_pass, + create_hash::create_hash_pass, create_module_assets::create_module_assets_pass, + create_module_hashes::create_module_hashes_pass, module_ids::module_ids_pass, + optimize_chunk_modules::optimize_chunk_modules_pass, optimize_chunks::optimize_chunks_pass, + optimize_code_generation::optimize_code_generation_pass, + optimize_dependencies::optimize_dependencies_pass, optimize_modules::optimize_modules_pass, + optimize_tree::optimize_tree_pass, process_assets::process_assets_pass, + runtime_requirements::runtime_requirements_pass, *, +}; +use crate::{ + Compilation, SharedPluginDriver, cache::Cache, incremental::IncrementalPasses, logger::Logger, +}; + +impl Compilation { + pub async fn run_passes( + &mut self, + plugin_driver: SharedPluginDriver, + cache: &mut dyn Cache, + ) -> Result<()> { + let logger = self.get_logger("rspack.Compiler"); + + let make_start = logger.time("make"); + let make_hook_start = logger.time("make hook"); + cache + .before_build_module_graph(&mut self.build_module_graph_artifact) + .await; + + plugin_driver.compiler_hooks.make.call(self).await?; + logger.time_end(make_hook_start); + self.build_module_graph().await?; + logger.time_end(make_start); + + let start = logger.time("finish make hook"); + plugin_driver.compiler_hooks.finish_make.call(self).await?; + logger.time_end(start); + + let start = logger.time("finish compilation"); + self.finish_build_module_graph().await?; + cache + .after_build_module_graph(&self.build_module_graph_artifact) + .await; + logger.time_end(start); + + let dependencies_diagnostics_artifact = self.dependencies_diagnostics_artifact.clone(); + let async_modules_artifact = self.async_modules_artifact.clone(); + let diagnostics = self + .collect_build_module_graph_effects( + &mut dependencies_diagnostics_artifact.borrow_mut(), + &mut async_modules_artifact.borrow_mut(), + ) + .await?; + self.extend_diagnostics(diagnostics); + + // add a checkpoint here since we may modify module graph later in incremental compilation + // and we can recover to this checkpoint in the future + if self.incremental.passes_enabled(IncrementalPasses::MAKE) { + self.build_module_graph_artifact.module_graph.checkpoint(); + } + + if !self.options.mode.is_development() { + self.module_static_cache_artifact.freeze(); + } + + #[cfg(feature = "debug_tool")] + { + use rspack_util::debug_tool::wait_for_signal; + wait_for_signal("seal compilation"); + } + let logger = self.get_logger("rspack.Compilation"); + // https://github.com/webpack/webpack/blob/main/lib/Compilation.js#L2809 + plugin_driver + .compilation_hooks + .seal + .call(self) + .await + .map_err(|e| e.wrap_err("caused by plugins in Compilation.hooks.seal"))?; + + optimize_dependencies_pass(self, plugin_driver.clone()).await?; + + let create_chunks_start = logger.time("create chunks"); + build_chunk_graph_pass(self).await?; + optimize_modules_pass(self, plugin_driver.clone()).await?; + optimize_chunks_pass(self, plugin_driver.clone()).await?; + logger.time_end(create_chunks_start); + + let optimize_start = logger.time("optimize"); + optimize_tree_pass(self, plugin_driver.clone()).await?; + optimize_chunk_modules_pass(self, plugin_driver.clone()).await?; + logger.time_end(optimize_start); + + module_ids_pass(self, plugin_driver.clone()).await?; + chunk_ids_pass(self, plugin_driver.clone()).await?; + assign_runtime_ids(self); + + optimize_code_generation_pass(self, plugin_driver.clone()).await?; + create_module_hashes_pass(self).await?; + code_generation_pass(self, plugin_driver.clone()).await?; + runtime_requirements_pass(self, plugin_driver.clone()).await?; + create_hash_pass(self, plugin_driver.clone()).await?; + create_module_assets_pass(self, plugin_driver.clone()).await?; + create_chunk_assets_pass(self, plugin_driver.clone()).await?; + process_assets_pass(self, plugin_driver.clone()).await?; + after_seal_pass(self, plugin_driver).await?; + + if !self.options.mode.is_development() { + self.module_static_cache_artifact.unfreeze(); + } + Ok(()) + } +} diff --git a/crates/rspack_core/src/compilation/runtime_requirements/mod.rs b/crates/rspack_core/src/compilation/runtime_requirements/mod.rs new file mode 100644 index 000000000000..7892b242edb0 --- /dev/null +++ b/crates/rspack_core/src/compilation/runtime_requirements/mod.rs @@ -0,0 +1,404 @@ +use super::*; +use crate::logger::Logger; + +pub async fn runtime_requirements_pass( + compilation: &mut Compilation, + plugin_driver: SharedPluginDriver, +) -> Result<()> { + let logger = compilation.get_logger("rspack.Compilation"); + let start = logger.time("runtime requirements"); + let process_runtime_requirements_modules = if let Some(mutations) = compilation + .incremental + .mutations_read(IncrementalPasses::MODULES_RUNTIME_REQUIREMENTS) + && !compilation.cgm_runtime_requirements_artifact.is_empty() + { + let revoked_modules = mutations.iter().filter_map(|mutation| match mutation { + Mutation::ModuleRemove { module } => Some(*module), + _ => None, + }); + for revoked_module in revoked_modules { + compilation + .cgm_runtime_requirements_artifact + .remove(&revoked_module); + } + let modules: IdentifierSet = mutations + .iter() + .filter_map(|mutation| match mutation { + Mutation::ModuleSetHashes { module } => Some(*module), + _ => None, + }) + .collect(); + let logger = compilation.get_logger("rspack.incremental.modulesRuntimeRequirements"); + logger.log(format!( + "{} modules are affected, {} in total", + modules.len(), + compilation.get_module_graph().modules().len() + )); + modules + } else { + compilation.cgm_runtime_requirements_artifact = Default::default(); + compilation + .get_module_graph() + .modules() + .keys() + .copied() + .collect() + }; + compilation + .process_modules_runtime_requirements( + process_runtime_requirements_modules, + plugin_driver.clone(), + ) + .await?; + let runtime_chunks = compilation.get_chunk_graph_entries().collect(); + + // Check if CHUNKS_RUNTIME_REQUIREMENTS pass is disabled, and clear artifact if needed + if !compilation + .incremental + .passes_enabled(IncrementalPasses::CHUNKS_RUNTIME_REQUIREMENTS) + { + compilation.cgc_runtime_requirements_artifact.clear(); + } + + let process_runtime_requirements_chunks = if let Some(mutations) = compilation + .incremental + .mutations_read(IncrementalPasses::CHUNKS_RUNTIME_REQUIREMENTS) + && !compilation.cgc_runtime_requirements_artifact.is_empty() + { + let removed_chunks = mutations.iter().filter_map(|mutation| match mutation { + Mutation::ChunkRemove { chunk } => Some(chunk), + _ => None, + }); + for removed_chunk in removed_chunks { + compilation + .cgc_runtime_requirements_artifact + .remove(removed_chunk); + } + let affected_chunks = mutations.get_affected_chunks_with_chunk_graph(compilation); + for affected_chunk in &affected_chunks { + compilation + .cgc_runtime_requirements_artifact + .remove(affected_chunk); + } + for runtime_chunk in &runtime_chunks { + compilation + .cgc_runtime_requirements_artifact + .remove(runtime_chunk); + } + compilation + .cgc_runtime_requirements_artifact + .retain(|chunk, _| compilation.chunk_by_ukey.contains(chunk)); + let logger = compilation.get_logger("rspack.incremental.chunksRuntimeRequirements"); + logger.log(format!( + "{} chunks are affected, {} in total", + affected_chunks.len(), + compilation.chunk_by_ukey.len() + )); + affected_chunks + } else { + compilation.chunk_by_ukey.keys().copied().collect() + }; + compilation + .process_chunks_runtime_requirements( + process_runtime_requirements_chunks, + runtime_chunks, + plugin_driver.clone(), + ) + .await?; + logger.time_end(start); + Ok(()) +} + +macro_rules! process_runtime_requirement_hook_macro { + ($name: ident, $s: ty, $c: ty) => { + async fn $name( + self: $s, + requirements: &mut RuntimeGlobals, + call_hook: impl for<'a> Fn( + $c, + &'a RuntimeGlobals, + &'a RuntimeGlobals, + &'a mut RuntimeGlobals, + ) -> BoxFuture<'a, Result<()>>, + ) -> Result<()> { + let mut runtime_requirements_mut = *requirements; + let mut runtime_requirements; + + loop { + runtime_requirements = runtime_requirements_mut; + runtime_requirements_mut = RuntimeGlobals::default(); + // runtime_requirements: rt_requirements of last time + // runtime_requirements_mut: changed rt_requirements + // requirements: all rt_requirements + call_hook( + self, + requirements, + &runtime_requirements, + &mut runtime_requirements_mut, + ) + .await?; + + // check if we have changes to runtime_requirements + runtime_requirements_mut = + runtime_requirements_mut.difference(requirements.intersection(runtime_requirements_mut)); + if runtime_requirements_mut.is_empty() { + break; + } else { + requirements.insert(runtime_requirements_mut); + } + } + Ok(()) + } + }; +} + +impl Compilation { + #[instrument("Compilation:process_modules_runtime_requirements", skip_all)] + pub async fn process_modules_runtime_requirements( + &mut self, + modules: IdentifierSet, + plugin_driver: SharedPluginDriver, + ) -> Result<()> { + let logger = self.get_logger("rspack.Compilation"); + let start = logger.time("runtime requirements.modules"); + + let module_results = rspack_futures::scope::<_, Result<_>>(|token| { + modules + .into_iter() + .filter(|module| self.chunk_graph.get_number_of_module_chunks(*module) > 0) + .for_each(|module| { + let s = unsafe { token.used((&self, &plugin_driver)) }; + s.spawn(move |(compilation, plugin_driver)| async move { + let mut map = RuntimeSpecMap::new(); + let runtimes = compilation + .chunk_graph + .get_module_runtimes_iter(module, &compilation.chunk_by_ukey); + for runtime in runtimes { + let runtime_requirements = compilation + .old_cache + .process_runtime_requirements_occasion + .use_cache(module, runtime, compilation, || async { + let mut runtime_requirements = compilation + .code_generation_results + .get_runtime_requirements(&module, Some(runtime)); + + plugin_driver + .compilation_hooks + .additional_module_runtime_requirements + .call(compilation, &module, &mut runtime_requirements) + .await + .map_err(|e| e.wrap_err("caused by plugins in Compilation.hooks.additionalModuleRuntimeRequirements"))?; + + compilation + .process_runtime_requirement_hook(&mut runtime_requirements, { + let plugin_driver = plugin_driver.clone(); + move |compilation, + all_runtime_requirements, + runtime_requirements, + runtime_requirements_mut| { + Box::pin({ + let plugin_driver = plugin_driver.clone(); + async move { + plugin_driver + .compilation_hooks + .runtime_requirement_in_module + .call( + compilation, + &module, + all_runtime_requirements, + runtime_requirements, + runtime_requirements_mut, + ) + .await + .map_err(|e| e.wrap_err("caused by plugins in Compilation.hooks.runtimeRequirementInModule"))?; + Ok(()) + }}) + } + }) + .await?; + Ok(runtime_requirements) + }) + .await?; + map.set(runtime.clone(), runtime_requirements); + } + Ok((module, map)) + }); + }); + }) + .await + .into_iter() + .map(|r| r.to_rspack_result()) + .collect::>>()?; + + for entry in module_results { + let (module, map) = entry?; + ChunkGraph::set_module_runtime_requirements(self, module, map); + } + logger.time_end(start); + Ok(()) + } + + #[instrument(name = "Compilation:process_chunks_runtime_requirements", target=TRACING_BENCH_TARGET skip_all)] + pub async fn process_chunks_runtime_requirements( + &mut self, + chunks: UkeySet, + entries: UkeySet, + plugin_driver: SharedPluginDriver, + ) -> Result<()> { + let logger = self.get_logger("rspack.Compilation"); + let start = logger.time("runtime requirements.chunks"); + let chunk_requirements = chunks + .iter() + .chain(entries.iter()) + .par_bridge() + .map(|chunk_ukey| { + let mut set = RuntimeGlobals::default(); + for mid in self.chunk_graph.get_chunk_modules_identifier(chunk_ukey) { + let chunk = self.chunk_by_ukey.expect_get(chunk_ukey); + if let Some(runtime_requirements) = + ChunkGraph::get_module_runtime_requirements(self, *mid, chunk.runtime()) + { + set.insert(*runtime_requirements); + } + } + + (*chunk_ukey, set) + }) + .collect::>(); + + for (chunk_ukey, mut set) in chunk_requirements { + plugin_driver + .compilation_hooks + .additional_chunk_runtime_requirements + .call(self, &chunk_ukey, &mut set) + .await + .map_err(|e| { + e.wrap_err("caused by plugins in Compilation.hooks.additionalChunkRuntimeRequirements") + })?; + + self + .process_runtime_requirement_hook_mut(&mut set, { + let plugin_driver = plugin_driver.clone(); + move |compilation, + all_runtime_requirements, + runtime_requirements, + runtime_requirements_mut| { + Box::pin({ + let plugin_driver = plugin_driver.clone(); + async move { + plugin_driver + .compilation_hooks + .runtime_requirement_in_chunk + .call( + compilation, + &chunk_ukey, + all_runtime_requirements, + runtime_requirements, + runtime_requirements_mut, + ) + .await + .map_err(|e| { + e.wrap_err("caused by plugins in Compilation.hooks.runtimeRequirementInChunk") + })?; + Ok(()) + } + }) + } + }) + .await?; + + ChunkGraph::set_chunk_runtime_requirements(self, chunk_ukey, set); + } + logger.time_end(start); + + let start = logger.time("runtime requirements.entries"); + for &entry_ukey in &entries { + let entry = self.chunk_by_ukey.expect_get(&entry_ukey); + let mut set = RuntimeGlobals::default(); + for chunk_ukey in entry + .get_all_referenced_chunks(&self.chunk_group_by_ukey) + .iter() + { + let runtime_requirements = ChunkGraph::get_chunk_runtime_requirements(self, chunk_ukey); + set.insert(*runtime_requirements); + } + + plugin_driver + .compilation_hooks + .additional_tree_runtime_requirements + .call(self, &entry_ukey, &mut set) + .await + .map_err(|e| { + e.wrap_err("caused by plugins in Compilation.hooks.additionalTreeRuntimeRequirements") + })?; + + self + .process_runtime_requirement_hook_mut(&mut set, { + let plugin_driver = plugin_driver.clone(); + move |compilation, + all_runtime_requirements, + runtime_requirements, + runtime_requirements_mut| { + Box::pin({ + let plugin_driver = plugin_driver.clone(); + async move { + plugin_driver + .compilation_hooks + .runtime_requirement_in_tree + .call( + compilation, + &entry_ukey, + all_runtime_requirements, + runtime_requirements, + runtime_requirements_mut, + ) + .await + .map_err(|e| { + e.wrap_err("caused by plugins in Compilation.hooks.runtimeRequirementInTree") + })?; + Ok(()) + } + }) + } + }) + .await?; + + ChunkGraph::set_tree_runtime_requirements(self, entry_ukey, set); + } + + // NOTE: webpack runs hooks.runtime_module in compilation.add_runtime_module + // and overwrite the runtime_module.generate() to get new source in create_chunk_assets + // this needs full runtime requirements, so run hooks.runtime_module after runtime_requirements_in_tree + let mut runtime_modules = mem::take(&mut self.runtime_modules); + for entry_ukey in &entries { + let runtime_module_ids: Vec<_> = self + .chunk_graph + .get_chunk_runtime_modules_iterable(entry_ukey) + .copied() + .collect(); + for runtime_module_id in runtime_module_ids { + plugin_driver + .compilation_hooks + .runtime_module + .call(self, &runtime_module_id, entry_ukey, &mut runtime_modules) + .await + .map_err(|e| e.wrap_err("caused by plugins in Compilation.hooks.runtimeModule"))?; + } + } + self.runtime_modules = runtime_modules; + + logger.time_end(start); + Ok(()) + } + + process_runtime_requirement_hook_macro!( + process_runtime_requirement_hook, + &Compilation, + &'a Compilation + ); + process_runtime_requirement_hook_macro!( + process_runtime_requirement_hook_mut, + &mut Compilation, + &'a mut Compilation + ); +} diff --git a/crates/rspack_core/src/compiler/mod.rs b/crates/rspack_core/src/compiler/mod.rs index 9355e8d1e2b8..5ae6b5e7021e 100644 --- a/crates/rspack_core/src/compiler/mod.rs +++ b/crates/rspack_core/src/compiler/mod.rs @@ -15,12 +15,13 @@ use tracing::instrument; pub use self::rebuild::CompilationRecords; use crate::{ BoxPlugin, CleanOptions, Compilation, CompilationAsset, CompilerOptions, CompilerPlatform, - ContextModuleFactory, Filename, KeepPattern, Logger, NormalModuleFactory, PluginDriver, - ResolverFactory, SharedPluginDriver, + ContextModuleFactory, Filename, KeepPattern, NormalModuleFactory, PluginDriver, ResolverFactory, + SharedPluginDriver, cache::{Cache, new_cache}, compilation::build_module_graph::ModuleExecutor, fast_set, include_hash, incremental::{Incremental, IncrementalPasses}, + logger::Logger, old_cache::Cache as OldCache, trim_dir, }; @@ -257,13 +258,10 @@ impl Compiler { Ok(()) } - async fn build_module_graph(&mut self) -> Result<()> { + #[instrument("Compiler:compile", target=TRACING_BENCH_TARGET,skip_all)] + async fn compile(&mut self) -> Result<()> { let mut compilation_params = self.new_compilation_params(); - // FOR BINDING SAFETY: - // Make sure `thisCompilation` hook was called for each `JsCompilation` update before any access to it. - // `JsCompiler` tapped `thisCompilation` to update the `JsCompilation` on the JavaScript side. - // Otherwise, trying to access the old native `JsCompilation` would cause undefined behavior - // as the previous instance might get dropped. + // Make sure `thisCompilation` is emitted before any JS side access to `JsCompilation`. self .plugin_driver .compiler_hooks @@ -277,65 +275,12 @@ impl Compiler { .call(&mut self.compilation, &mut compilation_params) .await?; - let logger = self.compilation.get_logger("rspack.Compiler"); - let make_start = logger.time("make"); - let make_hook_start = logger.time("make hook"); - self - .cache - .before_build_module_graph(&mut self.compilation.build_module_graph_artifact) - .await; - - self - .plugin_driver - .compiler_hooks - .make - .call(&mut self.compilation) - .await?; - logger.time_end(make_hook_start); - self.compilation.build_module_graph().await?; - logger.time_end(make_start); - - let start = logger.time("finish make hook"); - self - .plugin_driver - .compiler_hooks - .finish_make - .call(&mut self.compilation) - .await?; - logger.time_end(start); - - let start = logger.time("finish compilation"); - self.compilation.finish_build_module_graph().await?; - self - .cache - .after_build_module_graph(&self.compilation.build_module_graph_artifact) - .await; - - logger.time_end(start); - Ok(()) - } - #[instrument("Compiler:compile", target=TRACING_BENCH_TARGET,skip_all)] - async fn compile(&mut self) -> Result<()> { let logger = self.compilation.get_logger("rspack.Compiler"); let start = logger.time("seal compilation"); - #[cfg(feature = "debug_tool")] - { - use rspack_util::debug_tool::wait_for_signal; - wait_for_signal("seal compilation"); - } - self.build_module_graph().await?; - let dependencies_diagnostics_artifact = - self.compilation.dependencies_diagnostics_artifact.clone(); - let async_modules_artifact = self.compilation.async_modules_artifact.clone(); - let diagnostics = self + self .compilation - .collect_build_module_graph_effects( - &mut dependencies_diagnostics_artifact.borrow_mut(), - &mut async_modules_artifact.borrow_mut(), - ) + .run_passes(self.plugin_driver.clone(), &mut *self.cache) .await?; - self.compilation.extend_diagnostics(diagnostics); - self.compilation.seal(self.plugin_driver.clone()).await?; logger.time_end(start); // Consume plugin driver diagnostic From ad662bcbafd98cf742e1b5e6467df6e189ab6256 Mon Sep 17 00:00:00 2001 From: pshu Date: Thu, 15 Jan 2026 13:42:07 +0800 Subject: [PATCH 62/87] refactor(lazy-compilation): use POST request to transfer ids of active modules (#12678) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: use post transfer module ids * test: skip lazy active method * test: add lazy post request help * test: add large module id container * test: add case introduction * refactor: remove about controller * test: we are using post method now * refactor: rename * fix body parser (vibe-kanban 09797829) 1. 如果其他中间件一个解析好了body,并挂载在req.body 上的花就直直接使用 req.body 2. packages/rspack/src/builtin-plugin/lazy-compilation/middleware.ts body 解析的时候不能简单的使用 string 的拼接,需要考虑多字节符号的截断的问题。 * refactor read module ids from body (vibe-kanban a7874ac1) packages/rspack/src/builtin-plugin/lazy-compilation/middleware.ts 当req.body 非空时,直接假body中时一组 module ids,如果没有 body 自行拼接完,之后也 parse json string,返回 module ids 数组 * refactor: downgrading to lower web api * test: ✅ add lazy compilation active cors cases * chore: update test case doc * fix: we all need cors header no matter is simple request or not * refactor:delete cors header setting * refactor: set cors header should set by user * Update packages/rspack/hot/lazy-compilation-web.js Co-authored-by: neverland * test: fix case name * chore: api-extract update * fix: memory leak of requst listeners * refactor: remove event source handle logic * fix: jsdom XMLHTTPRequets need strict cors header * refactor: node lazy compilation client use post too --------- Co-authored-by: neverland --- AGENTS.md | 2 + .../plugin/lazy-compilation-test-plugin.ts | 3 + .../rspack-test-tools/src/runner/web/index.ts | 7 +- packages/rspack/hot/lazy-compilation-node.js | 124 +++++++++---- packages/rspack/hot/lazy-compilation-web.js | 96 ++++++---- .../lazy-compilation/middleware.ts | 96 ++++++++-- .../active-lots-modules/index.test.ts | 8 + .../active-lots-modules/rspack.config.js | 43 +++++ .../lazy-compilation/cross-origin/README.md | 46 +++++ .../cross-origin/index.test.ts | 170 ++++++++++++++++++ .../cross-origin/rspack.config.js | 24 +++ .../cross-origin/src/component.js | 3 + .../cross-origin/src/index.js | 9 + .../custom-prefix/index.test.ts | 4 +- 14 files changed, 548 insertions(+), 87 deletions(-) create mode 100644 tests/e2e/cases/lazy-compilation/active-lots-modules/index.test.ts create mode 100644 tests/e2e/cases/lazy-compilation/active-lots-modules/rspack.config.js create mode 100644 tests/e2e/cases/lazy-compilation/cross-origin/README.md create mode 100644 tests/e2e/cases/lazy-compilation/cross-origin/index.test.ts create mode 100644 tests/e2e/cases/lazy-compilation/cross-origin/rspack.config.js create mode 100644 tests/e2e/cases/lazy-compilation/cross-origin/src/component.js create mode 100644 tests/e2e/cases/lazy-compilation/cross-origin/src/index.js diff --git a/AGENTS.md b/AGENTS.md index 5ad62c3c2ade..8c92bc2cebb4 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -36,6 +36,8 @@ Rspack is a high-performance JavaScript bundler written in Rust that offers stro - Update snapshots: `npm run test -- -u` - Filter tests: `npm run test -- -t configCases/asset` +Depends on what you have modified, you need to rebuild by `pnpm run build:js` or `pnpm run build:binding:dev` or `pnpm run build:cli:dev` first, then run testing commands to verify the modification. + ## Debugging - **VS Code**: `.vscode/launch.json` with `Debug Rspack` and `Attach` options diff --git a/packages/rspack-test-tools/src/plugin/lazy-compilation-test-plugin.ts b/packages/rspack-test-tools/src/plugin/lazy-compilation-test-plugin.ts index be255bd0a34a..b70a09eadedf 100644 --- a/packages/rspack-test-tools/src/plugin/lazy-compilation-test-plugin.ts +++ b/packages/rspack-test-tools/src/plugin/lazy-compilation-test-plugin.ts @@ -38,6 +38,9 @@ export class LazyCompilationTestPlugin { resolve(null); }); server.on('request', (req, res) => { + // Set CORS headers for jsdom's XMLHttpRequest + res.setHeader('Access-Control-Allow-Origin', '*'); + middleware(req, res, () => {}); }); server.on('connection', (socket) => { diff --git a/packages/rspack-test-tools/src/runner/web/index.ts b/packages/rspack-test-tools/src/runner/web/index.ts index eff92d3d4426..aa1f1ecbb37c 100644 --- a/packages/rspack-test-tools/src/runner/web/index.ts +++ b/packages/rspack-test-tools/src/runner/web/index.ts @@ -175,7 +175,12 @@ export class WebRunner extends NodeRunner { protected createBaseModuleScope() { const moduleScope = super.createBaseModuleScope(); moduleScope.EventSource = EventSource; - moduleScope.fetch = async (url: string) => { + moduleScope.fetch = async (url: string, options: any) => { + // For Lazy Compilation Proxy the POST request to the real dev server. + if (options?.method === 'POST') { + return fetch(url, options as any); + } + try { const filePath = this.urlToPath(url); this.log(`fetch: ${url} -> ${filePath}`); diff --git a/packages/rspack/hot/lazy-compilation-node.js b/packages/rspack/hot/lazy-compilation-node.js index 9ecf07ab958d..2bd57fec8d90 100644 --- a/packages/rspack/hot/lazy-compilation-node.js +++ b/packages/rspack/hot/lazy-compilation-node.js @@ -1,4 +1,79 @@ var urlBase = decodeURIComponent(__resourceQuery.slice(1)); +var compiling = new Set(); +var errorHandlers = new Set(); + +/** @type {import("http").ClientRequest | undefined} */ +var pendingRequest; +/** @type {boolean} */ +var hasPendingUpdate = false; + +function sendRequest() { + if (compiling.size === 0) { + hasPendingUpdate = false; + return; + } + + var modules = Array.from(compiling); + var data = modules.join('\n'); + + var httpModule = urlBase.startsWith('https') + ? require('https') + : require('http'); + + var request = httpModule.request( + urlBase, + { + method: 'POST', + agent: false, + headers: { + 'Content-Type': 'text/plain', + }, + }, + function (res) { + pendingRequest = undefined; + if (res.statusCode < 200 || res.statusCode >= 300) { + var error = new Error( + 'Problem communicating active modules to the server: HTTP ' + + res.statusCode, + ); + errorHandlers.forEach(function (onError) { + onError(error); + }); + } + // Consume response data to free up memory + res.resume(); + if (hasPendingUpdate) { + hasPendingUpdate = false; + sendRequest(); + } + }, + ); + + pendingRequest = request; + + request.on('error', function (err) { + pendingRequest = undefined; + var error = new Error( + 'Problem communicating active modules to the server: ' + err.message, + ); + errorHandlers.forEach(function (onError) { + onError(error); + }); + }); + + request.write(data); + request.end(); +} + +function sendActiveRequest() { + hasPendingUpdate = true; + + // If no request is pending, start one + if (!pendingRequest) { + hasPendingUpdate = false; + sendRequest(); + } +} /** * @param {{ data: string, onError: (err: Error) => void, active: boolean, module: module }} options options @@ -9,42 +84,23 @@ exports.activate = function (options) { var onError = options.onError; var active = options.active; var module = options.module; - /** @type {import("http").IncomingMessage} */ - var response; - var request = ( - urlBase.startsWith('https') ? require('https') : require('http') - ).request( - urlBase + encodeURIComponent(data), - { - agent: false, - headers: { accept: 'text/event-stream' }, - }, - function (res) { - response = res; - response.on('error', errorHandler); - if (!active && !module.hot) { - console.log( - 'Hot Module Replacement is not enabled. Waiting for process restart...', - ); - } - }, - ); - /** - * @param {Error} err error - */ - function errorHandler(err) { - err.message = - 'Problem communicating active modules to the server' + - (err.message ? ': ' + err.message : '') + - '\nRequest: ' + - urlBase + - data; - onError(err); + errorHandlers.add(onError); + + if (!compiling.has(data)) { + compiling.add(data); + sendActiveRequest(); } - request.on('error', errorHandler); - request.end(); + + if (!active && !module.hot) { + console.log( + 'Hot Module Replacement is not enabled. Waiting for process restart...', + ); + } + return function () { - response.destroy(); + errorHandlers.delete(onError); + compiling.delete(data); + sendActiveRequest(); }; }; diff --git a/packages/rspack/hot/lazy-compilation-web.js b/packages/rspack/hot/lazy-compilation-web.js index 28027edaa777..e49ff2bcb18f 100644 --- a/packages/rspack/hot/lazy-compilation-web.js +++ b/packages/rspack/hot/lazy-compilation-web.js @@ -1,47 +1,73 @@ -if (typeof EventSource !== 'function') { +if (typeof XMLHttpRequest === 'undefined') { throw new Error( - "Environment doesn't support lazy compilation (requires EventSource)", + "Environment doesn't support lazy compilation (requires XMLHttpRequest)", ); } var urlBase = decodeURIComponent(__resourceQuery.slice(1)); -/** @type {EventSource | undefined} */ -var activeEventSource; var compiling = new Set(); var errorHandlers = new Set(); -var updateEventSource = function updateEventSource() { - if (activeEventSource) activeEventSource.close(); - if (compiling.size) { - activeEventSource = new EventSource( - urlBase + - Array.from(compiling, function (module) { - return encodeURIComponent(module); - }).join('@'), - ); - /** - * @this {EventSource} - * @param {Event & { message?: string, filename?: string, lineno?: number, colno?: number, error?: Error }} event event - */ - activeEventSource.onerror = function (event) { - errorHandlers.forEach(function (onError) { - onError( - new Error( - 'Problem communicating active modules to the server' + - (event.message ? `: ${event.message} ` : '') + - (event.filename ? `: ${event.filename} ` : '') + - (event.lineno ? `: ${event.lineno} ` : '') + - (event.colno ? `: ${event.colno} ` : '') + - (event.error ? `: ${event.error}` : ''), - ), - ); - }); - }; - } else { - activeEventSource = undefined; +/** @type {XMLHttpRequest | undefined} */ +var pendingXhr; +/** @type {boolean} */ +var hasPendingUpdate = false; + +var sendRequest = function sendRequest() { + if (compiling.size === 0) { + hasPendingUpdate = false; + return; } + + var modules = Array.from(compiling); + var data = modules.join('\n'); + + var xhr = new XMLHttpRequest(); + pendingXhr = xhr; + xhr.open('POST', urlBase, true); + // text/plain Content-Type is simple request header + xhr.setRequestHeader('Content-Type', 'text/plain'); + + xhr.onreadystatechange = function () { + if (xhr.readyState === 4) { + pendingXhr = undefined; + if (xhr.status < 200 || xhr.status >= 300) { + var error = new Error( + 'Problem communicating active modules to the server: HTTP ' + + xhr.status, + ); + errorHandlers.forEach(function (onError) { + onError(error); + }); + } + if (hasPendingUpdate) { + hasPendingUpdate = false; + sendRequest(); + } + } + }; + + xhr.onerror = function () { + pendingXhr = undefined; + var error = new Error('Problem communicating active modules to the server'); + errorHandlers.forEach(function (onError) { + onError(error); + }); + }; + + xhr.send(data); }; +function sendActiveRequest() { + hasPendingUpdate = true; + + // If no request is pending, start one + if (!pendingXhr) { + hasPendingUpdate = false; + sendRequest(); + } +} + /** * @param {{ data: string, onError: (err: Error) => void, active: boolean, module: module }} options options * @returns {() => void} function to destroy response @@ -55,7 +81,7 @@ exports.activate = function (options) { if (!compiling.has(data)) { compiling.add(data); - updateEventSource(); + sendActiveRequest(); } if (!active && !module.hot) { @@ -67,6 +93,6 @@ exports.activate = function (options) { return function () { errorHandlers.delete(onError); compiling.delete(data); - updateEventSource(); + sendActiveRequest(); }; }; diff --git a/packages/rspack/src/builtin-plugin/lazy-compilation/middleware.ts b/packages/rspack/src/builtin-plugin/lazy-compilation/middleware.ts index 7a5a243a59da..d1778752b41d 100644 --- a/packages/rspack/src/builtin-plugin/lazy-compilation/middleware.ts +++ b/packages/rspack/src/builtin-plugin/lazy-compilation/middleware.ts @@ -88,7 +88,6 @@ export const lazyCompilationMiddleware = ( } const options = { - // TODO: remove this when experiments.lazyCompilation is removed ...c.options.experiments.lazyCompilation, ...c.options.lazyCompilation, }; @@ -173,7 +172,69 @@ function applyPlugin( plugin.apply(compiler); } -// used for reuse code, do not export this +function readModuleIdsFromBody( + req: IncomingMessage & { body?: unknown }, +): Promise { + // If body is already parsed by another middleware, use it directly + if (req.body !== undefined) { + if (Array.isArray(req.body)) { + return Promise.resolve(req.body); + } + if (typeof req.body === 'string') { + return Promise.resolve(req.body.split('\n').filter(Boolean)); + } + throw new Error('Invalid body type'); + } + + return new Promise((resolve, reject) => { + if ((req as any).aborted || req.destroyed) { + reject(new Error('Request was aborted before body could be read')); + return; + } + + const cleanup = () => { + req.removeListener('data', onData); + req.removeListener('end', onEnd); + req.removeListener('error', onError); + req.removeListener('close', onClose); + req.removeListener('aborted', onAborted); + }; + + const chunks: Buffer[] = []; + const onData = (chunk: Buffer) => { + chunks.push(chunk); + }; + + const onEnd = () => { + cleanup(); + // Concatenate all chunks and decode as UTF-8 to handle multibyte characters correctly + const body = Buffer.concat(chunks).toString('utf8'); + resolve(body.split('\n').filter(Boolean)); + }; + + const onError = (err: Error) => { + cleanup(); + reject(err); + }; + + const onClose = () => { + cleanup(); + reject(new Error('Request was closed before body could be read')); + }; + + const onAborted = () => { + cleanup(); + reject(new Error('Request was aborted before body could be read')); + }; + + req.on('data', onData); + req.on('end', onEnd); + req.on('error', onError); + req.on('close', onClose); + req.on('aborted', onAborted); + }); +} + const lazyCompilationMiddlewareInternal = ( compiler: Compiler | MultiCompiler, activeModules: Set, @@ -181,21 +242,24 @@ const lazyCompilationMiddlewareInternal = ( ): MiddlewareHandler => { const logger = compiler.getInfrastructureLogger('LazyCompilation'); - return (req: IncomingMessage, res: ServerResponse, next?: () => void) => { - if (!req.url?.startsWith(lazyCompilationPrefix)) { - // only handle requests that are come from lazyCompilation + return async ( + req: IncomingMessage, + res: ServerResponse, + next?: () => void, + ) => { + if (!req.url?.startsWith(lazyCompilationPrefix) || req.method !== 'POST') { return next?.(); } - const modules = req.url - .slice(lazyCompilationPrefix.length) - .split('@') - .map(decodeURIComponent); - req.socket.setNoDelay(true); - - res.setHeader('content-type', 'text/event-stream'); - res.writeHead(200); - res.write('\n'); + let modules: string[] = []; + try { + modules = await readModuleIdsFromBody(req); + } catch (err) { + logger.error('Failed to parse request body: ' + err); + res.writeHead(400); + res.end('Bad Request'); + return; + } const moduleActivated = []; for (const key of modules) { @@ -210,5 +274,9 @@ const lazyCompilationMiddlewareInternal = ( if (moduleActivated.length && compiler.watching) { compiler.watching.invalidate(); } + + res.writeHead(200); + res.write('\n'); + res.end(); }; }; diff --git a/tests/e2e/cases/lazy-compilation/active-lots-modules/index.test.ts b/tests/e2e/cases/lazy-compilation/active-lots-modules/index.test.ts new file mode 100644 index 000000000000..b4df048e2626 --- /dev/null +++ b/tests/e2e/cases/lazy-compilation/active-lots-modules/index.test.ts @@ -0,0 +1,8 @@ +import { expect, test } from '@/fixtures'; + +test('should activate and compile lots of modules with long names', async ({ + page, +}) => { + const body = await page.locator('body'); + await expect(body).toContainText('All Modules Loaded'); +}); diff --git a/tests/e2e/cases/lazy-compilation/active-lots-modules/rspack.config.js b/tests/e2e/cases/lazy-compilation/active-lots-modules/rspack.config.js new file mode 100644 index 000000000000..a9ade0287662 --- /dev/null +++ b/tests/e2e/cases/lazy-compilation/active-lots-modules/rspack.config.js @@ -0,0 +1,43 @@ +const { rspack } = require('@rspack/core'); + +/* +Construct a project with lots of virtual files with very long file names +And `virtual_index.js` dynamically imports all the long file name files. +src/ +├── virtual_index.js +├── virtual_with_a_very_long_file_name_number_....._0.js +... +└── virtual_with_a_very_long_file_name_number_....._19.js +*/ +let lotsLongFileNameVirtualFiles = {}; +let longStr = new Array(1024).fill('a').join(''); +for (let i = 0; i < 20; i++) { + lotsLongFileNameVirtualFiles[ + `src/virtual_with_a_very_long_file_name_number_${longStr}_${i}.js` + ] = `"dynamic_imported"`; +} +let allFiles = Object.keys(lotsLongFileNameVirtualFiles); +lotsLongFileNameVirtualFiles['src/virtual_index.js'] = ` + Promise.all([ + ${allFiles.map((file) => `import('./${file.slice(3)}')\n`).join(',')} + ]).then(()=> document.body.innerHTML = 'All Modules Loaded'); +`; + +/** @type { import('@rspack/core').RspackOptions } */ +module.exports = { + context: __dirname, + entry: './src/virtual_index.js', + mode: 'development', + lazyCompilation: true, + devServer: { + hot: true, + port: 5678, + }, + plugins: [ + new rspack.HtmlRspackPlugin(), + new rspack.experiments.VirtualModulesPlugin(lotsLongFileNameVirtualFiles), + ], + experiments: { + useInputFileSystem: [/virtual/], + }, +}; diff --git a/tests/e2e/cases/lazy-compilation/cross-origin/README.md b/tests/e2e/cases/lazy-compilation/cross-origin/README.md new file mode 100644 index 000000000000..817ebaa50fb2 --- /dev/null +++ b/tests/e2e/cases/lazy-compilation/cross-origin/README.md @@ -0,0 +1,46 @@ +# Cross-Origin Lazy Compilation Test + +This test verifies that lazy compilation works correctly +when the lazy compilation server runs on a different origin (port) than the frontend dev server. + +## Architecture + +``` ++----------------------+ +----------------------+ +-----------------------------+ +| | | | | | +| Browser | | Dev Server | | Lazy Compilation Server | +| (Frontend) | | (Port: 8500) | | (Port: 8600) | +| | | | | | ++----------+-----------+ +----------+-----------+ +--------------+--------------+ + | | | + | 1. Load page | | + | GET http://localhost:8500 | + +-------------------------> | + | | | + | 2. Click button -> dynamic import() | + | | | + | 3. Cross-origin POST request | + | POST http://127.0.0.1:8600/lazy-... | + | Content-Type: text/plain | + | Body: "module-id-1\nmodule-id-2" | + +----------------------------------------------------------> + | | | + | 4. Response (SSE or empty for POST) | + <----------------------------------------------------------+ + | | | + | 5. Webpack invalidate & rebuild | + | | | + | 6. Load compiled chunk | + v | | ++----------------------+ | | +| Component | | | +| Rendered | | | ++----------------------+ | | +``` + +## Key Points + +1. **Two Separate Servers**: Frontend runs on port 8500, lazy compilation on port 8600 +2. **Cross-Origin Request**: Browser sends POST request to a different origin +3. **Simple Request**: Uses `Content-Type: text/plain` to avoid CORS preflight +4. **XMLHttpRequest**: Uses XHR instead of fetch for better browser compatibility diff --git a/tests/e2e/cases/lazy-compilation/cross-origin/index.test.ts b/tests/e2e/cases/lazy-compilation/cross-origin/index.test.ts new file mode 100644 index 000000000000..279d43a2ed8b --- /dev/null +++ b/tests/e2e/cases/lazy-compilation/cross-origin/index.test.ts @@ -0,0 +1,170 @@ +import http from 'node:http'; +import path from 'node:path'; +import { test as base, expect } from '@playwright/test'; +import fs from 'fs-extra'; +import { type Compiler, type Configuration, rspack } from '@rspack/core'; +import { RspackDevServer } from '@rspack/dev-server'; + +const tempDir = path.resolve(__dirname, '../../temp'); + +// Create a separate lazy compilation server on a different port (cross-origin) +function createLazyCompilationServer( + compiler: Compiler, + port: number, +): Promise { + return new Promise((resolve, reject) => { + const middleware = rspack.lazyCompilationMiddleware(compiler); + const server = http.createServer((req, res) => { + res.setHeader('Access-Control-Allow-Origin', '*'); + middleware(req, res, () => { + res.writeHead(404); + res.end('Not Found'); + }); + }); + + server.listen(port, () => { + resolve(server); + }); + + server.on('error', reject); + }); +} + +const test = base.extend<{ + crossOriginSetup: { + frontendPort: number; + lazyCompilationPort: number; + }; +}>({ + crossOriginSetup: [ + async ({ page }, use, testInfo) => { + const workerId = String(testInfo.workerIndex); + const testProjectDir = path.dirname(testInfo.file); + const tempProjectDir = path.join(tempDir, `cross-origin-${workerId}`); + + // Copy test project to temp directory + if (await fs.exists(tempProjectDir)) { + await fs.remove(tempProjectDir); + } + await fs.copy(testProjectDir, tempProjectDir); + + // Clear require cache for temp directory + for (const modulePath of Object.keys(require.cache)) { + if (modulePath.startsWith(tempProjectDir)) { + delete require.cache[modulePath]; + } + } + + // Use different ports for frontend and lazy compilation server + const basePort = 8500; + const frontendPort = basePort + testInfo.workerIndex; + const lazyCompilationPort = frontendPort + 100; + + // Load and modify config + const configPath = path.resolve(tempProjectDir, 'rspack.config.js'); + const config: Configuration = require(configPath); + delete require.cache[configPath]; + + config.context = tempProjectDir; + config.output = { + ...config.output, + path: path.resolve(tempProjectDir, 'dist'), + }; + config.devServer = { + ...config.devServer, + port: frontendPort, + }; + // Set cross-origin serverUrl + config.lazyCompilation = { + ...(typeof config.lazyCompilation === 'object' + ? config.lazyCompilation + : {}), + entries: false, + imports: true, + serverUrl: `http://127.0.0.1:${lazyCompilationPort}`, + }; + + // Create compiler + const compiler = rspack(config); + + // Start lazy compilation server on a different port (cross-origin) + const lazyServer = await createLazyCompilationServer( + compiler, + lazyCompilationPort, + ); + + // Start dev server (frontend) - without lazy compilation middleware + // since we're running it on a separate server + const devServer = new RspackDevServer( + { + ...config.devServer, + port: frontendPort, + }, + compiler, + ); + await devServer.start(); + + // Wait for initial build + await new Promise((resolve) => { + compiler.hooks.done.tap('test', () => resolve()); + }); + + // Navigate to frontend + await page.goto(`http://localhost:${frontendPort}`); + + await use({ frontendPort, lazyCompilationPort }); + + // Cleanup + await new Promise((res, rej) => { + compiler.close((err) => (err ? rej(err) : res())); + }); + await devServer.stop(); + await new Promise((resolve) => { + lazyServer.close(() => resolve()); + }); + await fs.remove(tempProjectDir); + }, + { auto: true }, + ], +}); + +test('should work with cross-origin lazy compilation using simple POST request', async ({ + page, + crossOriginSetup, +}) => { + const { lazyCompilationPort } = crossOriginSetup; + + // Set up request interception to verify the request format + const requests: { method: string; contentType: string; body: string }[] = []; + + page.on('request', (request) => { + const url = request.url(); + if (url.includes(`${lazyCompilationPort}`)) { + requests.push({ + method: request.method(), + contentType: request.headers()['content-type'] || '', + body: request.postData() || '', + }); + } + }); + + await page.waitForSelector('button:has-text("Click me")'); + + // Click the button to trigger dynamic import (cross-origin lazy compilation request) + await page.getByText('Click me').click(); + + // Wait for the component to appear - this confirms the cross-origin request worked + await page.waitForSelector('div:has-text("CrossOriginComponent")', { + timeout: 10000, + }); + + const componentCount = await page.getByText('CrossOriginComponent').count(); + expect(componentCount).toBe(1); + + // Verify the request was a simple POST request with text/plain content type + const lazyRequest = requests.find((r) => r.method === 'POST'); + expect(lazyRequest).toBeDefined(); + expect(lazyRequest!.contentType).toBe('text/plain'); + // The body should be newline-separated module IDs, not JSON + expect(lazyRequest!.body).not.toMatch(/^\[/); // Not a JSON array +}); diff --git a/tests/e2e/cases/lazy-compilation/cross-origin/rspack.config.js b/tests/e2e/cases/lazy-compilation/cross-origin/rspack.config.js new file mode 100644 index 000000000000..ccdecd9fc0e7 --- /dev/null +++ b/tests/e2e/cases/lazy-compilation/cross-origin/rspack.config.js @@ -0,0 +1,24 @@ +const { rspack } = require('@rspack/core'); + +/** @type { import('@rspack/core').RspackOptions } */ +module.exports = { + context: __dirname, + entry: { + main: './src/index.js', + }, + stats: 'none', + mode: 'development', + plugins: [new rspack.HtmlRspackPlugin()], + lazyCompilation: { + entries: false, + imports: true, + // serverUrl will be set dynamically in the test to point to a different port + }, + devtool: false, + devServer: { + hot: true, + devMiddleware: { + writeToDisk: true, + }, + }, +}; diff --git a/tests/e2e/cases/lazy-compilation/cross-origin/src/component.js b/tests/e2e/cases/lazy-compilation/cross-origin/src/component.js new file mode 100644 index 000000000000..660827de9de6 --- /dev/null +++ b/tests/e2e/cases/lazy-compilation/cross-origin/src/component.js @@ -0,0 +1,3 @@ +const component = document.createElement('div'); +component.textContent = 'CrossOriginComponent'; +document.body.appendChild(component); diff --git a/tests/e2e/cases/lazy-compilation/cross-origin/src/index.js b/tests/e2e/cases/lazy-compilation/cross-origin/src/index.js new file mode 100644 index 000000000000..571d00ff49e7 --- /dev/null +++ b/tests/e2e/cases/lazy-compilation/cross-origin/src/index.js @@ -0,0 +1,9 @@ +const button = document.createElement('button'); +button.textContent = 'Click me'; + +button.addEventListener('click', () => { + import('./component.js').then(() => { + console.log('Component loaded via cross-origin lazy compilation'); + }); +}); +document.body.appendChild(button); diff --git a/tests/e2e/cases/lazy-compilation/custom-prefix/index.test.ts b/tests/e2e/cases/lazy-compilation/custom-prefix/index.test.ts index a7e1ca5e376f..4354ff62c592 100644 --- a/tests/e2e/cases/lazy-compilation/custom-prefix/index.test.ts +++ b/tests/e2e/cases/lazy-compilation/custom-prefix/index.test.ts @@ -3,9 +3,7 @@ import { expect, test } from '@/fixtures'; test('should use custom prefix for lazy compilation', async ({ page }) => { // Wait for a request with custom prefix const responsePromise = page.waitForResponse( - (response) => - response.url().includes('/custom-lazy-endpoint-') && - response.request().method() === 'GET', + (response) => response.url().includes('/custom-lazy-endpoint-'), { timeout: 5000 }, ); From 0eb2ee3d8bcfac560b7b18213fac68cfea5b5f25 Mon Sep 17 00:00:00 2001 From: hardfist Date: Thu, 15 Jan 2026 14:55:29 +0800 Subject: [PATCH 63/87] refactor: move logger into pass and reorg some passes (#12742) * refactor: move logger into pass and reorg some passes * chore: fix bench check --- .../src/compilation/build_module_graph/mod.rs | 35 ++++- .../src/compilation/finish_make/mod.rs | 19 +++ .../compilation/finish_module_graph/mod.rs | 45 ++++++ .../{finish_module => finish_modules}/mod.rs | 34 +++-- .../rspack_core/src/compilation/make/mod.rs | 21 +++ crates/rspack_core/src/compilation/mod.rs | 28 +--- .../compilation/optimize_chunk_modules/mod.rs | 11 +- .../src/compilation/optimize_chunks/mod.rs | 6 + .../src/compilation/optimize_modules/mod.rs | 11 +- .../src/compilation/optimize_tree/mod.rs | 11 +- .../src/compilation/rspack_passes.md | 49 ++++--- .../rspack_core/src/compilation/run_passes.rs | 75 ++-------- .../rspack_core/src/compilation/seal/mod.rs | 23 ++++ .../rspack-test/statsAPICases/verbose-time.js | 128 +++++++++--------- .../logging/__snapshots__/stats.txt | 8 +- .../preset-verbose/__snapshots__/stats.txt | 8 +- .../benches/groups/build_chunk_graph.rs | 8 +- 17 files changed, 321 insertions(+), 199 deletions(-) create mode 100644 crates/rspack_core/src/compilation/finish_make/mod.rs create mode 100644 crates/rspack_core/src/compilation/finish_module_graph/mod.rs rename crates/rspack_core/src/compilation/{finish_module => finish_modules}/mod.rs (87%) create mode 100644 crates/rspack_core/src/compilation/make/mod.rs create mode 100644 crates/rspack_core/src/compilation/seal/mod.rs diff --git a/crates/rspack_core/src/compilation/build_module_graph/mod.rs b/crates/rspack_core/src/compilation/build_module_graph/mod.rs index a7eb0bdcfac5..9afcfecd0800 100644 --- a/crates/rspack_core/src/compilation/build_module_graph/mod.rs +++ b/crates/rspack_core/src/compilation/build_module_graph/mod.rs @@ -3,7 +3,11 @@ mod graph_updater; mod lazy_barrel_artifact; mod module_executor; +use std::sync::atomic::Ordering; + use rspack_error::Result; +use rspack_util::tracing_preset::TRACING_BENCH_TARGET; +use tracing::instrument; pub use self::{ artifact::{BuildModuleGraphArtifact, BuildModuleGraphArtifactState}, @@ -13,7 +17,36 @@ pub use self::{ }, module_executor::{ExecuteModuleId, ExecutedRuntimeModule, ModuleExecutor}, }; -use crate::Compilation; +use crate::{Compilation, logger::Logger}; + +pub async fn build_module_graph_pass(compilation: &mut Compilation) -> Result<()> { + let logger = compilation.get_logger("rspack.Compiler"); + let start = logger.time("build module graph"); + compilation.do_build_module_graph().await?; + logger.time_end(start); + Ok(()) +} + +impl Compilation { + #[instrument("Compilation:build_module_graph",target=TRACING_BENCH_TARGET, skip_all)] + async fn do_build_module_graph(&mut self) -> Result<()> { + // run module_executor + if let Some(module_executor) = &mut self.module_executor { + let mut module_executor = std::mem::take(module_executor); + module_executor.hook_before_make(self).await?; + self.module_executor = Some(module_executor); + } + + let artifact = self.build_module_graph_artifact.take(); + self + .build_module_graph_artifact + .replace(build_module_graph(self, artifact).await?); + + self.in_finish_make.store(true, Ordering::Release); + + Ok(()) + } +} /// make module graph, support incremental rebuild /// diff --git a/crates/rspack_core/src/compilation/finish_make/mod.rs b/crates/rspack_core/src/compilation/finish_make/mod.rs new file mode 100644 index 000000000000..114414853a6a --- /dev/null +++ b/crates/rspack_core/src/compilation/finish_make/mod.rs @@ -0,0 +1,19 @@ +use rspack_error::Result; + +use crate::{Compilation, SharedPluginDriver, logger::Logger}; + +pub async fn finish_make_pass( + compilation: &mut Compilation, + plugin_driver: SharedPluginDriver, +) -> Result<()> { + let logger = compilation.get_logger("rspack.Compiler"); + let start = logger.time("finish make hook"); + plugin_driver + .compiler_hooks + .finish_make + .call(compilation) + .await?; + logger.time_end(start); + + Ok(()) +} diff --git a/crates/rspack_core/src/compilation/finish_module_graph/mod.rs b/crates/rspack_core/src/compilation/finish_module_graph/mod.rs new file mode 100644 index 000000000000..31b41da2dfa5 --- /dev/null +++ b/crates/rspack_core/src/compilation/finish_module_graph/mod.rs @@ -0,0 +1,45 @@ +use std::sync::atomic::Ordering; + +use rspack_error::Result; +use rspack_util::tracing_preset::TRACING_BENCH_TARGET; +use tracing::instrument; + +use crate::{ + Compilation, cache::Cache, compilation::build_module_graph::finish_build_module_graph, + logger::Logger, +}; + +pub async fn finish_module_graph_pass( + compilation: &mut Compilation, + cache: &mut dyn Cache, +) -> Result<()> { + let logger = compilation.get_logger("rspack.Compiler"); + let start = logger.time("finish compilation"); + compilation.finish_build_module_graph().await?; + cache + .after_build_module_graph(&compilation.build_module_graph_artifact) + .await; + logger.time_end(start); + + Ok(()) +} + +impl Compilation { + #[instrument("Compilation:finish",target=TRACING_BENCH_TARGET, skip_all)] + pub async fn finish_build_module_graph(&mut self) -> Result<()> { + self.in_finish_make.store(false, Ordering::Release); + // clean up the entry deps + let make_artifact = self.build_module_graph_artifact.take(); + self + .build_module_graph_artifact + .replace(finish_build_module_graph(self, make_artifact).await?); + // sync assets to module graph from module_executor + if let Some(module_executor) = &mut self.module_executor { + let mut module_executor = std::mem::take(module_executor); + module_executor.hook_after_finish_modules(self).await?; + self.module_executor = Some(module_executor); + } + // make finished, make artifact should be readonly thereafter. + Ok(()) + } +} diff --git a/crates/rspack_core/src/compilation/finish_module/mod.rs b/crates/rspack_core/src/compilation/finish_modules/mod.rs similarity index 87% rename from crates/rspack_core/src/compilation/finish_module/mod.rs rename to crates/rspack_core/src/compilation/finish_modules/mod.rs index 23549acbc18b..ce70e2d0d57f 100644 --- a/crates/rspack_core/src/compilation/finish_module/mod.rs +++ b/crates/rspack_core/src/compilation/finish_modules/mod.rs @@ -1,25 +1,23 @@ +use rspack_error::Result; + use super::*; use crate::logger::Logger; -impl Compilation { - #[instrument("Compilation:finish",target=TRACING_BENCH_TARGET, skip_all)] - pub async fn finish_build_module_graph(&mut self) -> Result<()> { - self.in_finish_make.store(false, Ordering::Release); - // clean up the entry deps - let make_artifact = self.build_module_graph_artifact.take(); - self - .build_module_graph_artifact - .replace(finish_build_module_graph(self, make_artifact).await?); - // sync assets to module graph from module_executor - if let Some(module_executor) = &mut self.module_executor { - let mut module_executor = std::mem::take(module_executor); - module_executor.hook_after_finish_modules(self).await?; - self.module_executor = Some(module_executor); - } - // make finished, make artifact should be readonly thereafter. - Ok(()) - } +pub async fn finish_modules_pass(compilation: &mut Compilation) -> Result<()> { + let dependencies_diagnostics_artifact = compilation.dependencies_diagnostics_artifact.clone(); + let async_modules_artifact = compilation.async_modules_artifact.clone(); + let diagnostics = compilation + .collect_build_module_graph_effects( + &mut dependencies_diagnostics_artifact.borrow_mut(), + &mut async_modules_artifact.borrow_mut(), + ) + .await?; + compilation.extend_diagnostics(diagnostics); + + Ok(()) +} +impl Compilation { #[tracing::instrument("Compilation:collect_build_module_graph_effects", skip_all)] pub async fn collect_build_module_graph_effects( &mut self, diff --git a/crates/rspack_core/src/compilation/make/mod.rs b/crates/rspack_core/src/compilation/make/mod.rs new file mode 100644 index 000000000000..a151ef1b2e6d --- /dev/null +++ b/crates/rspack_core/src/compilation/make/mod.rs @@ -0,0 +1,21 @@ +use rspack_error::Result; + +use crate::{Compilation, SharedPluginDriver, cache::Cache, logger::Logger}; + +pub async fn make_hook_pass( + compilation: &mut Compilation, + plugin_driver: SharedPluginDriver, + cache: &mut dyn Cache, +) -> Result<()> { + let logger = compilation.get_logger("rspack.Compiler"); + + cache + .before_build_module_graph(&mut compilation.build_module_graph_artifact) + .await; + + let start = logger.time("make hook"); + plugin_driver.compiler_hooks.make.call(compilation).await?; + logger.time_end(start); + + Ok(()) +} diff --git a/crates/rspack_core/src/compilation/mod.rs b/crates/rspack_core/src/compilation/mod.rs index b1e18cc9bbee..18be47aa53b3 100644 --- a/crates/rspack_core/src/compilation/mod.rs +++ b/crates/rspack_core/src/compilation/mod.rs @@ -8,7 +8,10 @@ mod create_chunk_assets; mod create_hash; mod create_module_assets; mod create_module_hashes; -mod finish_module; +mod finish_make; +mod finish_module_graph; +mod finish_modules; +mod make; mod module_ids; mod optimize_chunk_modules; mod optimize_chunks; @@ -19,6 +22,7 @@ mod optimize_tree; mod process_assets; mod run_passes; mod runtime_requirements; +mod seal; use std::{ collections::{VecDeque, hash_map}, fmt::{self, Debug}, @@ -74,8 +78,7 @@ use crate::{ SourceType, Stats, ValueCacheVersions, build_chunk_graph::artifact::BuildChunkGraphArtifact, compilation::build_module_graph::{ - BuildModuleGraphArtifact, ModuleExecutor, UpdateParam, build_module_graph, - finish_build_module_graph, update_module_graph, + BuildModuleGraphArtifact, ModuleExecutor, UpdateParam, update_module_graph, }, compiler::{CompilationRecords, CompilerId}, get_runtime_key, @@ -990,25 +993,6 @@ impl Compilation { ukey } - #[instrument("Compilation:build_module_graph",target=TRACING_BENCH_TARGET, skip_all)] - pub async fn build_module_graph(&mut self) -> Result<()> { - // run module_executor - if let Some(module_executor) = &mut self.module_executor { - let mut module_executor = std::mem::take(module_executor); - module_executor.hook_before_make(self).await?; - self.module_executor = Some(module_executor); - } - - let artifact = self.build_module_graph_artifact.take(); - self - .build_module_graph_artifact - .replace(build_module_graph(self, artifact).await?); - - self.in_finish_make.store(true, Ordering::Release); - - Ok(()) - } - pub async fn rebuild_module( &mut self, module_identifiers: IdentifierSet, diff --git a/crates/rspack_core/src/compilation/optimize_chunk_modules/mod.rs b/crates/rspack_core/src/compilation/optimize_chunk_modules/mod.rs index 15b157d10de0..222ad5ba2003 100644 --- a/crates/rspack_core/src/compilation/optimize_chunk_modules/mod.rs +++ b/crates/rspack_core/src/compilation/optimize_chunk_modules/mod.rs @@ -1,14 +1,21 @@ use super::*; +use crate::logger::Logger; pub async fn optimize_chunk_modules_pass( compilation: &mut Compilation, plugin_driver: SharedPluginDriver, ) -> Result<()> { - plugin_driver + let logger = compilation.get_logger("rspack.Compilation"); + let start = logger.time("optimize chunk modules"); + + let result = plugin_driver .compilation_hooks .optimize_chunk_modules .call(compilation) .await .map(|_| ()) - .map_err(|e| e.wrap_err("caused by plugins in Compilation.hooks.optimizeChunkModules")) + .map_err(|e| e.wrap_err("caused by plugins in Compilation.hooks.optimizeChunkModules")); + + logger.time_end(start); + result } diff --git a/crates/rspack_core/src/compilation/optimize_chunks/mod.rs b/crates/rspack_core/src/compilation/optimize_chunks/mod.rs index 6bc6a593c054..fda4f268b7be 100644 --- a/crates/rspack_core/src/compilation/optimize_chunks/mod.rs +++ b/crates/rspack_core/src/compilation/optimize_chunks/mod.rs @@ -1,9 +1,13 @@ use super::*; +use crate::logger::Logger; pub async fn optimize_chunks_pass( compilation: &mut Compilation, plugin_driver: SharedPluginDriver, ) -> Result<()> { + let logger = compilation.get_logger("rspack.Compilation"); + let start = logger.time("optimize chunks"); + while matches!( plugin_driver .compilation_hooks @@ -13,5 +17,7 @@ pub async fn optimize_chunks_pass( .map_err(|e| e.wrap_err("caused by plugins in Compilation.hooks.optimizeChunks"))?, Some(true) ) {} + + logger.time_end(start); Ok(()) } diff --git a/crates/rspack_core/src/compilation/optimize_modules/mod.rs b/crates/rspack_core/src/compilation/optimize_modules/mod.rs index 72a6779165f3..af48e3cb3604 100644 --- a/crates/rspack_core/src/compilation/optimize_modules/mod.rs +++ b/crates/rspack_core/src/compilation/optimize_modules/mod.rs @@ -1,9 +1,13 @@ use super::*; +use crate::logger::Logger; pub async fn optimize_modules_pass( compilation: &mut Compilation, plugin_driver: SharedPluginDriver, ) -> Result<()> { + let logger = compilation.get_logger("rspack.Compilation"); + let start = logger.time("optimize modules"); + let mut diagnostics = vec![]; while matches!( plugin_driver @@ -16,10 +20,13 @@ pub async fn optimize_modules_pass( ) {} compilation.extend_diagnostics(diagnostics); - plugin_driver + let result = plugin_driver .compilation_hooks .after_optimize_modules .call(compilation) .await - .map_err(|e| e.wrap_err("caused by plugins in Compilation.hooks.afterOptimizeModules")) + .map_err(|e| e.wrap_err("caused by plugins in Compilation.hooks.afterOptimizeModules")); + + logger.time_end(start); + result } diff --git a/crates/rspack_core/src/compilation/optimize_tree/mod.rs b/crates/rspack_core/src/compilation/optimize_tree/mod.rs index ff62eba916a2..f1ba8821b710 100644 --- a/crates/rspack_core/src/compilation/optimize_tree/mod.rs +++ b/crates/rspack_core/src/compilation/optimize_tree/mod.rs @@ -1,13 +1,20 @@ use super::*; +use crate::logger::Logger; pub async fn optimize_tree_pass( compilation: &mut Compilation, plugin_driver: SharedPluginDriver, ) -> Result<()> { - plugin_driver + let logger = compilation.get_logger("rspack.Compilation"); + let start = logger.time("optimize tree"); + + let result = plugin_driver .compilation_hooks .optimize_tree .call(compilation) .await - .map_err(|e| e.wrap_err("caused by plugins in Compilation.hooks.optimizeTree")) + .map_err(|e| e.wrap_err("caused by plugins in Compilation.hooks.optimizeTree")); + + logger.time_end(start); + result } diff --git a/crates/rspack_core/src/compilation/rspack_passes.md b/crates/rspack_core/src/compilation/rspack_passes.md index b849dd6a8545..b8583f8bc1dd 100644 --- a/crates/rspack_core/src/compilation/rspack_passes.md +++ b/crates/rspack_core/src/compilation/rspack_passes.md @@ -12,14 +12,18 @@ The compilation process is organized into independent modules, each responsible compilation/ ├── mod.rs # Main Compilation struct which exposes the public API ├── run_passes.rs # Pass driver invoked from Compiler that runs make + seal passes -├── build_module_graph/ # Module graph construction -│ └── finish_module/ # Finalize module graph, async modules, dependency diagnostics +├── make/ # make_hook_pass: make hook + cache.before_build_module_graph +├── build_module_graph/ # build_module_graph_pass: module graph construction +├── finish_make/ # finish_make_pass: finish_make hook +├── finish_module_graph/ # finish_module_graph_pass: finalize module graph + cache +├── finish_modules/ # finish_modules_pass: finish_modules hook, diagnostics, checkpoint +├── seal/ # seal_pass: seal hook ├── optimize_dependencies/ # optimizeDependencies hook + side effects artifact ├── build_chunk_graph/ # Chunk graph construction (code splitting cache + pass wrapper) ├── optimize_modules/ # optimizeModules + afterOptimizeModules hooks ├── optimize_chunks/ # optimizeChunks hook ├── optimize_tree/ # optimizeTree hook -├── optimize_chunk_modules # optimizeChunkModules hook +├── optimize_chunk_modules/ # optimizeChunkModules hook ├── module_ids/ # Module ID assignment + diagnostics ├── chunk_ids/ # Chunk ID assignment + diagnostics ├── assign_runtime_ids/ # Runtime ID assignment for runtime chunks @@ -43,21 +47,24 @@ compilation/ `run_passes` orchestrates the full pipeline (make + seal) in this order: -1. Make: `make` hook → `build_module_graph` → `finish_make` hook → `finish_build_module_graph` -2. Collect make diagnostics (`collect_build_module_graph_effects`) -3. Incremental checkpoint (`module_graph`), freeze module static cache in production -4. Seal kickoff: `CompilationHooks::seal` -5. `optimize_dependencies_pass` -6. `build_chunk_graph_pass` → `optimize_modules_pass` → `optimize_chunks_pass` -7. `optimize_tree_pass` → `optimize_chunk_modules_pass` -8. `module_ids_pass` → `chunk_ids_pass` → `assign_runtime_ids` -9. `optimize_code_generation_pass` -10. `create_module_hashes_pass` -11. `code_generation_pass` -12. `runtime_requirements_pass` -13. `create_hash_pass` (also runs runtime module code generation) -14. `create_module_assets_pass` -15. `create_chunk_assets_pass` -16. `process_assets_pass` -17. `after_seal_pass` -18. Unfreeze module static cache in production +1. `make_hook_pass`: `make` hook + cache.before_build_module_graph +2. `build_module_graph_pass`: build module graph +3. `finish_make_pass`: `finish_make` hook +4. `finish_module_graph_pass`: `finish_build_module_graph` + cache.after_build_module_graph +5. `finish_modules_pass`: `finish_modules` hook, collect diagnostics, incremental checkpoint +6. Freeze module static cache in production +7. `seal_pass`: `seal` hook +8. `optimize_dependencies_pass` +9. `build_chunk_graph_pass` → `optimize_modules_pass` → `optimize_chunks_pass` +10. `optimize_tree_pass` → `optimize_chunk_modules_pass` +11. `module_ids_pass` → `chunk_ids_pass` → `assign_runtime_ids` +12. `optimize_code_generation_pass` +13. `create_module_hashes_pass` +14. `code_generation_pass` +15. `runtime_requirements_pass` +16. `create_hash_pass` (also runs runtime module code generation) +17. `create_module_assets_pass` +18. `create_chunk_assets_pass` +19. `process_assets_pass` +20. `after_seal_pass` +21. Unfreeze module static cache in production diff --git a/crates/rspack_core/src/compilation/run_passes.rs b/crates/rspack_core/src/compilation/run_passes.rs index d6be8a9c4fba..9b0c4cca45a8 100644 --- a/crates/rspack_core/src/compilation/run_passes.rs +++ b/crates/rspack_core/src/compilation/run_passes.rs @@ -1,18 +1,18 @@ use super::{ after_seal::after_seal_pass, assign_runtime_ids::assign_runtime_ids, - build_chunk_graph::pass::build_chunk_graph_pass, chunk_ids::chunk_ids_pass, - code_generation::code_generation_pass, create_chunk_assets::create_chunk_assets_pass, - create_hash::create_hash_pass, create_module_assets::create_module_assets_pass, - create_module_hashes::create_module_hashes_pass, module_ids::module_ids_pass, + build_chunk_graph::pass::build_chunk_graph_pass, build_module_graph::build_module_graph_pass, + chunk_ids::chunk_ids_pass, code_generation::code_generation_pass, + create_chunk_assets::create_chunk_assets_pass, create_hash::create_hash_pass, + create_module_assets::create_module_assets_pass, create_module_hashes::create_module_hashes_pass, + finish_make::finish_make_pass, finish_module_graph::finish_module_graph_pass, + finish_modules::finish_modules_pass, make::make_hook_pass, module_ids::module_ids_pass, optimize_chunk_modules::optimize_chunk_modules_pass, optimize_chunks::optimize_chunks_pass, optimize_code_generation::optimize_code_generation_pass, optimize_dependencies::optimize_dependencies_pass, optimize_modules::optimize_modules_pass, optimize_tree::optimize_tree_pass, process_assets::process_assets_pass, - runtime_requirements::runtime_requirements_pass, *, -}; -use crate::{ - Compilation, SharedPluginDriver, cache::Cache, incremental::IncrementalPasses, logger::Logger, + runtime_requirements::runtime_requirements_pass, seal::seal_pass, *, }; +use crate::{Compilation, SharedPluginDriver, cache::Cache}; impl Compilation { pub async fn run_passes( @@ -20,76 +20,31 @@ impl Compilation { plugin_driver: SharedPluginDriver, cache: &mut dyn Cache, ) -> Result<()> { - let logger = self.get_logger("rspack.Compiler"); - - let make_start = logger.time("make"); - let make_hook_start = logger.time("make hook"); - cache - .before_build_module_graph(&mut self.build_module_graph_artifact) - .await; - - plugin_driver.compiler_hooks.make.call(self).await?; - logger.time_end(make_hook_start); - self.build_module_graph().await?; - logger.time_end(make_start); - - let start = logger.time("finish make hook"); - plugin_driver.compiler_hooks.finish_make.call(self).await?; - logger.time_end(start); - - let start = logger.time("finish compilation"); - self.finish_build_module_graph().await?; - cache - .after_build_module_graph(&self.build_module_graph_artifact) - .await; - logger.time_end(start); - - let dependencies_diagnostics_artifact = self.dependencies_diagnostics_artifact.clone(); - let async_modules_artifact = self.async_modules_artifact.clone(); - let diagnostics = self - .collect_build_module_graph_effects( - &mut dependencies_diagnostics_artifact.borrow_mut(), - &mut async_modules_artifact.borrow_mut(), - ) - .await?; - self.extend_diagnostics(diagnostics); - + make_hook_pass(self, plugin_driver.clone(), cache).await?; + build_module_graph_pass(self).await?; + finish_make_pass(self, plugin_driver.clone()).await?; + finish_module_graph_pass(self, cache).await?; + finish_modules_pass(self).await?; + // This is the end of first pass of build module graph which will be recovered for next compilation // add a checkpoint here since we may modify module graph later in incremental compilation // and we can recover to this checkpoint in the future if self.incremental.passes_enabled(IncrementalPasses::MAKE) { self.build_module_graph_artifact.module_graph.checkpoint(); } - if !self.options.mode.is_development() { self.module_static_cache_artifact.freeze(); } - #[cfg(feature = "debug_tool")] - { - use rspack_util::debug_tool::wait_for_signal; - wait_for_signal("seal compilation"); - } - let logger = self.get_logger("rspack.Compilation"); - // https://github.com/webpack/webpack/blob/main/lib/Compilation.js#L2809 - plugin_driver - .compilation_hooks - .seal - .call(self) - .await - .map_err(|e| e.wrap_err("caused by plugins in Compilation.hooks.seal"))?; + seal_pass(self, plugin_driver.clone()).await?; optimize_dependencies_pass(self, plugin_driver.clone()).await?; - let create_chunks_start = logger.time("create chunks"); build_chunk_graph_pass(self).await?; optimize_modules_pass(self, plugin_driver.clone()).await?; optimize_chunks_pass(self, plugin_driver.clone()).await?; - logger.time_end(create_chunks_start); - let optimize_start = logger.time("optimize"); optimize_tree_pass(self, plugin_driver.clone()).await?; optimize_chunk_modules_pass(self, plugin_driver.clone()).await?; - logger.time_end(optimize_start); module_ids_pass(self, plugin_driver.clone()).await?; chunk_ids_pass(self, plugin_driver.clone()).await?; diff --git a/crates/rspack_core/src/compilation/seal/mod.rs b/crates/rspack_core/src/compilation/seal/mod.rs new file mode 100644 index 000000000000..94d12e17cd6b --- /dev/null +++ b/crates/rspack_core/src/compilation/seal/mod.rs @@ -0,0 +1,23 @@ +use rspack_error::Result; + +use crate::{Compilation, SharedPluginDriver}; + +pub async fn seal_pass( + compilation: &mut Compilation, + plugin_driver: SharedPluginDriver, +) -> Result<()> { + #[cfg(feature = "debug_tool")] + { + use rspack_util::debug_tool::wait_for_signal; + wait_for_signal("seal compilation"); + } + // https://github.com/webpack/webpack/blob/main/lib/Compilation.js#L2809 + plugin_driver + .compilation_hooks + .seal + .call(compilation) + .await + .map_err(|e| e.wrap_err("caused by plugins in Compilation.hooks.seal"))?; + + Ok(()) +} diff --git a/tests/rspack-test/statsAPICases/verbose-time.js b/tests/rspack-test/statsAPICases/verbose-time.js index 50e7aabb4177..e86b4920a5f6 100644 --- a/tests/rspack-test/statsAPICases/verbose-time.js +++ b/tests/rspack-test/statsAPICases/verbose-time.js @@ -13,76 +13,78 @@ module.exports = { ?.toString({ all: false, logging: "verbose" }) .replace(/\d+ ms/g, "X ms") ).toMatchInlineSnapshot(` - LOG from rspack.Compilation - finish modules: X ms - optimize dependencies: X ms - rebuild chunk graph: X ms - create chunks: X ms - optimize: X ms - module ids: X ms - chunk ids: X ms - optimize code generation: X ms - code generation: X ms - runtime requirements.modules: X ms - runtime requirements.chunks: X ms - runtime requirements.entries: X ms - runtime requirements: X ms - hashing: hash chunks: X ms - hashing: hash runtime chunks: X ms - hashing: process full hash chunks: X ms - hashing: X ms - create module assets: X ms - create chunk assets: X ms - process assets: X ms - after process assets: X ms - after seal: X ms + LOG from rspack.Compilation + finish modules: X ms + optimize dependencies: X ms + rebuild chunk graph: X ms + optimize modules: X ms + optimize chunks: X ms + optimize tree: X ms + optimize chunk modules: X ms + module ids: X ms + chunk ids: X ms + optimize code generation: X ms + code generation: X ms + runtime requirements.modules: X ms + runtime requirements.chunks: X ms + runtime requirements.entries: X ms + runtime requirements: X ms + hashing: hash chunks: X ms + hashing: hash runtime chunks: X ms + hashing: process full hash chunks: X ms + hashing: X ms + create module assets: X ms + create chunk assets: X ms + process assets: X ms + after process assets: X ms + after seal: X ms - LOG from rspack.Compiler - make hook: X ms - make: X ms - finish make hook: X ms - finish compilation: X ms - seal compilation: X ms - emitAssets: X ms + LOG from rspack.Compiler + make hook: X ms + build module graph: X ms + finish make hook: X ms + finish compilation: X ms + seal compilation: X ms + emitAssets: X ms - LOG from rspack.EnsureChunkConditionsPlugin - ensure chunk conditions: X ms + LOG from rspack.EnsureChunkConditionsPlugin + ensure chunk conditions: X ms - LOG from rspack.ModuleConcatenationPlugin - select relevant modules: X ms - 0 potential root modules, 0 potential inner modules - sort relevant modules: X ms - find modules to concatenate: X ms - 0 candidates were considered for adding (0 cached failure, 0 already in config, 0 invalid module, 0 incorrect chunks, 0 incorrect dependency, 0 incorrect chunks of importer, 0 incorrect module dependency, 0 incorrect runtime condition, 0 importer failed, 0 added) - sort concat configurations: X ms + LOG from rspack.ModuleConcatenationPlugin + select relevant modules: X ms + 0 potential root modules, 0 potential inner modules + sort relevant modules: X ms + find modules to concatenate: X ms + 0 candidates were considered for adding (0 cached failure, 0 already in config, 0 invalid module, 0 incorrect chunks, 0 incorrect dependency, 0 incorrect chunks of importer, 0 incorrect module dependency, 0 incorrect runtime condition, 0 importer failed, 0 added) + sort concat configurations: X ms - LOG from rspack.RealContentHashPlugin - hash to asset names: X ms + LOG from rspack.RealContentHashPlugin + hash to asset names: X ms - LOG from rspack.RemoveEmptyChunksPlugin - remove empty chunks: X ms + LOG from rspack.RemoveEmptyChunksPlugin + remove empty chunks: X ms - LOG from rspack.SideEffectsFlagPlugin - prepare connections: X ms - find optimizable connections: X ms - do optimize connections: X ms - update connections: X ms - optimized 0 connections + LOG from rspack.SideEffectsFlagPlugin + prepare connections: X ms + find optimizable connections: X ms + do optimize connections: X ms + update connections: X ms + optimized 0 connections - LOG from rspack.SplitChunksPlugin - prepare module data: X ms - prepare cache groups: X ms - process cache groups: X ms - ensure max size fit: X ms + LOG from rspack.SplitChunksPlugin + prepare module data: X ms + prepare cache groups: X ms + process cache groups: X ms + ensure max size fit: X ms - LOG from rspack.buildChunkGraph - prepare entrypoints: X ms - process queue: X ms - extend chunkGroup runtime: X ms - 8 queue items processed (4 blocks) - 0 chunk groups connected - 0 chunk groups processed for merging (0 module sets) - 0 chunk group info updated (0 already connected chunk groups reconnected) - `); + LOG from rspack.buildChunkGraph + prepare entrypoints: X ms + process queue: X ms + extend chunkGroup runtime: X ms + 8 queue items processed (4 blocks) + 0 chunk groups connected + 0 chunk groups processed for merging (0 module sets) + 0 chunk group info updated (0 already connected chunk groups reconnected) + `); } }; diff --git a/tests/rspack-test/statsOutputCases/logging/__snapshots__/stats.txt b/tests/rspack-test/statsOutputCases/logging/__snapshots__/stats.txt index dc544d347102..6ed8f2d18b6c 100644 --- a/tests/rspack-test/statsOutputCases/logging/__snapshots__/stats.txt +++ b/tests/rspack-test/statsOutputCases/logging/__snapshots__/stats.txt @@ -76,8 +76,10 @@ LOG from rspack.Compilation finish modules: xx ms optimize dependencies: xx ms rebuild chunk graph: xx ms - create chunks: xx ms - optimize: xx ms + optimize modules: xx ms + optimize chunks: xx ms + optimize tree: xx ms + optimize chunk modules: xx ms module ids: xx ms chunk ids: xx ms optimize code generation: xx ms @@ -98,7 +100,7 @@ LOG from rspack.Compilation LOG from rspack.Compiler make hook: xx ms - make: xx ms + build module graph: xx ms finish make hook: xx ms finish compilation: xx ms seal compilation: xx ms diff --git a/tests/rspack-test/statsOutputCases/preset-verbose/__snapshots__/stats.txt b/tests/rspack-test/statsOutputCases/preset-verbose/__snapshots__/stats.txt index 76c1fcef61a2..7bc82c753174 100644 --- a/tests/rspack-test/statsOutputCases/preset-verbose/__snapshots__/stats.txt +++ b/tests/rspack-test/statsOutputCases/preset-verbose/__snapshots__/stats.txt @@ -48,8 +48,10 @@ LOG from rspack.Compilation finish modules: xx ms optimize dependencies: xx ms rebuild chunk graph: xx ms - create chunks: xx ms - optimize: xx ms + optimize modules: xx ms + optimize chunks: xx ms + optimize tree: xx ms + optimize chunk modules: xx ms module ids: xx ms chunk ids: xx ms optimize code generation: xx ms @@ -70,7 +72,7 @@ LOG from rspack.Compilation LOG from rspack.Compiler make hook: xx ms - make: xx ms + build module graph: xx ms finish make hook: xx ms finish compilation: xx ms seal compilation: xx ms diff --git a/xtask/benchmark/benches/groups/build_chunk_graph.rs b/xtask/benchmark/benches/groups/build_chunk_graph.rs index f41612a55531..6fa00b983ff1 100644 --- a/xtask/benchmark/benches/groups/build_chunk_graph.rs +++ b/xtask/benchmark/benches/groups/build_chunk_graph.rs @@ -5,7 +5,9 @@ use criterion::criterion_group; use rspack::builder::Builder as _; use rspack_benchmark::Criterion; use rspack_core::{ - Compilation, Compiler, Experiments, Optimization, build_chunk_graph, fast_set, + Compilation, Compiler, Experiments, Optimization, build_chunk_graph, + build_module_graph::build_module_graph_pass, + fast_set, incremental::{Incremental, IncrementalOptions}, }; use rspack_error::Diagnostic; @@ -175,7 +177,9 @@ pub fn build_chunk_graph_benchmark_inner(c: &mut Criterion) { .call(&mut compiler.compilation) .await .unwrap(); - compiler.compilation.build_module_graph().await.unwrap(); + build_module_graph_pass(&mut compiler.compilation) + .await + .unwrap(); let mut side_effects_optimize_artifact = compiler.compilation.side_effects_optimize_artifact.take(); From cd1581887a89a2defff1df014002416c505b7c9f Mon Sep 17 00:00:00 2001 From: "senze.fan" <151665030@qq.com> Date: Thu, 15 Jan 2026 16:47:23 +0800 Subject: [PATCH 64/87] chore(lint): bump @rslint/core to 0.2.0 and enable default-param-last rule (#12746) * chore(deps): bump @rslint/core to 0.2.0 and update rslint.json * fix(lint): enable @typescript-eslint/default-param-last rule --- package.json | 2 +- packages/rspack/src/MultiStats.ts | 4 +-- pnpm-lock.yaml | 60 +++++++++++++++---------------- rslint.json | 14 +++++++- 4 files changed, 46 insertions(+), 34 deletions(-) diff --git a/package.json b/package.json index a8af2948b7ba..036a764643b1 100644 --- a/package.json +++ b/package.json @@ -64,7 +64,7 @@ "@biomejs/biome": "^2.3.11", "@microsoft/api-extractor": "7.55.2", "@microsoft/api-extractor-model": "7.32.2", - "@rslint/core": "0.1.13", + "@rslint/core": "0.2.0", "@rspack/cli": "workspace:*", "@taplo/cli": "^0.7.0", "@types/is-ci": "^3.0.4", diff --git a/packages/rspack/src/MultiStats.ts b/packages/rspack/src/MultiStats.ts index f8cedbd84c07..a67718f2a70d 100644 --- a/packages/rspack/src/MultiStats.ts +++ b/packages/rspack/src/MultiStats.ts @@ -35,13 +35,13 @@ export default class MultiStats { } #createChildOptions( - options: boolean | StatsPresets | MultiStatsOptions = {}, + options: boolean | StatsPresets | MultiStatsOptions, context: (KnownCreateStatsOptionsContext & Record) | undefined, ) { const { children: childrenOptions = undefined, ...baseOptions } = typeof options === 'string' || typeof options === 'boolean' ? { preset: options } - : options; + : (options ?? {}); const children = this.stats.map((stat, idx) => { const childOptions = Array.isArray(childrenOptions) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 97be27569e2b..d896764380cd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -23,8 +23,8 @@ importers: specifier: 7.32.2 version: 7.32.2(@types/node@20.19.29) '@rslint/core': - specifier: 0.1.13 - version: 0.1.13 + specifier: 0.2.0 + version: 0.2.0 '@rspack/cli': specifier: workspace:* version: link:packages/rspack-cli @@ -3247,37 +3247,37 @@ packages: typescript: optional: true - '@rslint/core@0.1.13': - resolution: {integrity: sha512-4K/5/aZFS4sz4fZ2hdNFFLTwgpnxTkaDo1vC+fBltDMe9G0Jp0ELhesM1nbYPa3f+JsN8xE8BU8XseJjW6igYQ==} + '@rslint/core@0.2.0': + resolution: {integrity: sha512-g9EXVfr5Y5ZDAMSzRA8YOPGrhsUCF1YvVb8XrX9Ft6vX6PPi3RiL+zbDoaOYPx4V0tdHrXs68S8jsasJvld17Q==} hasBin: true - '@rslint/darwin-arm64@0.1.13': - resolution: {integrity: sha512-UpZWLD6B9pZ+uXjZ0i+nkXbZKHPatd/6FNroF7q6qRSnFdix+moxaqgzhHg+9Eq4rnVc7aL1VmduRTh40bH7xg==} + '@rslint/darwin-arm64@0.2.0': + resolution: {integrity: sha512-dn5zEWBpW6VUUi4KdrLEcbzQLxvZ2TsdMg42+e2QRcYvu66/65WXOyZQJ8fbQEEST0tkpa154zgPDG3fDW3okQ==} cpu: [arm64] os: [darwin] - '@rslint/darwin-x64@0.1.13': - resolution: {integrity: sha512-o9BocB82RglcoI0Cnz3Stx5SdBTzjZb3ZY+EFcsom4RTEna2QVlQhG4Y5NogicfzPJvudvnl2RREPuNuWiBTpw==} + '@rslint/darwin-x64@0.2.0': + resolution: {integrity: sha512-6zWm09teGePwAo8s3dVix4TwFDKl2gizfrHOraGs4fxAjm42tbK1m6d5GKKFOdpnSqEaV/sPYYej9lCJKpr3Rw==} cpu: [x64] os: [darwin] - '@rslint/linux-arm64@0.1.13': - resolution: {integrity: sha512-4vBIDkFS9e1239VNbwWe5c35D9pxM0RrxXidVV2jmv2/O0kOrcKdx0m+n6RiD/0EHfboe8dUd2AleRQpHiDZqQ==} + '@rslint/linux-arm64@0.2.0': + resolution: {integrity: sha512-WTvS2ULWFjrBssZIKApw0353DFlTcq9LqTDK6987YJcKlwn9Rgs07nLSMgstdWrB5yIrTKprFGPEvMtiJtrrBw==} cpu: [arm64] os: [linux] - '@rslint/linux-x64@0.1.13': - resolution: {integrity: sha512-HQG/GeN5YggyPUJIvdbVrIqSiiR/X+NSKSCpw719Ttbl9Vw6juk4tUskCjIDVgl5lhpfiqArn4gVT4EPNSd7XQ==} + '@rslint/linux-x64@0.2.0': + resolution: {integrity: sha512-woIFlScbGDzX8pCexdIKG7uwq9nP3DDmUHfVQ/Ri2wzM4gH6dEKagf4tmbRay7jiVSp28SK8KAmtabvw3kxLKw==} cpu: [x64] os: [linux] - '@rslint/win32-arm64@0.1.13': - resolution: {integrity: sha512-oxfgWQMePJ6QjhG1Q7M527D2neunbuUpYy/HFDS8kdhTYPuHRsMUG2I5eIkdoumBC36FuGWKRaKJBZuKfWwskg==} + '@rslint/win32-arm64@0.2.0': + resolution: {integrity: sha512-U+1UdG0RUFT8rv1lRqrf+tpXLhTc0MhVYBmSshEPlaain0PSdGQ6f3Cq8njtqBk7smI09+wayLBro8Fk/eOkYg==} cpu: [arm64] os: [win32] - '@rslint/win32-x64@0.1.13': - resolution: {integrity: sha512-fxUw0sYpuy+Op1096/zddo4fqNBOC//NOp3c85uiLie3SMyQ3HtPp4dnW7e9CLmc6EcXr24fMkQI0BEHHpN7Ow==} + '@rslint/win32-x64@0.2.0': + resolution: {integrity: sha512-TDaaghoT4i0VCfpQMN8STzQJThiLoUkgNJDPXvuscQ2FeiX5WE3NT/NES+sq9VwwAelrKjQlL+TDw4kzRR/wcg==} cpu: [x64] os: [win32] @@ -10796,31 +10796,31 @@ snapshots: transitivePeerDependencies: - '@typescript/native-preview' - '@rslint/core@0.1.13': + '@rslint/core@0.2.0': optionalDependencies: - '@rslint/darwin-arm64': 0.1.13 - '@rslint/darwin-x64': 0.1.13 - '@rslint/linux-arm64': 0.1.13 - '@rslint/linux-x64': 0.1.13 - '@rslint/win32-arm64': 0.1.13 - '@rslint/win32-x64': 0.1.13 - - '@rslint/darwin-arm64@0.1.13': + '@rslint/darwin-arm64': 0.2.0 + '@rslint/darwin-x64': 0.2.0 + '@rslint/linux-arm64': 0.2.0 + '@rslint/linux-x64': 0.2.0 + '@rslint/win32-arm64': 0.2.0 + '@rslint/win32-x64': 0.2.0 + + '@rslint/darwin-arm64@0.2.0': optional: true - '@rslint/darwin-x64@0.1.13': + '@rslint/darwin-x64@0.2.0': optional: true - '@rslint/linux-arm64@0.1.13': + '@rslint/linux-arm64@0.2.0': optional: true - '@rslint/linux-x64@0.1.13': + '@rslint/linux-x64@0.2.0': optional: true - '@rslint/win32-arm64@0.1.13': + '@rslint/win32-arm64@0.2.0': optional: true - '@rslint/win32-x64@0.1.13': + '@rslint/win32-x64@0.2.0': optional: true '@rspack/binding-darwin-arm64@1.7.0': diff --git a/rslint.json b/rslint.json index 937303190a4c..a01673a9a955 100644 --- a/rslint.json +++ b/rslint.json @@ -37,7 +37,19 @@ "@typescript-eslint/no-unused-vars": "off", "@typescript-eslint/no-var-requires": "off", "@typescript-eslint/no-require-imports": "off", - "@typescript-eslint/no-empty-function": "off" + "@typescript-eslint/no-empty-function": "off", + "@typescript-eslint/ban-ts-comment": "off", + "@typescript-eslint/consistent-indexed-object-style": "off", + "@typescript-eslint/no-this-alias": "off", + "@typescript-eslint/consistent-type-definitions": "off", + "@typescript-eslint/consistent-return": "off", + "@typescript-eslint/consistent-type-exports": "off", + "@typescript-eslint/consistent-generic-constructors": "off", + "@typescript-eslint/ban-types": "off", + "@typescript-eslint/no-extraneous-class": "off", + "@typescript-eslint/consistent-type-imports": "off", + "@typescript-eslint/no-invalid-void-type": "off", + "@typescript-eslint/default-param-last": "error" }, "plugins": ["@typescript-eslint"] } From 476c9a0455323a762e1acdd14d1b2fea91327462 Mon Sep 17 00:00:00 2001 From: 9aoy <9aoyuao@gmail.com> Date: Thu, 15 Jan 2026 20:44:56 +0800 Subject: [PATCH 65/87] test: support filter test by absolute path (#12749) * test: support filter test by absolute path * Update packages/rspack-test-tools/src/helper/directory.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update packages/rspack-test-tools/src/helper/directory.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update tests/rspack-test/Cache.test.js Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * fix: lint * docs: update -t --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../rspack-test-tools/etc/test-tools.api.md | 3 ++- .../rspack-test-tools/src/helper/directory.ts | 21 +++++++++++++++++-- tests/rspack-test/Cache.test.js | 2 +- tests/rspack-test/rstest.config.ts | 19 +++++++++-------- .../en/contribute/development/testing.mdx | 9 +++++--- .../zh/contribute/development/testing.mdx | 9 +++++--- 6 files changed, 44 insertions(+), 19 deletions(-) diff --git a/packages/rspack-test-tools/etc/test-tools.api.md b/packages/rspack-test-tools/etc/test-tools.api.md index da6cd4b9138a..2b682c08fea1 100644 --- a/packages/rspack-test-tools/etc/test-tools.api.md +++ b/packages/rspack-test-tools/etc/test-tools.api.md @@ -138,7 +138,8 @@ export function createWatchCase(name: string, src: string, dist: string, temp: s export function createWatchIncrementalCase(name: string, src: string, dist: string, temp: string, options?: WatchIncrementalOptions): void; // @public (undocumented) -export function describeByWalk(testFile: string, createCase: (name: string, src: string, dist: string) => void, options?: { +export function describeByWalk( +testFile: string, createCase: (name: string, src: string, dist: string) => void, options?: { type?: 'file' | 'directory'; level?: number; source?: string; diff --git a/packages/rspack-test-tools/src/helper/directory.ts b/packages/rspack-test-tools/src/helper/directory.ts index b06349d5faf2..be56a34c49d3 100644 --- a/packages/rspack-test-tools/src/helper/directory.ts +++ b/packages/rspack-test-tools/src/helper/directory.ts @@ -9,6 +9,9 @@ export const isValidCaseDirectory = (name: string) => !name.startsWith('_') && !name.startsWith('.') && name !== 'node_modules'; export function describeByWalk( + /** + * The test file absolute path. + */ testFile: string, createCase: (name: string, src: string, dist: string) => void, options: { @@ -30,6 +33,7 @@ export function describeByWalk( options.source || path.join(path.dirname(testFile), `${testId}Cases`); const testSourceId = path.basename(sourceBase); + const absoluteTestDir = path.dirname(testFile); const distBase = options.dist || path.join(path.dirname(testFile), 'js', testId); @@ -75,8 +79,21 @@ export function describeByWalk( .split('.') .shift()!, ); + let suiteName = name; - describeFn(name, () => { + // support filter test by absolute path + if (process.env.testFilter?.includes(absoluteTestDir)) { + const fullCasePath = path.join( + absoluteTestDir, + testSourceId, + caseName, + ); + if (fullCasePath.includes(process.env.testFilter!)) { + suiteName = fullCasePath; + } + } + + describeFn(suiteName, () => { const source = path.join(sourceBase, caseName); let dist = ''; if (absoluteDist) { @@ -89,7 +106,7 @@ export function describeByWalk( dist = path.join(sourceBase, caseName, relativeDist); } } - createCase(name, source, dist); + createCase(suiteName, source, dist); }); } }); diff --git a/tests/rspack-test/Cache.test.js b/tests/rspack-test/Cache.test.js index 8e891bd0f57d..6d70cf7193df 100644 --- a/tests/rspack-test/Cache.test.js +++ b/tests/rspack-test/Cache.test.js @@ -4,7 +4,7 @@ const tempDir = path.resolve(__dirname, `./js/temp`); // Run tests rspack-test/tests/cacheCases in target async-node describeByWalk( - "cache", + __filename, (name, src, dist) => { createCacheCase(name, src, dist, "async-node", path.join(tempDir, name)); }, diff --git a/tests/rspack-test/rstest.config.ts b/tests/rspack-test/rstest.config.ts index aa8c2ead2b58..9deb8c0beb0b 100644 --- a/tests/rspack-test/rstest.config.ts +++ b/tests/rspack-test/rstest.config.ts @@ -34,6 +34,14 @@ const wasmConfig = process.env.WASM && defineProject({ maxConcurrency: 1, }); +const testFilter = process.argv.includes("--test") || process.argv.includes("-t") + ? process.argv[ + (process.argv.includes("-t") + ? process.argv.indexOf("-t") + : process.argv.indexOf("--test")) + 1 + ] + : undefined; + const sharedConfig = defineProject({ setupFiles: setupFilesAfterEnv, testTimeout: process.env.CI ? 60000 : 30000, @@ -75,14 +83,7 @@ const sharedConfig = defineProject({ RSPACK_DEV: 'false', RSPACK_EXPERIMENTAL: 'true', RSPACK_CONFIG_VALIDATE: "strict", - testFilter: - process.argv.includes("--test") || process.argv.includes("-t") - ? process.argv[ - (process.argv.includes("-t") - ? process.argv.indexOf("-t") - : process.argv.indexOf("--test")) + 1 - ] - : undefined, + testFilter, printLogger: process.env.DEBUG === "test" ? 'true' : 'false', __TEST_PATH__: __dirname, __TEST_FIXTURES_PATH__: path.resolve(__dirname, "fixtures"), @@ -112,7 +113,7 @@ export default defineConfig({ RSPACK_HOT_TEST: 'true', }, }], - reporters: ['default'], + reporters: testFilter ? ['verbose'] : ['default'], hideSkippedTests: true, pool: { maxWorkers: process.env.WASM ? 1 : "80%", diff --git a/website/docs/en/contribute/development/testing.mdx b/website/docs/en/contribute/development/testing.mdx index 9c4c2c838660..e94a9e1398d4 100644 --- a/website/docs/en/contribute/development/testing.mdx +++ b/website/docs/en/contribute/development/testing.mdx @@ -41,7 +41,7 @@ You can run Rspack tests by running `./x test unit` or `pnpm run test:unit` at t You can also go to the `tests/rspack-test` folder and run `npm run test` to run test cases and add some arguments: - **When refreshing test snapshots is needed**: Add `-u`, like `npm run test -- -u` -- **When filtering test cases is needed**: Add `-t`, like `npm run test -- -t configCases/asset` to only run test cases from the `tests/rspack-test/configCases/asset` folder. Pattern matching supports regex, see [rstest](https://rstest.rs/config/test/testNamePattern) for details. +- **When filtering test cases is needed**: Add `-t`. Pattern matching supports regex, see [rstest](https://rstest.rs/config/test/testNamePattern) for details. ### Running tests @@ -51,8 +51,11 @@ You can run these test cases in the following ways: - Or run `npm run test` from the `tests/rspack-test` directory. - To update snapshots, run `npm run test -- -u` from the `tests/rspack-test` directory. - To pass specific rstest cli arguments, run `npm run test -- {args}` from the `tests/rspack-test` directory. -- To filter specific test cases, run `npm run test -- -t path-of-spec` from the `tests/rspack-test` directory. - - Like `npm run test -- -t configCases/asset` to only run test cases from the `tests/rspack-test/configCases/asset` folder (config will be automatically mapped to configCases, and other folders will work in a similar way). +- To filter specific test cases, run `npm run test -- -t ${testPath}` where `testPath` can be either an absolute or relative path. + - For example: + - `npm run test -- -t hotCases/json/error-in-json` (or `npm run test -- -t /Users/rspack/tests/rspack-test/hotCases/json/error-in-json`) will run all tests in the `error-in-json` test case. + - `npm run test -- -t hotCases/json` (or `npm run test -- -t /Users/rspack/tests/rspack-test/hotCases/json`) will run all test cases in the `json` directory. + - `npm run test -- -t hotCases` (or `npm run test -- -t /Users/rspack/tests/rspack-test/hotCases`) will run all test cases in the `hotCases` directory. - To use Rspack Wasm for running test cases, you need to additionally configure the following environment variables: 1. `NAPI_RS_FORCE_WASI=1`: Forces the use of Rspack Wasm instead of native binding 2. `WASM=1`: Enables Wasm-specific test configurations diff --git a/website/docs/zh/contribute/development/testing.mdx b/website/docs/zh/contribute/development/testing.mdx index 2c20865796bd..cf5f85274736 100644 --- a/website/docs/zh/contribute/development/testing.mdx +++ b/website/docs/zh/contribute/development/testing.mdx @@ -41,7 +41,7 @@ Rspack 的测试用例包括如下: 也可以进入 `tests/rspack-test` 文件夹并运行 `npm run test` 来运行测试用例,并且对测试流程进行更精细的控制: - **需要刷新测试快照时**:添加 `-u` 参数,如 `npm run test -- -u` -- **需要过滤测试用例时**:添加 `-t` 参数,如 `npm run test -- -t configCases/asset` 即可仅运行 `tests/rspack-test/configCases/asset` 文件夹下的用例。匹配支持正则,详见 [rstest](https://rstest.rs/config/test/testNamePattern) +- **需要过滤测试用例时**:添加 `-t` 参数。匹配支持正则,详见 [rstest](https://rstest.rs/config/test/testNamePattern) ### 运行测试 @@ -51,8 +51,11 @@ Rspack 的测试用例包括如下: - 或在 `tests/rspack-test` 目录下运行 `npm run test`。 - 如需更新 snapshot,在 `tests/rspack-test` 目录下运行 `npm run test -- -u`。 - 如需传入特定 rstest cli 参数,在 `tests/rspack-test` 目录下运行 `npm run test -- {args}`。 -- 如需过滤特定测试用例,在 `tests/rspack-test` 目录下运行 `npm run test -- -t path-of-spec`。 - - 如 `npm run test -- -t configCases/asset` 即可仅运行 `tests/rspack-test/configCases/asset` 文件夹下的用例(config 会自动映射到 configCases,其他文件夹类似)。 +- 如需过滤特定测试用例,运行 `npm run test -- -t ${testPath}`,其中 `${testPath}` 可以是绝对路径或相对路径。 + - 例如: + - `npm run test -- -t hotCases/json/error-in-json` (或 `npm run test -- -t /Users/rspack/tests/rspack-test/hotCases/json/error-in-json`) 将运行 `error-in-json` 测试用例中的所有测试。 + - `npm run test -- -t hotCases/json` (或 `npm run test -- -t /Users/rspack/tests/rspack-test/hotCases/json`) 将运行 `json` 目录下的所有测试用例。 + - `npm run test -- -t hotCases` (或 `npm run test -- -t /Users/rspack/tests/rspack-test/hotCases`) 将运行 `hotCases` 目录下的所有测试用例。 - 如需使用 Rspack Wasm 运行测试用例,需要额外配置以下环境变量: 1. `NAPI_RS_FORCE_WASI=1`: 强制使用 Rspack Wasm 而不是原生绑定 2. `WASM=1`:启用 Wasm 专用的测试配置 From ef467b46e73ce4ca7269940c11cad832027c6e7d Mon Sep 17 00:00:00 2001 From: hardfist Date: Thu, 15 Jan 2026 22:51:44 +0800 Subject: [PATCH 66/87] refactor: use newtype for alias artifact (#12754) --- .../src/artifacts/async_modules_artifact.rs | 47 +++++++++++++++ .../cgc_runtime_requirements_artifact.rs | 55 ++++++++++++++++++ .../src/artifacts/chunk_render_artifact.rs | 55 ++++++++++++++++++ .../dependencies_diagnostics_artifact.rs | 58 +++++++++++++++++++ .../imported_by_defer_modules_artifact.rs | 47 +++++++++++++++ crates/rspack_core/src/artifacts/mod.rs | 24 ++++---- .../src/artifacts/module_ids_artifact.rs | 51 ++++++++++++++++ .../compilation/create_chunk_assets/mod.rs | 2 +- .../src/compilation/finish_modules/mod.rs | 3 +- 9 files changed, 328 insertions(+), 14 deletions(-) create mode 100644 crates/rspack_core/src/artifacts/async_modules_artifact.rs create mode 100644 crates/rspack_core/src/artifacts/cgc_runtime_requirements_artifact.rs create mode 100644 crates/rspack_core/src/artifacts/chunk_render_artifact.rs create mode 100644 crates/rspack_core/src/artifacts/dependencies_diagnostics_artifact.rs create mode 100644 crates/rspack_core/src/artifacts/imported_by_defer_modules_artifact.rs create mode 100644 crates/rspack_core/src/artifacts/module_ids_artifact.rs diff --git a/crates/rspack_core/src/artifacts/async_modules_artifact.rs b/crates/rspack_core/src/artifacts/async_modules_artifact.rs new file mode 100644 index 000000000000..de7c389c845c --- /dev/null +++ b/crates/rspack_core/src/artifacts/async_modules_artifact.rs @@ -0,0 +1,47 @@ +use std::ops::{Deref, DerefMut}; + +use rspack_collections::IdentifierSet; + +#[derive(Debug, Default, Clone)] +pub struct AsyncModulesArtifact(IdentifierSet); + +impl Deref for AsyncModulesArtifact { + type Target = IdentifierSet; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for AsyncModulesArtifact { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +impl From for AsyncModulesArtifact { + fn from(value: IdentifierSet) -> Self { + Self(value) + } +} + +impl From for IdentifierSet { + fn from(value: AsyncModulesArtifact) -> Self { + value.0 + } +} + +impl FromIterator<::Item> for AsyncModulesArtifact { + fn from_iter::Item>>(iter: T) -> Self { + Self(IdentifierSet::from_iter(iter)) + } +} + +impl IntoIterator for AsyncModulesArtifact { + type Item = ::Item; + type IntoIter = ::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.0.into_iter() + } +} diff --git a/crates/rspack_core/src/artifacts/cgc_runtime_requirements_artifact.rs b/crates/rspack_core/src/artifacts/cgc_runtime_requirements_artifact.rs new file mode 100644 index 000000000000..97736e8d5332 --- /dev/null +++ b/crates/rspack_core/src/artifacts/cgc_runtime_requirements_artifact.rs @@ -0,0 +1,55 @@ +use std::ops::{Deref, DerefMut}; + +use rspack_collections::UkeyMap; + +use crate::{ChunkUkey, RuntimeGlobals}; + +#[derive(Debug, Default, Clone)] +pub struct CgcRuntimeRequirementsArtifact(UkeyMap); + +impl Deref for CgcRuntimeRequirementsArtifact { + type Target = UkeyMap; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for CgcRuntimeRequirementsArtifact { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +impl From> for CgcRuntimeRequirementsArtifact { + fn from(value: UkeyMap) -> Self { + Self(value) + } +} + +impl From for UkeyMap { + fn from(value: CgcRuntimeRequirementsArtifact) -> Self { + value.0 + } +} + +impl FromIterator< as IntoIterator>::Item> + for CgcRuntimeRequirementsArtifact +{ + fn from_iter< + T: IntoIterator as IntoIterator>::Item>, + >( + iter: T, + ) -> Self { + Self(UkeyMap::from_iter(iter)) + } +} + +impl IntoIterator for CgcRuntimeRequirementsArtifact { + type Item = as IntoIterator>::Item; + type IntoIter = as IntoIterator>::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.0.into_iter() + } +} diff --git a/crates/rspack_core/src/artifacts/chunk_render_artifact.rs b/crates/rspack_core/src/artifacts/chunk_render_artifact.rs new file mode 100644 index 000000000000..31e98c9cdf94 --- /dev/null +++ b/crates/rspack_core/src/artifacts/chunk_render_artifact.rs @@ -0,0 +1,55 @@ +use std::ops::{Deref, DerefMut}; + +use rspack_collections::UkeyMap; + +use crate::{ChunkRenderResult, ChunkUkey}; + +#[derive(Debug, Default, Clone)] +pub struct ChunkRenderArtifact(UkeyMap); + +impl Deref for ChunkRenderArtifact { + type Target = UkeyMap; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for ChunkRenderArtifact { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +impl From> for ChunkRenderArtifact { + fn from(value: UkeyMap) -> Self { + Self(value) + } +} + +impl From for UkeyMap { + fn from(value: ChunkRenderArtifact) -> Self { + value.0 + } +} + +impl FromIterator< as IntoIterator>::Item> + for ChunkRenderArtifact +{ + fn from_iter< + T: IntoIterator as IntoIterator>::Item>, + >( + iter: T, + ) -> Self { + Self(UkeyMap::from_iter(iter)) + } +} + +impl IntoIterator for ChunkRenderArtifact { + type Item = as IntoIterator>::Item; + type IntoIter = as IntoIterator>::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.0.into_iter() + } +} diff --git a/crates/rspack_core/src/artifacts/dependencies_diagnostics_artifact.rs b/crates/rspack_core/src/artifacts/dependencies_diagnostics_artifact.rs new file mode 100644 index 000000000000..92889c2960c0 --- /dev/null +++ b/crates/rspack_core/src/artifacts/dependencies_diagnostics_artifact.rs @@ -0,0 +1,58 @@ +use std::ops::{Deref, DerefMut}; + +use rspack_collections::IdentifierMap; +use rspack_error::Diagnostic; + +#[derive(Debug, Default, Clone)] +pub struct DependenciesDiagnosticsArtifact(IdentifierMap>); + +impl DependenciesDiagnosticsArtifact { + pub fn into_values(self) -> impl Iterator> { + self.0.into_values() + } +} + +impl Deref for DependenciesDiagnosticsArtifact { + type Target = IdentifierMap>; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for DependenciesDiagnosticsArtifact { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +impl From>> for DependenciesDiagnosticsArtifact { + fn from(value: IdentifierMap>) -> Self { + Self(value) + } +} + +impl From for IdentifierMap> { + fn from(value: DependenciesDiagnosticsArtifact) -> Self { + value.0 + } +} + +impl FromIterator<> as IntoIterator>::Item> + for DependenciesDiagnosticsArtifact +{ + fn from_iter> as IntoIterator>::Item>>( + iter: T, + ) -> Self { + Self(IdentifierMap::from_iter(iter)) + } +} + +impl IntoIterator for DependenciesDiagnosticsArtifact { + type Item = > as IntoIterator>::Item; + type IntoIter = > as IntoIterator>::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.0.into_iter() + } +} diff --git a/crates/rspack_core/src/artifacts/imported_by_defer_modules_artifact.rs b/crates/rspack_core/src/artifacts/imported_by_defer_modules_artifact.rs new file mode 100644 index 000000000000..48c168a25eee --- /dev/null +++ b/crates/rspack_core/src/artifacts/imported_by_defer_modules_artifact.rs @@ -0,0 +1,47 @@ +use std::ops::{Deref, DerefMut}; + +use rspack_collections::IdentifierSet; + +#[derive(Debug, Default, Clone)] +pub struct ImportedByDeferModulesArtifact(IdentifierSet); + +impl Deref for ImportedByDeferModulesArtifact { + type Target = IdentifierSet; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for ImportedByDeferModulesArtifact { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +impl From for ImportedByDeferModulesArtifact { + fn from(value: IdentifierSet) -> Self { + Self(value) + } +} + +impl From for IdentifierSet { + fn from(value: ImportedByDeferModulesArtifact) -> Self { + value.0 + } +} + +impl FromIterator<::Item> for ImportedByDeferModulesArtifact { + fn from_iter::Item>>(iter: T) -> Self { + Self(IdentifierSet::from_iter(iter)) + } +} + +impl IntoIterator for ImportedByDeferModulesArtifact { + type Item = ::Item; + type IntoIter = ::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.0.into_iter() + } +} diff --git a/crates/rspack_core/src/artifacts/mod.rs b/crates/rspack_core/src/artifacts/mod.rs index bdc364889edf..211fef3e38c6 100644 --- a/crates/rspack_core/src/artifacts/mod.rs +++ b/crates/rspack_core/src/artifacts/mod.rs @@ -1,31 +1,31 @@ -use rspack_collections::{IdentifierMap, IdentifierSet, UkeyMap}; -use rspack_error::Diagnostic; - -use crate::{ChunkRenderResult, ChunkUkey, ModuleId, RuntimeGlobals}; - +mod async_modules_artifact; +mod cgc_runtime_requirements_artifact; mod cgm_hash_artifact; mod cgm_runtime_requirement_artifact; mod chunk_hashes_artifact; mod chunk_ids_artifact; +mod chunk_render_artifact; mod chunk_render_cache_artifact; mod code_generation_results; +mod dependencies_diagnostics_artifact; +mod imported_by_defer_modules_artifact; mod module_graph_cache_artifact; +mod module_ids_artifact; mod module_static_cache_artifact; mod side_effects_do_optimize_artifact; +pub use async_modules_artifact::AsyncModulesArtifact; +pub use cgc_runtime_requirements_artifact::CgcRuntimeRequirementsArtifact; pub use cgm_hash_artifact::*; pub use cgm_runtime_requirement_artifact::*; pub use chunk_hashes_artifact::*; pub use chunk_ids_artifact::*; +pub use chunk_render_artifact::ChunkRenderArtifact; pub use chunk_render_cache_artifact::ChunkRenderCacheArtifact; pub use code_generation_results::*; +pub use dependencies_diagnostics_artifact::DependenciesDiagnosticsArtifact; +pub use imported_by_defer_modules_artifact::ImportedByDeferModulesArtifact; pub use module_graph_cache_artifact::*; +pub use module_ids_artifact::ModuleIdsArtifact; pub use module_static_cache_artifact::*; pub use side_effects_do_optimize_artifact::*; - -pub type AsyncModulesArtifact = IdentifierSet; -pub type ImportedByDeferModulesArtifact = IdentifierSet; -pub type DependenciesDiagnosticsArtifact = IdentifierMap>; -pub type ModuleIdsArtifact = IdentifierMap; -pub type CgcRuntimeRequirementsArtifact = UkeyMap; -pub type ChunkRenderArtifact = UkeyMap; diff --git a/crates/rspack_core/src/artifacts/module_ids_artifact.rs b/crates/rspack_core/src/artifacts/module_ids_artifact.rs new file mode 100644 index 000000000000..22ed6e161c7c --- /dev/null +++ b/crates/rspack_core/src/artifacts/module_ids_artifact.rs @@ -0,0 +1,51 @@ +use std::ops::{Deref, DerefMut}; + +use rspack_collections::IdentifierMap; + +use crate::ModuleId; + +#[derive(Debug, Default, Clone)] +pub struct ModuleIdsArtifact(IdentifierMap); + +impl Deref for ModuleIdsArtifact { + type Target = IdentifierMap; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for ModuleIdsArtifact { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +impl From> for ModuleIdsArtifact { + fn from(value: IdentifierMap) -> Self { + Self(value) + } +} + +impl From for IdentifierMap { + fn from(value: ModuleIdsArtifact) -> Self { + value.0 + } +} + +impl FromIterator< as IntoIterator>::Item> for ModuleIdsArtifact { + fn from_iter as IntoIterator>::Item>>( + iter: T, + ) -> Self { + Self(IdentifierMap::from_iter(iter)) + } +} + +impl IntoIterator for ModuleIdsArtifact { + type Item = as IntoIterator>::Item; + type IntoIter = as IntoIterator>::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.0.into_iter() + } +} diff --git a/crates/rspack_core/src/compilation/create_chunk_assets/mod.rs b/crates/rspack_core/src/compilation/create_chunk_assets/mod.rs index d26ec44ff4b4..69a7fe2074c6 100644 --- a/crates/rspack_core/src/compilation/create_chunk_assets/mod.rs +++ b/crates/rspack_core/src/compilation/create_chunk_assets/mod.rs @@ -100,7 +100,7 @@ impl Compilation { }) .await; - let mut chunk_render_results: UkeyMap = Default::default(); + let mut chunk_render_results = ChunkRenderArtifact::default(); for result in results { let item = result.to_rspack_result()?; let (key, value) = item?; diff --git a/crates/rspack_core/src/compilation/finish_modules/mod.rs b/crates/rspack_core/src/compilation/finish_modules/mod.rs index ce70e2d0d57f..7d972011f6e5 100644 --- a/crates/rspack_core/src/compilation/finish_modules/mod.rs +++ b/crates/rspack_core/src/compilation/finish_modules/mod.rs @@ -161,7 +161,8 @@ impl Compilation { .collect::>(); (*module_identifier, diagnostics) }) - .collect(); + .collect::>>() + .into(); let all_modules_diagnostics = if has_mutations { dependencies_diagnostics_artifact.extend(dependencies_diagnostics); dependencies_diagnostics_artifact.clone() From cc18589648a80174e42e21af0ac09150aa884a5f Mon Sep 17 00:00:00 2001 From: CPunisher <1343316114@qq.com> Date: Fri, 16 Jan 2026 14:49:32 +0800 Subject: [PATCH 67/87] chore: bump `swc_core` from 54 to 55 (#12758) * chore: bump swc * chore: bump swc exp * chore: cargo codegen --- Cargo.lock | 184 ++++++++++++----------- Cargo.toml | 16 +- crates/rspack_workspace/src/generated.rs | 2 +- 3 files changed, 104 insertions(+), 98 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dc5f4b2d2bde..62fef0eb4fbf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1307,6 +1307,12 @@ version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59f8e79d1fbf76bdfbde321e902714bf6c49df88a7dda6fc682fc2979226962d" +[[package]] +name = "dragonbox_ecma" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a5577f010d4e1bb3f3c4d6081e05718eb6992cf20119cab4d3abadff198b5ae" + [[package]] name = "dtoa" version = "1.0.9" @@ -5641,9 +5647,9 @@ checksum = "b7401a30af6cb5818bb64852270bb722533397edcfc7344954a38f420819ece2" [[package]] name = "swc" -version = "52.0.0" +version = "53.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d330c7945664f5fe9594443dbaea3abfa275a1d6513d0888d163cc580ddab408" +checksum = "54d8a1ae04e3a6aa68590bdf49f908a2e6d66f2c06d33a0e489de2e0e7a235f8" dependencies = [ "anyhow", "base64", @@ -5750,9 +5756,9 @@ dependencies = [ [[package]] name = "swc_compiler_base" -version = "45.0.0" +version = "46.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05764fac0b452c050eec49135de597223166590b9992ce9096628db06fce5ae3" +checksum = "c5891ef751db4d8257714d78792b0100eedeb8ba229e7be2e90e26074db58920" dependencies = [ "anyhow", "base64", @@ -5809,9 +5815,9 @@ dependencies = [ [[package]] name = "swc_core" -version = "54.0.0" +version = "55.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f361c932ffe029754a10512ee217f550109ee80dda1fe6ec90772440bfc0a68" +checksum = "b4017f75dd2c60b9840edd096ee7d0b86e250b7604746f00060272161bbf5aa1" dependencies = [ "par-core", "swc", @@ -5838,9 +5844,9 @@ dependencies = [ [[package]] name = "swc_ecma_ast" -version = "19.0.0" +version = "20.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "724195600825cbdd2a899d5473d2ce1f24ae418bff1231f160ecf38a3bc81f46" +checksum = "4682d975a3b4ea33f351e7938db4db41f757d9abe537af4780611ef006531698" dependencies = [ "bitflags 2.9.1", "cbor4ii", @@ -5859,25 +5865,24 @@ dependencies = [ [[package]] name = "swc_ecma_codegen" -version = "21.0.0" +version = "22.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c77d9d21345ca986ae3b5ff1a4fa3607b15b07ed397506e6dba32e867cf40fd" +checksum = "c5bee5594d86feee801134048e926748a31ad10e7befef507322b056c113e148" dependencies = [ "ascii", "compact_str", + "dragonbox_ecma", "memchr", "num-bigint", "once_cell", "regex", "rustc-hash", - "ryu-js", "serde", "swc_allocator", "swc_atoms", "swc_common", "swc_ecma_ast", "swc_ecma_codegen_macros", - "swc_sourcemap", "tracing", ] @@ -5894,9 +5899,9 @@ dependencies = [ [[package]] name = "swc_ecma_compat_bugfixes" -version = "39.0.0" +version = "40.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75920017b78c5231b47250c329930b76031f703ebfb14ead7b466f43374d6828" +checksum = "a4bc37853b9131944aabc14f78870514dbd6dd45bf90bb14df27f435ed78a863" dependencies = [ "rustc-hash", "swc_atoms", @@ -5912,9 +5917,9 @@ dependencies = [ [[package]] name = "swc_ecma_compat_common" -version = "30.0.0" +version = "31.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdb4c2493374ec4d5c456ebdf5de3168d56993147b3888ec47d837334898eb4b" +checksum = "d5b2d61ac98952d5a1cf1b71b83f424e5a95146d94a6855777d08116818a9061" dependencies = [ "swc_common", "swc_ecma_ast", @@ -5924,9 +5929,9 @@ dependencies = [ [[package]] name = "swc_ecma_compat_es2015" -version = "39.0.0" +version = "40.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e654cd8be79bc1aba940135d600d975dcec9047e8935897db9f53fa8bd94c3e" +checksum = "e8b5620d55a7916f36478231b160c7763513708de1c4f8ffa2befe4be1db4282" dependencies = [ "arrayvec", "indexmap", @@ -5951,9 +5956,9 @@ dependencies = [ [[package]] name = "swc_ecma_compat_es2016" -version = "35.0.0" +version = "36.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ed1b54c134f5c972dabe6d153dab0ec26db0e6ca31ad7b9ec1824a46c595a0" +checksum = "cfa4e8572155e752c98a6155d4b5fab965d6d7ca665889994c7934280c7137f0" dependencies = [ "swc_ecma_ast", "swc_ecma_transformer", @@ -5964,9 +5969,9 @@ dependencies = [ [[package]] name = "swc_ecma_compat_es2017" -version = "35.0.0" +version = "36.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34b18078fcaf7bf8f16d41d644383d97879bf6677aacbd97a2c4426b2a6c85dd" +checksum = "5ed2e895823c6863bf08ee50f8bc42c3ea1e11fe12124b1bac518ad123417f1a" dependencies = [ "serde", "swc_common", @@ -5979,9 +5984,9 @@ dependencies = [ [[package]] name = "swc_ecma_compat_es2018" -version = "36.0.0" +version = "37.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25c6661887ef18abf36746dfc4aea1c6bb8f006656a1db11fbcaefd340764492" +checksum = "e41a9161a34e4c763254d7008ab69e50f084d652cc8d18d6284be26bc3a8d1e4" dependencies = [ "serde", "swc_ecma_ast", @@ -5993,9 +5998,9 @@ dependencies = [ [[package]] name = "swc_ecma_compat_es2019" -version = "35.0.0" +version = "36.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c6d2040d966a2db719193c13739765bb4026d746ed34767323fbc4ecc241dd4" +checksum = "e3b8a4a95459fa57bbe1e85b3ce494d41db37c2f5b74173da0c03f6a9a9d601d" dependencies = [ "swc_common", "swc_ecma_ast", @@ -6007,9 +6012,9 @@ dependencies = [ [[package]] name = "swc_ecma_compat_es2020" -version = "37.0.0" +version = "38.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368df3e1713a0b2cecf51e1f5d2ed2f99367e21e6dbb3b4c1b7603664bc4854f" +checksum = "668053c35dff7726323974a3c359c59dcdec51b46029fb32de935b2808179b49" dependencies = [ "serde", "swc_common", @@ -6024,9 +6029,9 @@ dependencies = [ [[package]] name = "swc_ecma_compat_es2021" -version = "35.0.0" +version = "36.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "485ea701061eaa7934461dd4874deda80e6b0f254c672c232fc14a4e3b6e6008" +checksum = "3314c63ddc46044214d328f4a820735e1ce0318e3dedfca8c508e7ce2b799c09" dependencies = [ "swc_ecma_ast", "swc_ecma_transformer", @@ -6037,9 +6042,9 @@ dependencies = [ [[package]] name = "swc_ecma_compat_es2022" -version = "37.0.0" +version = "38.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee87fab5c61b2147798343581ca60b5320362b82a0140faa080757efc6498d1e" +checksum = "ef462e62ce35b87c1ab2aff8926549308c5505e6d7ac9acc90af618d05734f42" dependencies = [ "rustc-hash", "swc_atoms", @@ -6057,9 +6062,9 @@ dependencies = [ [[package]] name = "swc_ecma_compat_es3" -version = "26.0.0" +version = "27.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5107a2c40d6779f7c0f7e5dd7522304b499d2310526450cd9f49c3ce3072281" +checksum = "0c1dd219e6e1b668223ae4e41141c0eeb78d14cfd178b97d6c532b93a27b3fe5" dependencies = [ "swc_common", "swc_ecma_ast", @@ -6071,9 +6076,9 @@ dependencies = [ [[package]] name = "swc_ecma_ext_transforms" -version = "25.0.0" +version = "26.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd5ec1b4d8740ccf1b56f0910648bdc23b23623514a88ce39a071b79e825080c" +checksum = "2a6aed670f87cde675f40dcd0ff5196f3cec9b2bc7e6fed12adf5b808f18eb69" dependencies = [ "phf", "swc_common", @@ -6084,9 +6089,9 @@ dependencies = [ [[package]] name = "swc_ecma_hooks" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac98742c42ad8bdca8ebeccf6b7a420369dab3a1cb88ef1f017eb1e588014ba8" +checksum = "8c9adff1f01550ef653e262ad709a2914d3dd6cfd559aea2e28eeeab8f895981" dependencies = [ "swc_atoms", "swc_common", @@ -6118,9 +6123,9 @@ dependencies = [ [[package]] name = "swc_ecma_minifier" -version = "42.0.0" +version = "43.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e55ced848cae0fa5e33e465540bbeafd70645f4099b8b9b3ca66e66d95f52300" +checksum = "fa6c2bc0cd5a04a2be11accdc58f0497f97bd44943c03d76371729694cf601e3" dependencies = [ "arrayvec", "bitflags 2.9.1", @@ -6154,9 +6159,9 @@ dependencies = [ [[package]] name = "swc_ecma_parser" -version = "32.0.0" +version = "33.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1d0c36843109fff178bbedc439b4190daa865d78e553134243a4df220329fdd" +checksum = "3cb866d9ca2df54daa4a460bdd105cd641d780f0578928cb1f7f4e54574bb2bb" dependencies = [ "bitflags 2.9.1", "either", @@ -6174,9 +6179,9 @@ dependencies = [ [[package]] name = "swc_ecma_preset_env" -version = "45.0.0" +version = "46.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4f1f6c815a26faa019a3629890c4ca8b6657b4b3682237fabf948899fa81e91" +checksum = "4415d2eb6277081b91daffedcd4ac9701bc6b03427764b28a7f14da26aaae224" dependencies = [ "anyhow", "foldhash 0.1.5", @@ -6199,9 +6204,9 @@ dependencies = [ [[package]] name = "swc_ecma_quote_macros" -version = "32.0.0" +version = "33.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d70a7f12dd07015e00bf30770497de4ab45db2cf34ca9e870aece9e456166032" +checksum = "b0f033afe55c4bc19e1a305c7d9e7cce50baf7a3df242e3da26948674b26dd9f" dependencies = [ "anyhow", "proc-macro2", @@ -6217,9 +6222,9 @@ dependencies = [ [[package]] name = "swc_ecma_transformer" -version = "6.0.0" +version = "7.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12e2aaef402a685c66f7cfb983b7b218ca42cd3de15c8aaf912f10ea8cd77402" +checksum = "8f920b9afa7b4354b697fdaa2120da4abfe00dc45a9e5ca1a2a91113012151db" dependencies = [ "rustc-hash", "swc_atoms", @@ -6234,9 +6239,9 @@ dependencies = [ [[package]] name = "swc_ecma_transforms" -version = "44.0.0" +version = "45.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3bba9c21bfc599f9a7aae0e2f9107b0b3156ee86bbdb796fd36ef8c265ff8c0" +checksum = "a913f58b3288afbe700aed8110cb98c4fddec471aa60d5a6079caad7b1994b22" dependencies = [ "par-core", "swc_common", @@ -6253,9 +6258,9 @@ dependencies = [ [[package]] name = "swc_ecma_transforms_base" -version = "35.0.0" +version = "36.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83f9f0dee4466e6eeb7042f2a0fc6c84298dfa914baff5bcfb44beb9f24b215f" +checksum = "acdca4cb85a06e5831afb59a3bf6b642aed19b6ea965df3b90ad43d2984e2d46" dependencies = [ "better_scoped_tls", "indexmap", @@ -6276,9 +6281,9 @@ dependencies = [ [[package]] name = "swc_ecma_transforms_classes" -version = "35.0.0" +version = "36.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dc00cb0ee27cb78fc719482a7bf5697b5052b878dbd5ba6b65249c1ddcf8832" +checksum = "3567a1a95c2f6d5f7c3ca59051cf099c5ac54cf8f293bcfb43b385477b9f80a9" dependencies = [ "swc_common", "swc_ecma_ast", @@ -6289,9 +6294,9 @@ dependencies = [ [[package]] name = "swc_ecma_transforms_compat" -version = "40.0.0" +version = "41.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91cbf17a99fdb5d8604a2c5109fa6980f59b9b5827e715358ec24249449e74d7" +checksum = "747972c4b18286ee79206dc70aef0f1a6593b62eb45364eccf7f34734e2148ec" dependencies = [ "indexmap", "par-core", @@ -6330,9 +6335,9 @@ dependencies = [ [[package]] name = "swc_ecma_transforms_module" -version = "38.0.0" +version = "39.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a884810184e70414a38b7572c4ea6ef66fed036cfdcd9f9804ce83e14b1ad76" +checksum = "6ce560526cbd4e3cbd1c9183d099954ebd2399099ab8d6b9651f83728ef1f622" dependencies = [ "Inflector", "anyhow", @@ -6358,9 +6363,9 @@ dependencies = [ [[package]] name = "swc_ecma_transforms_optimization" -version = "37.0.0" +version = "38.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bc5e01b1e5c696b4784a133a5ee28ca8b309800d858ab63509069df8fe30181" +checksum = "ab76533e9da38c8f13ca1a9d0a6edd6b3de328a281441aee9810281e1b7ba4e9" dependencies = [ "bytes-str", "dashmap 5.5.3", @@ -6382,9 +6387,9 @@ dependencies = [ [[package]] name = "swc_ecma_transforms_proposal" -version = "35.0.0" +version = "36.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b8f121d69b5ec24359e611be11075734f0fd535b0ce2f8f2887b0cafb0166ef" +checksum = "35a8e84e073ab1675784257ef2f707f5d914724b147144a3617905d2eb81f93c" dependencies = [ "either", "rustc-hash", @@ -6400,9 +6405,9 @@ dependencies = [ [[package]] name = "swc_ecma_transforms_react" -version = "38.0.0" +version = "39.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "652b77238937631359f964e53d53ca2b92f9fa29c6a28c9d3b054c44e18a17b9" +checksum = "e21590a3c184b98ea3bae1717e58e02c64597c087429a635c6301f41f09ceaaf" dependencies = [ "base64", "bytes-str", @@ -6416,6 +6421,7 @@ dependencies = [ "swc_common", "swc_config", "swc_ecma_ast", + "swc_ecma_hooks", "swc_ecma_parser", "swc_ecma_transforms_base", "swc_ecma_utils", @@ -6424,9 +6430,9 @@ dependencies = [ [[package]] name = "swc_ecma_transforms_typescript" -version = "38.0.0" +version = "39.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c32bbafb42b8f0f2013e94a4b4981d643a645b1a7f9c20931cbca5bf78c1538" +checksum = "8ce02fbf3b0bd4f69eb1d020973d9a6e7c4bb062d464fade653f6bc8a075f592" dependencies = [ "bytes-str", "rustc-hash", @@ -6442,9 +6448,9 @@ dependencies = [ [[package]] name = "swc_ecma_usage_analyzer" -version = "27.0.0" +version = "28.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e5215c48b139422dcf54958d746b5e9a7b31bab8fc126f28e4049c4985505d5" +checksum = "b7aec80849cab609d92af5dd2670f18fc760f7029beb11beebcef3fed9ba3466" dependencies = [ "bitflags 2.9.1", "indexmap", @@ -6460,16 +6466,16 @@ dependencies = [ [[package]] name = "swc_ecma_utils" -version = "25.0.0" +version = "26.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dd5ee449d21110a271e73d0a9f7640a8854a62cb0e2cb0c9db3445383598e21" +checksum = "58e74834be7fece99481e2f59b91b0c90ae790582ef3190b79e5ec050f4550e4" dependencies = [ + "dragonbox_ecma", "indexmap", "num_cpus", "once_cell", "par-core", "rustc-hash", - "ryu-js", "swc_atoms", "swc_common", "swc_ecma_ast", @@ -6479,9 +6485,9 @@ dependencies = [ [[package]] name = "swc_ecma_visit" -version = "19.0.0" +version = "20.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a69d63f7f704a2ec937edef90a3eba1f64602eceb60c8deb260c01131f680e8b" +checksum = "e971a258717db3dc8939c38410d8b8cb8126f1b05b9758672daa7cae3e0248c2" dependencies = [ "new_debug_unreachable", "num-bigint", @@ -6518,9 +6524,9 @@ dependencies = [ [[package]] name = "swc_experimental_ast_macros" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b45db26cc495a8695f8034277ceb6a44e52eb702d6c64ea5c7156dd673ea8c98" +checksum = "4ea34d308ac6d6275f8db1b17ad97f418252881e5571aebb00b25bdd76b1a61a" dependencies = [ "proc-macro2", "quote", @@ -6529,9 +6535,9 @@ dependencies = [ [[package]] name = "swc_experimental_ecma_ast" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23564af8c9c028bebb6a0d40ec6ac81c1167c4b6dfcc3268db96d07b11d82576" +checksum = "20d6b8909beb446633ca6b01cf713d07d899a0b36c611f42e295011305a90372" dependencies = [ "num-bigint", "oxc_index", @@ -6542,9 +6548,9 @@ dependencies = [ [[package]] name = "swc_experimental_ecma_parser" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb177bdc3f39cc4d69c3b41b5c5e40c10f48a77ac3d9b9c11d282b2d36afa7c5" +checksum = "1a56639b88f4a05370335f4df2d9148de794d8469d380722d1364d16adbcbf20" dependencies = [ "bitflags 2.9.1", "either", @@ -6559,9 +6565,9 @@ dependencies = [ [[package]] name = "swc_experimental_ecma_semantic" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cec03726324631cc59fb5e89f26a9e005c99825d0a96217ed6430a29f49099d" +checksum = "2ab0f625c6b01151edbf67cb5a07cece1280cb19610d547c9de13ed58a6d709e" dependencies = [ "bitflags 2.9.1", "oxc_index", @@ -6573,9 +6579,9 @@ dependencies = [ [[package]] name = "swc_experimental_ecma_visit" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0893ca54f257f32286b5a8a8d58cf3a25126897e9ab2549f4327c1381023eea" +checksum = "dcd5577d8b36074bf0f5ecf1bceaa9f2cd7449c7b1b2f8ef7a0ca6b0e5fd5230" dependencies = [ "swc_experimental_ecma_ast", ] @@ -6632,9 +6638,9 @@ dependencies = [ [[package]] name = "swc_html_minifier" -version = "42.0.0" +version = "43.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5c9393dfb081b8658b030d2b52f5afe10c529773f574e6fc51b2fe0446c4d87" +checksum = "982adda9ac4530c6bdbaa52dd821571339b8b0876d78227f4a0b48ca84a90b41" dependencies = [ "once_cell", "rustc-hash", @@ -6720,9 +6726,9 @@ dependencies = [ [[package]] name = "swc_plugin_proxy" -version = "19.0.0" +version = "20.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f976dc63cd8b1916f265ee7d2647c28a85b433640099a5bf07153346dedffda" +checksum = "e78e1a9d26be495289cb07b9d73222f92f60b74d47904169d3ce4977600ec11e" dependencies = [ "better_scoped_tls", "cbor4ii", @@ -6735,9 +6741,9 @@ dependencies = [ [[package]] name = "swc_plugin_runner" -version = "23.0.0" +version = "24.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea88e7208565cc3d9c23fdd0ab4cf3896fb857f27ebb6d100805556fd0e46b10" +checksum = "9a48f119fba50bb6bbf54366fc37a7e0c4d94a641936a082330cc6ab8e3f947d" dependencies = [ "anyhow", "blake3", diff --git a/Cargo.toml b/Cargo.toml index 7e3e51fc3ed4..7aaefd4f69cd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -136,19 +136,19 @@ rkyv = { version = "=0.8.8", default-features = false, features = ["std", " # Must be pinned with the same swc versions pnp = { version = "0.12.7", default-features = false } -swc = { version = "52.0.0", default-features = false } +swc = { version = "53.0.0", default-features = false } swc_config = { version = "3.1.2", default-features = false } -swc_core = { version = "54.0.0", default-features = false, features = ["parallel_rayon"] } -swc_ecma_minifier = { version = "42.0.0", default-features = false } +swc_core = { version = "55.0.0", default-features = false, features = ["parallel_rayon"] } +swc_ecma_minifier = { version = "43.0.0", default-features = false } swc_error_reporters = { version = "20.0.0", default-features = false } swc_html = { version = "30.0.0", default-features = false } -swc_html_minifier = { version = "42.0.0", default-features = false } +swc_html_minifier = { version = "43.0.0", default-features = false } swc_node_comments = { version = "18.0.0", default-features = false } -swc_plugin_runner = { version = "23.0.0", default-features = false } +swc_plugin_runner = { version = "24.0.0", default-features = false } -swc_experimental_ecma_ast = { version = "0.4.0", default-features = false } -swc_experimental_ecma_parser = { version = "0.4.0", default-features = false } -swc_experimental_ecma_semantic = { version = "0.4.0", default-features = false } +swc_experimental_ecma_ast = { version = "0.4.1", default-features = false } +swc_experimental_ecma_parser = { version = "0.4.1", default-features = false } +swc_experimental_ecma_semantic = { version = "0.4.1", default-features = false } rspack_dojang = { version = "0.1.11", default-features = false } tracy-client = { version = "=0.18.4", default-features = false, features = [ diff --git a/crates/rspack_workspace/src/generated.rs b/crates/rspack_workspace/src/generated.rs index d7a2d70611df..4c33836d0089 100644 --- a/crates/rspack_workspace/src/generated.rs +++ b/crates/rspack_workspace/src/generated.rs @@ -1,7 +1,7 @@ //! This is a generated file. Don't modify it by hand! Run 'cargo codegen' to re-generate the file. /// The version of the `swc_core` package used in the current workspace. pub const fn rspack_swc_core_version() -> &'static str { - "54.0.0" + "55.0.0" } /// The version of the JavaScript `@rspack/core` package. From 8c8a40257111d6fd6069c914dd443f431cacbd23 Mon Sep 17 00:00:00 2001 From: hardfist Date: Fri, 16 Jan 2026 16:11:29 +0800 Subject: [PATCH 68/87] refactor: move all artifacts together (#12755) --- .../build_chunk_graph_artifact.rs} | 0 .../build_module_graph_artifact.rs} | 0 crates/rspack_core/src/artifacts/mod.rs | 5 +++++ .../src/compilation/build_chunk_graph/mod.rs | 1 - .../src/compilation/build_chunk_graph/pass.rs | 6 +----- .../src/compilation/build_module_graph/mod.rs | 3 +-- crates/rspack_core/src/compilation/mod.rs | 19 +++++++++---------- 7 files changed, 16 insertions(+), 18 deletions(-) rename crates/rspack_core/src/{compilation/build_chunk_graph/artifact.rs => artifacts/build_chunk_graph_artifact.rs} (100%) rename crates/rspack_core/src/{compilation/build_module_graph/artifact.rs => artifacts/build_module_graph_artifact.rs} (100%) diff --git a/crates/rspack_core/src/compilation/build_chunk_graph/artifact.rs b/crates/rspack_core/src/artifacts/build_chunk_graph_artifact.rs similarity index 100% rename from crates/rspack_core/src/compilation/build_chunk_graph/artifact.rs rename to crates/rspack_core/src/artifacts/build_chunk_graph_artifact.rs diff --git a/crates/rspack_core/src/compilation/build_module_graph/artifact.rs b/crates/rspack_core/src/artifacts/build_module_graph_artifact.rs similarity index 100% rename from crates/rspack_core/src/compilation/build_module_graph/artifact.rs rename to crates/rspack_core/src/artifacts/build_module_graph_artifact.rs diff --git a/crates/rspack_core/src/artifacts/mod.rs b/crates/rspack_core/src/artifacts/mod.rs index 211fef3e38c6..da73ee8bdd0a 100644 --- a/crates/rspack_core/src/artifacts/mod.rs +++ b/crates/rspack_core/src/artifacts/mod.rs @@ -1,4 +1,6 @@ mod async_modules_artifact; +mod build_chunk_graph_artifact; +mod build_module_graph_artifact; mod cgc_runtime_requirements_artifact; mod cgm_hash_artifact; mod cgm_runtime_requirement_artifact; @@ -15,6 +17,9 @@ mod module_static_cache_artifact; mod side_effects_do_optimize_artifact; pub use async_modules_artifact::AsyncModulesArtifact; +pub(crate) use build_chunk_graph_artifact::use_code_splitting_cache; +pub use build_chunk_graph_artifact::*; +pub use build_module_graph_artifact::*; pub use cgc_runtime_requirements_artifact::CgcRuntimeRequirementsArtifact; pub use cgm_hash_artifact::*; pub use cgm_runtime_requirement_artifact::*; diff --git a/crates/rspack_core/src/compilation/build_chunk_graph/mod.rs b/crates/rspack_core/src/compilation/build_chunk_graph/mod.rs index e64652e1f4e7..d79742e8793f 100644 --- a/crates/rspack_core/src/compilation/build_chunk_graph/mod.rs +++ b/crates/rspack_core/src/compilation/build_chunk_graph/mod.rs @@ -4,7 +4,6 @@ use tracing::instrument; use crate::{Compilation, incremental::IncrementalPasses}; -pub(crate) mod artifact; pub(crate) mod code_splitter; pub(crate) mod incremental; pub(crate) mod pass; diff --git a/crates/rspack_core/src/compilation/build_chunk_graph/pass.rs b/crates/rspack_core/src/compilation/build_chunk_graph/pass.rs index f6a5380e1368..1c99b4ca5f6a 100644 --- a/crates/rspack_core/src/compilation/build_chunk_graph/pass.rs +++ b/crates/rspack_core/src/compilation/build_chunk_graph/pass.rs @@ -1,11 +1,7 @@ use rspack_error::Result; use crate::{ - compilation::{ - Compilation, - build_chunk_graph::{artifact::use_code_splitting_cache, build_chunk_graph}, - }, - logger::Logger, + Compilation, build_chunk_graph::build_chunk_graph, logger::Logger, use_code_splitting_cache, }; pub async fn build_chunk_graph_pass(compilation: &mut Compilation) -> Result<()> { diff --git a/crates/rspack_core/src/compilation/build_module_graph/mod.rs b/crates/rspack_core/src/compilation/build_module_graph/mod.rs index 9afcfecd0800..21f245bdb9af 100644 --- a/crates/rspack_core/src/compilation/build_module_graph/mod.rs +++ b/crates/rspack_core/src/compilation/build_module_graph/mod.rs @@ -1,4 +1,3 @@ -mod artifact; mod graph_updater; mod lazy_barrel_artifact; mod module_executor; @@ -10,13 +9,13 @@ use rspack_util::tracing_preset::TRACING_BENCH_TARGET; use tracing::instrument; pub use self::{ - artifact::{BuildModuleGraphArtifact, BuildModuleGraphArtifactState}, graph_updater::{UpdateParam, update_module_graph}, lazy_barrel_artifact::{ ForwardId, ForwardedIdSet, HasLazyDependencies, LazyDependencies, LazyUntil, ModuleToLazyMake, }, module_executor::{ExecuteModuleId, ExecutedRuntimeModule, ModuleExecutor}, }; +pub use crate::{BuildModuleGraphArtifact, BuildModuleGraphArtifactState}; use crate::{Compilation, logger::Logger}; pub async fn build_module_graph_pass(compilation: &mut Compilation) -> Result<()> { diff --git a/crates/rspack_core/src/compilation/mod.rs b/crates/rspack_core/src/compilation/mod.rs index 18be47aa53b3..d30ba2de0f44 100644 --- a/crates/rspack_core/src/compilation/mod.rs +++ b/crates/rspack_core/src/compilation/mod.rs @@ -62,21 +62,20 @@ use tracing::instrument; use ustr::Ustr; use crate::{ - AsyncModulesArtifact, BindingCell, BoxDependency, BoxModule, CacheCount, CacheOptions, - CgcRuntimeRequirementsArtifact, CgmHashArtifact, CgmRuntimeRequirementsArtifact, Chunk, - ChunkByUkey, ChunkContentHash, ChunkGraph, ChunkGroupByUkey, ChunkGroupUkey, ChunkHashesArtifact, - ChunkKind, ChunkNamedIdArtifact, ChunkRenderArtifact, ChunkRenderCacheArtifact, - ChunkRenderResult, ChunkUkey, CodeGenerationJob, CodeGenerationResult, CodeGenerationResults, - CompilationLogger, CompilationLogging, CompilerOptions, CompilerPlatform, ConcatenationScope, - DependenciesDiagnosticsArtifact, DependencyCodeGeneration, DependencyTemplate, - DependencyTemplateType, DependencyType, DerefOption, Entry, EntryData, EntryOptions, - EntryRuntime, Entrypoint, ExecuteModuleId, Filename, ImportPhase, ImportVarMap, + AsyncModulesArtifact, BindingCell, BoxDependency, BoxModule, BuildChunkGraphArtifact, CacheCount, + CacheOptions, CgcRuntimeRequirementsArtifact, CgmHashArtifact, CgmRuntimeRequirementsArtifact, + Chunk, ChunkByUkey, ChunkContentHash, ChunkGraph, ChunkGroupByUkey, ChunkGroupUkey, + ChunkHashesArtifact, ChunkKind, ChunkNamedIdArtifact, ChunkRenderArtifact, + ChunkRenderCacheArtifact, ChunkRenderResult, ChunkUkey, CodeGenerationJob, CodeGenerationResult, + CodeGenerationResults, CompilationLogger, CompilationLogging, CompilerOptions, CompilerPlatform, + ConcatenationScope, DependenciesDiagnosticsArtifact, DependencyCodeGeneration, + DependencyTemplate, DependencyTemplateType, DependencyType, DerefOption, Entry, EntryData, + EntryOptions, EntryRuntime, Entrypoint, ExecuteModuleId, Filename, ImportPhase, ImportVarMap, ImportedByDeferModulesArtifact, MemoryGCStorage, ModuleFactory, ModuleGraph, ModuleGraphCacheArtifact, ModuleIdentifier, ModuleIdsArtifact, ModuleStaticCacheArtifact, PathData, ResolverFactory, RuntimeGlobals, RuntimeKeyMap, RuntimeMode, RuntimeModule, RuntimeSpec, RuntimeSpecMap, RuntimeTemplate, SharedPluginDriver, SideEffectsOptimizeArtifact, SourceType, Stats, ValueCacheVersions, - build_chunk_graph::artifact::BuildChunkGraphArtifact, compilation::build_module_graph::{ BuildModuleGraphArtifact, ModuleExecutor, UpdateParam, update_module_graph, }, From fe1e14c1d5cbc751241ca48483abe4c9c3c9f081 Mon Sep 17 00:00:00 2001 From: CPunisher <1343316114@qq.com> Date: Fri, 16 Jan 2026 17:03:17 +0800 Subject: [PATCH 69/87] chore: limit threads for codspeed benchmark (#12763) Limit threads --- .github/actions/codspeed/action.yaml | 102 --------------------- .github/workflows/reusable-build-bench.yml | 5 +- xtask/benchmark/benches/groups/bundle.rs | 3 +- 3 files changed, 6 insertions(+), 104 deletions(-) delete mode 100644 .github/actions/codspeed/action.yaml diff --git a/.github/actions/codspeed/action.yaml b/.github/actions/codspeed/action.yaml deleted file mode 100644 index ee667c8a06ff..000000000000 --- a/.github/actions/codspeed/action.yaml +++ /dev/null @@ -1,102 +0,0 @@ -name: 'CodSpeed Performance Analysis' -description: 'Continuous benchmarking and performance checks' -branding: - color: orange - icon: activity - -author: 'Arthur Pastel' -inputs: - token: - description: 'CodSpeed upload token' - required: false - run: - description: 'The command to run the benchmarks' - required: true - - working-directory: - description: | - The directory where the `run` command will be executed. - Warning: if you use defaults.working-directory, you must still set this parameter. - required: false - upload-url: - description: 'The upload endpoint (for on-premise deployments)' - required: false - - runner-version: - description: 'The version of the runner to use' - required: false - - mode: - description: | - The mode to to run the benchmarks in. The following modes are available: - - `instrumentation` (default): Run the benchmarks with instrumentation enabled. - - `walltime`: Run the benchmarks with walltime enabled. - - We strongly recommend not changing this mode unless you know what you are doing. - - Using the `walltime` mode on traditional VMs/Hosted Runners will lead to inconsistent data. For the best results, we recommend using CodSpeed Hosted Macro Runners, which are fine-tuned for performance measurement consistency. - Check out the [Walltime Instrument Documentation](https://docs.codspeed.io/instruments/walltime/) for more details. - required: false - - instruments: - description: | - Comma separated list of instruments to enable. The following instruments are available: - - `mongodb`: MongoDB instrumentation, requires the MongoDB instrument to be enabled for the organization in CodSpeed - required: false - mongo-uri-env-name: - description: | - The name of the environment variable containing the MongoDB URI. Requires the `mongodb` instrument to be activated in `instruments`. - If the instrumentation is enabled and this value is not set, the user will need to dynamically provide the MongoDB URI to the CodSpeed runner. - required: false - -runs: - using: 'composite' - steps: - - shell: bash - env: - GH_MATRIX: '${{ toJson(matrix) }}' - GH_STRATEGY: '${{ toJson(strategy) }}' - run: | - # Configure and run codspeed-runner - # if [ -n "${{ inputs.runner-version }}" ]; then - # RUNNER_VERSION="${{ inputs.runner-version }}" - # else - # RUNNER_VERSION=$(cat $GITHUB_ACTION_PATH/.codspeed-runner-version) - # fi - - # Get the runner arguments - RUNNER_ARGS="" - if [ -n "${{ inputs.token }}" ]; then - RUNNER_ARGS="$RUNNER_ARGS --token ${{ inputs.token }}" - fi - if [ -n "${{ inputs.working-directory }}" ]; then - RUNNER_ARGS="$RUNNER_ARGS --working-directory=${{ inputs.working-directory }}" - fi - if [ -n "${{ inputs.upload-url }}" ]; then - RUNNER_ARGS="$RUNNER_ARGS --upload-url=${{ inputs.upload-url }}" - fi - if [ -n "${{ inputs.mode }}" ]; then - RUNNER_ARGS="$RUNNER_ARGS --mode=${{ inputs.mode }}" - fi - if [ -n "${{ inputs.instruments }}" ]; then - RUNNER_ARGS="$RUNNER_ARGS --instruments=${{ inputs.instruments }}" - fi - if [ -n "${{ inputs.mongo-uri-env-name }}" ]; then - RUNNER_ARGS="$RUNNER_ARGS --mongo-uri-env-name=${{ inputs.mongo-uri-env-name }}" - fi - - # Install the CodSpeedHQ/runner - # head_status=$(curl -I -fsSL -w "%{http_code}" -o /dev/null https://github.com/CodSpeedHQ/runner/releases/download/v$RUNNER_VERSION/codspeed-runner-installer.sh) - # if [ "$head_status" -eq 404 ]; then - # echo "Error: Version $RUNNER_VERSION is not available in https://github.com/CodSpeedHQ/runner/releases, please a correct version." - # exit 1 - # else - # curl -fsSL https://github.com/CodSpeedHQ/runner/releases/download/v$RUNNER_VERSION/codspeed-runner-installer.sh | bash -s -- --quiet - # fi - - # We can use official official runner if it supports config valgrind flags in the future: https://github.com/CodSpeedHQ/runner/pull/92 - cargo install --git https://github.com/CPunisher/runner.git --rev 7e87e3c5d93390fb28e4fbd5f3859f3b20d8fc6a - - # Run the benchmarks - # Enable fair sched to make benchmark more stable, see: https://github.com/CodSpeedHQ/runner/pull/91 - env VALGRIND_FLAGS='--fair-sched=yes' codspeed run $RUNNER_ARGS -- '${{ inputs.run }}' diff --git a/.github/workflows/reusable-build-bench.yml b/.github/workflows/reusable-build-bench.yml index 0fc566686e80..ab82b54560db 100644 --- a/.github/workflows/reusable-build-bench.yml +++ b/.github/workflows/reusable-build-bench.yml @@ -77,8 +77,11 @@ jobs: run: pnpm run build:js - name: Run benchmark - uses: ./.github/actions/codspeed + uses: CodSpeedHQ/action@0700edb451d0e9f2426f99bd6977027e550fb2a6 # https://github.com/CodSpeedHQ/action/releases/tag/v4.7.0 timeout-minutes: 30 + env: + RAYON_NUM_THREADS: 1 with: + mode: 'simulation' run: pnpm run bench:ci token: ${{ secrets.CODSPEED_TOKEN }} diff --git a/xtask/benchmark/benches/groups/bundle.rs b/xtask/benchmark/benches/groups/bundle.rs index 56ad7a5c5f09..37f9a00229db 100644 --- a/xtask/benchmark/benches/groups/bundle.rs +++ b/xtask/benchmark/benches/groups/bundle.rs @@ -22,7 +22,8 @@ fn bundle_benchmark(c: &mut Criterion) { // Codspeed can only handle to up to 500 threads by default let rt = runtime::Builder::new_multi_thread() - .max_blocking_threads(256) + .worker_threads(8) + .max_blocking_threads(8) .build() .unwrap(); From cfa49be439ed238617abc3ce3046ed401b2a2d58 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 18 Jan 2026 00:46:26 +0000 Subject: [PATCH 70/87] chore(deps): update dependency cspell to ^9.6.0 (#12768) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- pnpm-lock.yaml | 438 +++++++++++++++++++++---------------------- website/package.json | 2 +- 2 files changed, 220 insertions(+), 220 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d896764380cd..7a9f5cdb1990 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -992,8 +992,8 @@ importers: specifier: ~2.1.1 version: 2.1.1 cspell: - specifier: ^9.4.0 - version: 9.4.0 + specifier: ^9.6.0 + version: 9.6.0 cspell-ban-words: specifier: 0.0.4 version: 0.0.4 @@ -1565,28 +1565,28 @@ packages: vite: ^4.2.0 || ^5.0.0 || ^6.0.0 vitest: '>=1.2.2' - '@cspell/cspell-bundled-dicts@9.4.0': - resolution: {integrity: sha512-Hm2gpMg/lRv4fKtiO2NfBiaJdFZVVb1V1a+IVhlD9qCuObLhCt60Oze2kD1dQzhbaIX756cs/eyxa5bQ5jihhQ==} + '@cspell/cspell-bundled-dicts@9.6.0': + resolution: {integrity: sha512-gLNe9bB+5gMsTEhR9YPE0Wt122HR2EV+Q1j9W+MbwbeBJmpTWrgAP1ZdpvHOg+6LF6x/bD/EC9HfWdd/om8wXA==} engines: {node: '>=20'} - '@cspell/cspell-json-reporter@9.4.0': - resolution: {integrity: sha512-TpHY7t13xNhcZF9bwOfgVIhcyPDamMnxU/TBYhf4mPtXPLrZ5gBTg3UZh0/9Zn3naMjmJtngdsLvB2wai9xBlQ==} + '@cspell/cspell-json-reporter@9.6.0': + resolution: {integrity: sha512-5sY1lgAXS5xEOsjT5rREMADj7pHIt56XOL7xR80nNl0TwlpZbeBHhoB2aH5sirVTeodJFN5iraXNbVOYPPupPw==} engines: {node: '>=20'} - '@cspell/cspell-pipe@9.4.0': - resolution: {integrity: sha512-cI0sUe7SB99hJB1T6PhH/MpSrnml1kOekTCE+VH3Eb7zkVP5/mwJXs8BlufdvwBona+Cgkx6jeWlhFpxLc39Yg==} + '@cspell/cspell-pipe@9.6.0': + resolution: {integrity: sha512-YNuY8NNXfE+8Qzknm2ps6QbrZLZu6rSZTZr3dYW3K6TK7+IFVlJ6e2Z9iKJTqp6aZ4AGU/r9QYGmNX4Oq4gZ0A==} engines: {node: '>=20'} - '@cspell/cspell-resolver@9.4.0': - resolution: {integrity: sha512-o9gbbdXlhxG2rqtGqQ7xZ8MGDDsPLbskBnTeuA++ix4Ch/HdjrBNmKReIGAEqJPfP+JGgoEKqFISHUDKAJ/ygQ==} + '@cspell/cspell-resolver@9.6.0': + resolution: {integrity: sha512-Gb2UWNmRpTOQGpYL4Q/LMw+b50KcRZcf/wJg6w0Yl3IT+F/uDNhNh1f5rHuTyGsbMsMxHJhsb2AoP+73GlbIfw==} engines: {node: '>=20'} - '@cspell/cspell-service-bus@9.4.0': - resolution: {integrity: sha512-UottRlFPN6FGUfojx5HtUPZTeYXg2rf2HvO/HLh0KicirVYO16vFxTevg9MyOvw1EXSsDRz8ECANjiE7fnzBCQ==} + '@cspell/cspell-service-bus@9.6.0': + resolution: {integrity: sha512-DCuKKkySTEB8MPLTdoPMdmakYcx7XCsHz1YEMbzOcLqJCxXsRlRZg4qE9kRBee/2QY7eYA2kaYNgn/TDMooa4g==} engines: {node: '>=20'} - '@cspell/cspell-types@9.4.0': - resolution: {integrity: sha512-vSpd50OfmthBH0aRFRLA2zJFtwli3ntHA0WAOJ8tIMLUCJgF3udooRXFeX3wR8ri69C9mc3864LC4inyRC/E9w==} + '@cspell/cspell-types@9.6.0': + resolution: {integrity: sha512-JTqrD47tV+rWc1y2W8T0NTfWLQMlSWX4OF64/Jf3WbsOD+4UXVIfjRlzPry7+1Zekm6pa38+23jkDBytYpu8yw==} engines: {node: '>=20'} '@cspell/dict-ada@4.1.1': @@ -1595,56 +1595,56 @@ packages: '@cspell/dict-al@1.1.1': resolution: {integrity: sha512-sD8GCaZetgQL4+MaJLXqbzWcRjfKVp8x+px3HuCaaiATAAtvjwUQ5/Iubiqwfd1boIh2Y1/3EgM3TLQ7Q8e0wQ==} - '@cspell/dict-aws@4.0.16': - resolution: {integrity: sha512-a681zShZbtTo947NvTYGLer95ZDQw1ROKvIFydak1e0OlfFCsNdtcYTupn0nbbYs53c9AO7G2DU8AcNEAnwXPA==} + '@cspell/dict-aws@4.0.17': + resolution: {integrity: sha512-ORcblTWcdlGjIbWrgKF+8CNEBQiLVKdUOFoTn0KPNkAYnFcdPP0muT4892h7H4Xafh3j72wqB4/loQ6Nti9E/w==} '@cspell/dict-bash@4.2.2': resolution: {integrity: sha512-kyWbwtX3TsCf5l49gGQIZkRLaB/P8g73GDRm41Zu8Mv51kjl2H7Au0TsEvHv7jzcsRLS6aUYaZv6Zsvk1fOz+Q==} - '@cspell/dict-companies@3.2.7': - resolution: {integrity: sha512-fEyr3LmpFKTaD0LcRhB4lfW1AmULYBqzg4gWAV0dQCv06l+TsA+JQ+3pZJbUcoaZirtgsgT3dL3RUjmGPhUH0A==} + '@cspell/dict-companies@3.2.10': + resolution: {integrity: sha512-bJ1qnO1DkTn7JYGXvxp8FRQc4yq6tRXnrII+jbP8hHmq5TX5o1Wu+rdfpoUQaMWTl6balRvcMYiINDesnpR9Bw==} - '@cspell/dict-cpp@6.0.15': - resolution: {integrity: sha512-N7MKK3llRNoBncygvrnLaGvmjo4xzVr5FbtAc9+MFGHK6/LeSySBupr1FM72XDaVSIsmBEe7sDYCHHwlI9Jb2w==} + '@cspell/dict-cpp@7.0.2': + resolution: {integrity: sha512-dfbeERiVNeqmo/npivdR6rDiBCqZi3QtjH2Z0HFcXwpdj6i97dX1xaKyK2GUsO/p4u1TOv63Dmj5Vm48haDpuA==} '@cspell/dict-cryptocurrencies@5.0.5': resolution: {integrity: sha512-R68hYYF/rtlE6T/dsObStzN5QZw+0aQBinAXuWCVqwdS7YZo0X33vGMfChkHaiCo3Z2+bkegqHlqxZF4TD3rUA==} - '@cspell/dict-csharp@4.0.7': - resolution: {integrity: sha512-H16Hpu8O/1/lgijFt2lOk4/nnldFtQ4t8QHbyqphqZZVE5aS4J/zD/WvduqnLY21aKhZS6jo/xF5PX9jyqPKUA==} + '@cspell/dict-csharp@4.0.8': + resolution: {integrity: sha512-qmk45pKFHSxckl5mSlbHxmDitSsGMlk/XzFgt7emeTJWLNSTUK//MbYAkBNRtfzB4uD7pAFiKgpKgtJrTMRnrQ==} - '@cspell/dict-css@4.0.18': - resolution: {integrity: sha512-EF77RqROHL+4LhMGW5NTeKqfUd/e4OOv6EDFQ/UQQiFyWuqkEKyEz0NDILxOFxWUEVdjT2GQ2cC7t12B6pESwg==} + '@cspell/dict-css@4.0.19': + resolution: {integrity: sha512-VYHtPnZt/Zd/ATbW3rtexWpBnHUohUrQOHff/2JBhsVgxOrksAxJnLAO43Q1ayLJBJUUwNVo+RU0sx0aaysZfg==} - '@cspell/dict-dart@2.3.1': - resolution: {integrity: sha512-xoiGnULEcWdodXI6EwVyqpZmpOoh8RA2Xk9BNdR7DLamV/QMvEYn8KJ7NlRiTSauJKPNkHHQ5EVHRM6sTS7jdg==} + '@cspell/dict-dart@2.3.2': + resolution: {integrity: sha512-sUiLW56t9gfZcu8iR/5EUg+KYyRD83Cjl3yjDEA2ApVuJvK1HhX+vn4e4k4YfjpUQMag8XO2AaRhARE09+/rqw==} '@cspell/dict-data-science@2.0.13': resolution: {integrity: sha512-l1HMEhBJkPmw4I2YGVu2eBSKM89K9pVF+N6qIr5Uo5H3O979jVodtuwP8I7LyPrJnC6nz28oxeGRCLh9xC5CVA==} - '@cspell/dict-django@4.1.5': - resolution: {integrity: sha512-AvTWu99doU3T8ifoMYOMLW2CXKvyKLukPh1auOPwFGHzueWYvBBN+OxF8wF7XwjTBMMeRleVdLh3aWCDEX/ZWg==} + '@cspell/dict-django@4.1.6': + resolution: {integrity: sha512-SdbSFDGy9ulETqNz15oWv2+kpWLlk8DJYd573xhIkeRdcXOjskRuxjSZPKfW7O3NxN/KEf3gm3IevVOiNuFS+w==} - '@cspell/dict-docker@1.1.16': - resolution: {integrity: sha512-UiVQ5RmCg6j0qGIxrBnai3pIB+aYKL3zaJGvXk1O/ertTKJif9RZikKXCEgqhaCYMweM4fuLqWSVmw3hU164Iw==} + '@cspell/dict-docker@1.1.17': + resolution: {integrity: sha512-OcnVTIpHIYYKhztNTyK8ShAnXTfnqs43hVH6p0py0wlcwRIXe5uj4f12n7zPf2CeBI7JAlPjEsV0Rlf4hbz/xQ==} - '@cspell/dict-dotnet@5.0.10': - resolution: {integrity: sha512-ooar8BP/RBNP1gzYfJPStKEmpWy4uv/7JCq6FOnJLeD1yyfG3d/LFMVMwiJo+XWz025cxtkM3wuaikBWzCqkmg==} + '@cspell/dict-dotnet@5.0.11': + resolution: {integrity: sha512-LSVKhpFf/ASTWJcfYeS0Sykcl1gVMsv2Z5Eo0TnTMSTLV3738HH+66pIsjUTChqU6SF3gKPuCe6EOaRYqb/evA==} '@cspell/dict-elixir@4.0.8': resolution: {integrity: sha512-CyfphrbMyl4Ms55Vzuj+mNmd693HjBFr9hvU+B2YbFEZprE5AG+EXLYTMRWrXbpds4AuZcvN3deM2XVB80BN/Q==} - '@cspell/dict-en-common-misspellings@2.1.8': - resolution: {integrity: sha512-vDsjRFPQGuAADAiitf82z9Mz3DcqKZi6V5hPAEIFkLLKjFVBcjUsSq59SfL59ElIFb76MtBO0BLifdEbBj+DoQ==} + '@cspell/dict-en-common-misspellings@2.1.11': + resolution: {integrity: sha512-2jcY494If1udvzd7MT2z/QH/RACUo/I02vIY4ttNdZhgYvUmRKhg8OBdrbzYo0lJOcc7XUb8rhIFQRHzxOSVeA==} - '@cspell/dict-en-gb-mit@3.1.14': - resolution: {integrity: sha512-b+vEerlHP6rnNf30tmTJb7JZnOq4WAslYUvexOz/L3gDna9YJN3bAnwRJ3At3bdcOcMG7PTv3Pi+C73IR22lNg==} + '@cspell/dict-en-gb-mit@3.1.16': + resolution: {integrity: sha512-4PPdapCJslytxAVJu35Mv97qDyGmAQxtDE790T2bWNhcqN6gvRVAc/eTRaXkUIf21q1xCxxNNqpH4VfMup69rQ==} - '@cspell/dict-en_us@4.4.24': - resolution: {integrity: sha512-JE+/H2YicHJTneRmgH4GSI21rS+1yGZVl1jfOQgl8iHLC+yTTMtCvueNDMK94CgJACzYAoCsQB70MqiFJJfjLQ==} + '@cspell/dict-en_us@4.4.27': + resolution: {integrity: sha512-0y4vH2i5cFmi8sxkc4OlD2IlnqDznOtKczm4h6jA288g5VVrm3bhkYK6vcB8b0CoRKtYWKet4VEmHBP1yI+Qfw==} - '@cspell/dict-filetypes@3.0.14': - resolution: {integrity: sha512-KSXaSMYYNMLLdHEnju1DyRRH3eQWPRYRnOXpuHUdOh2jC44VgQoxyMU7oB3NAhDhZKBPCihabzECsAGFbdKfEA==} + '@cspell/dict-filetypes@3.0.15': + resolution: {integrity: sha512-uDMeqYlLlK476w/muEFQGBy9BdQWS0mQ7BJiy/iQv5XUWZxE2O54ZQd9nW8GyQMzAgoyg5SG4hf9l039Qt66oA==} '@cspell/dict-flutter@1.1.1': resolution: {integrity: sha512-UlOzRcH2tNbFhZmHJN48Za/2/MEdRHl2BMkCWZBYs+30b91mWvBfzaN4IJQU7dUZtowKayVIF9FzvLZtZokc5A==} @@ -1664,8 +1664,8 @@ packages: '@cspell/dict-git@3.0.7': resolution: {integrity: sha512-odOwVKgfxCQfiSb+nblQZc4ErXmnWEnv8XwkaI4sNJ7cNmojnvogYVeMqkXPjvfrgEcizEEA4URRD2Ms5PDk1w==} - '@cspell/dict-golang@6.0.24': - resolution: {integrity: sha512-rY7PlC3MsHozmjrZWi0HQPUl0BVCV0+mwK0rnMT7pOIXqOe4tWCYMULDIsEk4F0gbIxb5badd2dkCPDYjLnDgA==} + '@cspell/dict-golang@6.0.26': + resolution: {integrity: sha512-YKA7Xm5KeOd14v5SQ4ll6afe9VSy3a2DWM7L9uBq4u3lXToRBQ1W5PRa+/Q9udd+DTURyVVnQ+7b9cnOlNxaRg==} '@cspell/dict-google@1.0.9': resolution: {integrity: sha512-biL65POqialY0i4g6crj7pR6JnBkbsPovB2WDYkj3H4TuC/QXv7Pu5pdPxeUJA6TSCHI7T5twsO4VSVyRxD9CA==} @@ -1673,11 +1673,11 @@ packages: '@cspell/dict-haskell@4.0.6': resolution: {integrity: sha512-ib8SA5qgftExpYNjWhpYIgvDsZ/0wvKKxSP+kuSkkak520iPvTJumEpIE+qPcmJQo4NzdKMN8nEfaeci4OcFAQ==} - '@cspell/dict-html-symbol-entities@4.0.4': - resolution: {integrity: sha512-afea+0rGPDeOV9gdO06UW183Qg6wRhWVkgCFwiO3bDupAoyXRuvupbb5nUyqSTsLXIKL8u8uXQlJ9pkz07oVXw==} + '@cspell/dict-html-symbol-entities@4.0.5': + resolution: {integrity: sha512-429alTD4cE0FIwpMucvSN35Ld87HCyuM8mF731KU5Rm4Je2SG6hmVx7nkBsLyrmH3sQukTcr1GaiZsiEg8svPA==} - '@cspell/dict-html@4.0.13': - resolution: {integrity: sha512-vHzk2xfqQYPvoXtQtywa6ekIonPrUEwe2uftjry3UNRNl89TtzLJVSkiymKJ3WMb+W/DwKXKIb1tKzcIS8ccIg==} + '@cspell/dict-html@4.0.14': + resolution: {integrity: sha512-2bf7n+kS92g+cMKV0wr9o/Oq9n8JzU7CcrB96gIh2GHgnF+0xDOqO2W/1KeFAqOfqosoOVE48t+4dnEMkkoJ2Q==} '@cspell/dict-java@5.0.12': resolution: {integrity: sha512-qPSNhTcl7LGJ5Qp6VN71H8zqvRQK04S08T67knMq9hTA8U7G1sTKzLmBaDOFhq17vNX/+rT+rbRYp+B5Nwza1A==} @@ -1703,25 +1703,25 @@ packages: '@cspell/dict-makefile@1.0.5': resolution: {integrity: sha512-4vrVt7bGiK8Rx98tfRbYo42Xo2IstJkAF4tLLDMNQLkQ86msDlYSKG1ZCk8Abg+EdNcFAjNhXIiNO+w4KflGAQ==} - '@cspell/dict-markdown@2.0.13': - resolution: {integrity: sha512-rFeGikf+lVlywEp7giATUfi8myFeee6jqgbUgtdIdl/OBmRBPe5m7mKNk7yMItMZe8ICrwMxFwJy5OeTnrr6QA==} + '@cspell/dict-markdown@2.0.14': + resolution: {integrity: sha512-uLKPNJsUcumMQTsZZgAK9RgDLyQhUz/uvbQTEkvF/Q4XfC1i/BnA8XrOrd0+Vp6+tPOKyA+omI5LRWfMu5K/Lw==} peerDependencies: - '@cspell/dict-css': ^4.0.18 - '@cspell/dict-html': ^4.0.13 - '@cspell/dict-html-symbol-entities': ^4.0.4 + '@cspell/dict-css': ^4.0.19 + '@cspell/dict-html': ^4.0.14 + '@cspell/dict-html-symbol-entities': ^4.0.5 '@cspell/dict-typescript': ^3.2.3 - '@cspell/dict-monkeyc@1.0.11': - resolution: {integrity: sha512-7Q1Ncu0urALI6dPTrEbSTd//UK0qjRBeaxhnm8uY5fgYNFYAG+u4gtnTIo59S6Bw5P++4H3DiIDYoQdY/lha8w==} + '@cspell/dict-monkeyc@1.0.12': + resolution: {integrity: sha512-MN7Vs11TdP5mbdNFQP5x2Ac8zOBm97ARg6zM5Sb53YQt/eMvXOMvrep7+/+8NJXs0jkp70bBzjqU4APcqBFNAw==} '@cspell/dict-node@5.0.8': resolution: {integrity: sha512-AirZcN2i84ynev3p2/1NCPEhnNsHKMz9zciTngGoqpdItUb2bDt1nJBjwlsrFI78GZRph/VaqTVFwYikmncpXg==} - '@cspell/dict-npm@5.2.26': - resolution: {integrity: sha512-jtjp/wE/4KRTWjtiosAakDwdvrU4lTF3djOaI0tPDPytxou6QTHSm5A7FzU+MzLqvNfdYHUsCcdvx1FE1T/6pg==} + '@cspell/dict-npm@5.2.29': + resolution: {integrity: sha512-ZAef8JpYmbuHFT1zekj/YyImLPvZevjECw663EmG5GPePyNo4AfH8Dd2fFhaOyQ3P5I5LrkAhGwypnOfUxcssw==} - '@cspell/dict-php@4.1.0': - resolution: {integrity: sha512-dTDeabyOj7eFvn2Q4Za3uVXM2+SzeFMqX8ly2P0XTo4AzbCmI2hulFD/QIADwWmwiRrInbbf8cxwFHNIYrXl4w==} + '@cspell/dict-php@4.1.1': + resolution: {integrity: sha512-EXelI+4AftmdIGtA8HL8kr4WlUE11OqCSVlnIgZekmTkEGSZdYnkFdiJ5IANSALtlQ1mghKjz+OFqVs6yowgWA==} '@cspell/dict-powershell@5.0.15': resolution: {integrity: sha512-l4S5PAcvCFcVDMJShrYD0X6Huv9dcsQPlsVsBGbH38wvuN7gS7+GxZFAjTNxDmTY1wrNi1cCatSg6Pu2BW4rgg==} @@ -1729,26 +1729,26 @@ packages: '@cspell/dict-public-licenses@2.0.15': resolution: {integrity: sha512-cJEOs901H13Pfy0fl4dCD1U+xpWIMaEPq8MeYU83FfDZvellAuSo4GqWCripfIqlhns/L6+UZEIJSOZnjgy7Wg==} - '@cspell/dict-python@4.2.24': - resolution: {integrity: sha512-B1oXYTa0+3sKOvx/svwxFaT3MrkHJ7ZLWpA1N7ZyHoET7IJhLCwcfAu7DCTq1f24Wnd4t+ARJvPEmFbMx65VBw==} + '@cspell/dict-python@4.2.25': + resolution: {integrity: sha512-hDdN0YhKgpbtZVRjQ2c8jk+n0wQdidAKj1Fk8w7KEHb3YlY5uPJ0mAKJk7AJKPNLOlILoUmN+HAVJz+cfSbWYg==} '@cspell/dict-r@2.1.1': resolution: {integrity: sha512-71Ka+yKfG4ZHEMEmDxc6+blFkeTTvgKbKAbwiwQAuKl3zpqs1Y0vUtwW2N4b3LgmSPhV3ODVY0y4m5ofqDuKMw==} - '@cspell/dict-ruby@5.0.9': - resolution: {integrity: sha512-H2vMcERMcANvQshAdrVx0XoWaNX8zmmiQN11dZZTQAZaNJ0xatdJoSqY8C8uhEMW89bfgpN+NQgGuDXW2vmXEw==} + '@cspell/dict-ruby@5.1.0': + resolution: {integrity: sha512-9PJQB3cfkBULrMLp5kSAcFPpzf8oz9vFN+QYZABhQwWkGbuzCIXSorHrmWSASlx4yejt3brjaWS57zZ/YL5ZQQ==} - '@cspell/dict-rust@4.0.12': - resolution: {integrity: sha512-z2QiH+q9UlNhobBJArvILRxV8Jz0pKIK7gqu4TgmEYyjiu1TvnGZ1tbYHeu9w3I/wOP6UMDoCBTty5AlYfW0mw==} + '@cspell/dict-rust@4.1.1': + resolution: {integrity: sha512-fXiXnZH0wOaEVTKFRNaz6TsUGhuB8dAT0ubYkDNzRQCaV5JGSOebGb1v2x5ZrOSVp+moxWM/vdBfiNU6KOEaFQ==} - '@cspell/dict-scala@5.0.8': - resolution: {integrity: sha512-YdftVmumv8IZq9zu1gn2U7A4bfM2yj9Vaupydotyjuc+EEZZSqAafTpvW/jKLWji2TgybM1L2IhmV0s/Iv9BTw==} + '@cspell/dict-scala@5.0.9': + resolution: {integrity: sha512-AjVcVAELgllybr1zk93CJ5wSUNu/Zb5kIubymR/GAYkMyBdYFCZ3Zbwn4Zz8GJlFFAbazABGOu0JPVbeY59vGg==} '@cspell/dict-shell@1.1.2': resolution: {integrity: sha512-WqOUvnwcHK1X61wAfwyXq04cn7KYyskg90j4lLg3sGGKMW9Sq13hs91pqrjC44Q+lQLgCobrTkMDw9Wyl9nRFA==} - '@cspell/dict-software-terms@5.1.16': - resolution: {integrity: sha512-AJQ8KZyU9vi2XhEehh2ECkq/jyib0aHOjWYFeHx/2AIrn9LsYJwXI1aD7FFyQ3qixevp+ceAPJ0MVeWLL6LTTw==} + '@cspell/dict-software-terms@5.1.20': + resolution: {integrity: sha512-TEk1xHvetTI4pv7Vzje1D322m6QEjaH2P6ucOOf6q7EJCppQIdC0lZSXkgHJAFU5HGSvEXSzvnVeW2RHW86ziQ==} '@cspell/dict-sql@2.2.1': resolution: {integrity: sha512-qDHF8MpAYCf4pWU8NKbnVGzkoxMNrFqBHyG/dgrlic5EQiKANCLELYtGlX5auIMDLmTf1inA0eNtv74tyRJ/vg==} @@ -1771,20 +1771,20 @@ packages: '@cspell/dict-zig@1.0.0': resolution: {integrity: sha512-XibBIxBlVosU06+M6uHWkFeT0/pW5WajDRYdXG2CgHnq85b0TI/Ks0FuBJykmsgi2CAD3Qtx8UHFEtl/DSFnAQ==} - '@cspell/dynamic-import@9.4.0': - resolution: {integrity: sha512-d2fjLjzrKGUIn5hWK8gMuyAh2pqXSxBqOHpU1jR3jxbrO3MilunKNijaSstv7CZn067Jpc36VfaKQodaXNZzUA==} + '@cspell/dynamic-import@9.6.0': + resolution: {integrity: sha512-Lkn82wyGj2ltxeYfH2bEjshdes1fx3ouYUZxeW5i6SBBvEVJoSmr43AygI8A317UMIQxVj59qVBorrtGYcRI1w==} engines: {node: '>=20'} - '@cspell/filetypes@9.4.0': - resolution: {integrity: sha512-RMrYHkvPF0tHVFM+T4voEhX9sfYQrd/mnNbf6+O4CWUyLCz4NQ5H9yOgEIJwEcLu4y3NESGXFef/Jn5xo0CUfg==} + '@cspell/filetypes@9.6.0': + resolution: {integrity: sha512-CaWyk5j20H6sr+HCArtUY95jUQb7A/6W0GC4B4umnqoWvgqwR72duowLFa+w1K2C7tZg3GoV4Wf2cUn9jjt5FA==} engines: {node: '>=20'} - '@cspell/strong-weak-map@9.4.0': - resolution: {integrity: sha512-ui7mlXYmqElS/SmRubPBNWdkQVWgWbB6rjCurc+0owYXlnweItAMHTxC8mCWM/Au22SF1dB/JR8QBELFXLkTjQ==} + '@cspell/strong-weak-map@9.6.0': + resolution: {integrity: sha512-9g8LCLv/2RrprGeGnFAaBETWq7ESnBcoMbvgNu+vZE58iF+pbFvP0qGgKvVeKEEpc2LZhNuHLsUH37MUS6DOQg==} engines: {node: '>=20'} - '@cspell/url@9.4.0': - resolution: {integrity: sha512-nt88P6m20AaVbqMxsyPf8KqyWPaFEW2UANi0ijBxc2xTkD2KiUovxfZUYW6NMU9XBYZlovT5LztkEhst2yBcSA==} + '@cspell/url@9.6.0': + resolution: {integrity: sha512-257WOxh9vOYHAVgBNXRCdLEd+ldzlVbzcc9u+6DYoCDCNGe0OvOWOGsAfnUbMc9xEw48XgBlDYgOlPbjWGLOTg==} engines: {node: '>=20'} '@cspotcode/source-map-support@0.8.1': @@ -4608,8 +4608,8 @@ packages: resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} engines: {node: '>= 12'} - comment-json@4.4.1: - resolution: {integrity: sha512-r1To31BQD5060QdkC+Iheai7gHwoSZobzunqkf2/kQ6xIAfJyrKNAFUwdKvkK7Qgu7pVTKQEa7ok7Ed3ycAJgg==} + comment-json@4.5.1: + resolution: {integrity: sha512-taEtr3ozUmOB7it68Jll7s0Pwm+aoiHyXKrEC8SEodL4rNpdfDLqa7PfBlrgFoCNNdR8ImL+muti5IGvktJAAg==} engines: {node: '>= 6'} compressible@2.0.18: @@ -4738,42 +4738,44 @@ packages: cspell-ban-words@0.0.4: resolution: {integrity: sha512-w+18WPFAEmo2F+Fr4L29+GdY5ckOLN95WPwb/arfrtuzzB5VzQRFyIujo0T7pq+xFE0Z2gjfLn33Wk/u5ctNQQ==} - cspell-config-lib@9.4.0: - resolution: {integrity: sha512-CvQKSmK/DRIf3LpNx2sZth65pHW2AHngZqLkH3DTwnAPbiCAsE0XvCrVhvDfCNu/6uJIaa+NVHSs8GOf//DHBQ==} + cspell-config-lib@9.6.0: + resolution: {integrity: sha512-5ztvheawkmFXNHGN82iOOntU3T5mmlQBP/plgoKdBZ6+lSYrOJLkOyqxYyi7MrUBDtWrXPzFllkBrPNRDlbX/A==} engines: {node: '>=20'} - cspell-dictionary@9.4.0: - resolution: {integrity: sha512-c2qscanRZChoHZFYI7KpvBMdy8i6wNwl2EflcNRrFiFOq67t9CgxLe54PafaqhrHGpBc8nElaZKciLvjj6Uscw==} + cspell-dictionary@9.6.0: + resolution: {integrity: sha512-wW0m1kLrbK6bRY/GrLUGKUUJ1Z4ZUgIb8LD4zNaECcvGviv9V7VcR3mEwUip3ZjoHa3ClzEoWgQ9gXrtac80Wg==} engines: {node: '>=20'} - cspell-gitignore@9.4.0: - resolution: {integrity: sha512-HMrzLmJBUMSpaMMkltlTAz/aVOrHxixyhKfg5WbFCJ5JYZO6Qu3/JU3wRoOFoud9449wRjLkvrGmbbL2+vO6Lw==} + cspell-gitignore@9.6.0: + resolution: {integrity: sha512-8GfmJuRBBvibyPHnNE2wYJAiQ/ceDYLD1X1sUQaCyj6hPMR7ChJiVhFPtS11hMqkjZ46OBMYTMGWqO792L9fEQ==} engines: {node: '>=20'} hasBin: true - cspell-glob@9.4.0: - resolution: {integrity: sha512-Q87Suj9oXrhoKck15qWorCizBjMNxG/k3NjnhKIAMrF+PdUa1Mpl0MOD+hqV1Wvwh1UHcIMYCP3bR3XpBbNx+Q==} + cspell-glob@9.6.0: + resolution: {integrity: sha512-KmEbKN0qdEamsEYbkFu7zjLYfw3hMmn9kmeh94IHr2kq6vWq5vNP5l1BuqmrUeFZlbNd07vj08IKAZHYsoGheQ==} engines: {node: '>=20'} - cspell-grammar@9.4.0: - resolution: {integrity: sha512-ie7OQ4Neflo+61bMzoLR7GtlZfMBAm2KL1U4iNqh15wUE5fDbvXeN15H5lu+gcO8BwYvC5wxZknw1x62/J8+3Q==} + cspell-grammar@9.6.0: + resolution: {integrity: sha512-jZVIM5/3eB9rWURDq+VXdYip+DmPuFzO+bqaRtzqT8w6YoOIGYbiIxdwvyyA9xdH7SmW8uqHJP5x4pzZju1lNQ==} engines: {node: '>=20'} hasBin: true - cspell-io@9.4.0: - resolution: {integrity: sha512-8w30dqlO54H9w6WGlvZhHI5kytVbF3bYPqKJAZLWKEO36L2mdpf6/abx/FA4yVLJ56wmH1x0N0ZK32wNRl5C6A==} + cspell-io@9.6.0: + resolution: {integrity: sha512-wZuZzKOYIb698kVEINYjGaNFQu+AFZ945TORM3hapmPjez+vsHwl8m/pPpCHeGMpQtHMEDkX84AbQ7R55MRIwg==} engines: {node: '>=20'} - cspell-lib@9.4.0: - resolution: {integrity: sha512-ajjioE59IEDNUPawfaBpiMfGC32iKPkuYd4T9ftguuef8VvyKRifniiUi1nxwGgAhzSfxHvWs7qdT+29Pp5TMQ==} + cspell-lib@9.6.0: + resolution: {integrity: sha512-m9rIv8hkQ3Dio4s80HQbM9cdxENcd6pS8j2AHWL50OSjJf3Xhw6/wMrIAGbwLHP15K6QZVU2eJ/abCzIJwjA4w==} engines: {node: '>=20'} - cspell-trie-lib@9.4.0: - resolution: {integrity: sha512-bySJTm8XDiJAoC1MDo4lE/KpSNxydo13ZETC8TF7Hb3rbWI1c6o5eZ4+i/tkG3M94OvKV91+MeAvoMCe7GGgAw==} + cspell-trie-lib@9.6.0: + resolution: {integrity: sha512-L7GSff5F9cF60QT78WsebVlb3sppi6jbvTHwsw7WF1jUN/ioAo7OzBYtYB7xkYeejcdVEpqfvf/ZOXPDp8x2Wg==} engines: {node: '>=20'} + peerDependencies: + '@cspell/cspell-types': 9.6.0 - cspell@9.4.0: - resolution: {integrity: sha512-ZvXO+EY/G0/msu7jwRiVk0sXL/zB7DMJLBvjSUrK82uVbDoDxHwXxUuOz2UVnk2+J61//ldIZrjxVK8KMvaJlg==} + cspell@9.6.0: + resolution: {integrity: sha512-Mpf0oT2KAHTIb3YPAXWhW64/4CZKW5Lka4j1YxCLK3jM3nenmIsY/ocrJvqCMF4+1eejRF0N55sT3XmrijI5YQ==} engines: {node: '>=20'} hasBin: true @@ -5423,8 +5425,8 @@ packages: fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - fast-equals@5.3.3: - resolution: {integrity: sha512-/boTcHZeIAQ2r/tL11voclBHDeP9WPxLt+tyAbVSyyXuUFyh0Tne7gJZTqGbxnvj79TjLdCXLOY7UIPhyG5MTw==} + fast-equals@6.0.0: + resolution: {integrity: sha512-PFhhIGgdM79r5Uztdj9Zb6Tt1zKafqVfdMGwVca1z5z6fbX7DmsySSuJd8HiP6I1j505DCS83cLxo5rmSNeVEA==} engines: {node: '>=6.0.0'} fast-glob@3.3.3: @@ -7867,8 +7869,8 @@ packages: resolution: {integrity: sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==} engines: {node: '>=18'} - smol-toml@1.5.2: - resolution: {integrity: sha512-QlaZEqcAH3/RtNyet1IPIYPsEWAaYyXXv1Krsi+1L/QHppjX4Ifm8MQsBISz9vE8cHicIq3clogsheili5vhaQ==} + smol-toml@1.6.0: + resolution: {integrity: sha512-4zemZi0HvTnYwLfrpk/CF9LOd9Lt87kAt50GnqhMpyF9U3poDAP2+iukq2bZsO/ufegbYehBkqINbsWxj4l4cw==} engines: {node: '>= 18'} sockjs@0.3.24: @@ -9379,38 +9381,38 @@ snapshots: transitivePeerDependencies: - debug - '@cspell/cspell-bundled-dicts@9.4.0': + '@cspell/cspell-bundled-dicts@9.6.0': dependencies: '@cspell/dict-ada': 4.1.1 '@cspell/dict-al': 1.1.1 - '@cspell/dict-aws': 4.0.16 + '@cspell/dict-aws': 4.0.17 '@cspell/dict-bash': 4.2.2 - '@cspell/dict-companies': 3.2.7 - '@cspell/dict-cpp': 6.0.15 + '@cspell/dict-companies': 3.2.10 + '@cspell/dict-cpp': 7.0.2 '@cspell/dict-cryptocurrencies': 5.0.5 - '@cspell/dict-csharp': 4.0.7 - '@cspell/dict-css': 4.0.18 - '@cspell/dict-dart': 2.3.1 + '@cspell/dict-csharp': 4.0.8 + '@cspell/dict-css': 4.0.19 + '@cspell/dict-dart': 2.3.2 '@cspell/dict-data-science': 2.0.13 - '@cspell/dict-django': 4.1.5 - '@cspell/dict-docker': 1.1.16 - '@cspell/dict-dotnet': 5.0.10 + '@cspell/dict-django': 4.1.6 + '@cspell/dict-docker': 1.1.17 + '@cspell/dict-dotnet': 5.0.11 '@cspell/dict-elixir': 4.0.8 - '@cspell/dict-en-common-misspellings': 2.1.8 - '@cspell/dict-en-gb-mit': 3.1.14 - '@cspell/dict-en_us': 4.4.24 - '@cspell/dict-filetypes': 3.0.14 + '@cspell/dict-en-common-misspellings': 2.1.11 + '@cspell/dict-en-gb-mit': 3.1.16 + '@cspell/dict-en_us': 4.4.27 + '@cspell/dict-filetypes': 3.0.15 '@cspell/dict-flutter': 1.1.1 '@cspell/dict-fonts': 4.0.5 '@cspell/dict-fsharp': 1.1.1 '@cspell/dict-fullstack': 3.2.7 '@cspell/dict-gaming-terms': 1.1.2 '@cspell/dict-git': 3.0.7 - '@cspell/dict-golang': 6.0.24 + '@cspell/dict-golang': 6.0.26 '@cspell/dict-google': 1.0.9 '@cspell/dict-haskell': 4.0.6 - '@cspell/dict-html': 4.0.13 - '@cspell/dict-html-symbol-entities': 4.0.4 + '@cspell/dict-html': 4.0.14 + '@cspell/dict-html-symbol-entities': 4.0.5 '@cspell/dict-java': 5.0.12 '@cspell/dict-julia': 1.1.1 '@cspell/dict-k8s': 1.0.12 @@ -9419,20 +9421,20 @@ snapshots: '@cspell/dict-lorem-ipsum': 4.0.5 '@cspell/dict-lua': 4.0.8 '@cspell/dict-makefile': 1.0.5 - '@cspell/dict-markdown': 2.0.13(@cspell/dict-css@4.0.18)(@cspell/dict-html-symbol-entities@4.0.4)(@cspell/dict-html@4.0.13)(@cspell/dict-typescript@3.2.3) - '@cspell/dict-monkeyc': 1.0.11 + '@cspell/dict-markdown': 2.0.14(@cspell/dict-css@4.0.19)(@cspell/dict-html-symbol-entities@4.0.5)(@cspell/dict-html@4.0.14)(@cspell/dict-typescript@3.2.3) + '@cspell/dict-monkeyc': 1.0.12 '@cspell/dict-node': 5.0.8 - '@cspell/dict-npm': 5.2.26 - '@cspell/dict-php': 4.1.0 + '@cspell/dict-npm': 5.2.29 + '@cspell/dict-php': 4.1.1 '@cspell/dict-powershell': 5.0.15 '@cspell/dict-public-licenses': 2.0.15 - '@cspell/dict-python': 4.2.24 + '@cspell/dict-python': 4.2.25 '@cspell/dict-r': 2.1.1 - '@cspell/dict-ruby': 5.0.9 - '@cspell/dict-rust': 4.0.12 - '@cspell/dict-scala': 5.0.8 + '@cspell/dict-ruby': 5.1.0 + '@cspell/dict-rust': 4.1.1 + '@cspell/dict-scala': 5.0.9 '@cspell/dict-shell': 1.1.2 - '@cspell/dict-software-terms': 5.1.16 + '@cspell/dict-software-terms': 5.1.20 '@cspell/dict-sql': 2.2.1 '@cspell/dict-svelte': 1.0.7 '@cspell/dict-swift': 2.0.6 @@ -9441,59 +9443,59 @@ snapshots: '@cspell/dict-vue': 3.0.5 '@cspell/dict-zig': 1.0.0 - '@cspell/cspell-json-reporter@9.4.0': + '@cspell/cspell-json-reporter@9.6.0': dependencies: - '@cspell/cspell-types': 9.4.0 + '@cspell/cspell-types': 9.6.0 - '@cspell/cspell-pipe@9.4.0': {} + '@cspell/cspell-pipe@9.6.0': {} - '@cspell/cspell-resolver@9.4.0': + '@cspell/cspell-resolver@9.6.0': dependencies: global-directory: 4.0.1 - '@cspell/cspell-service-bus@9.4.0': {} + '@cspell/cspell-service-bus@9.6.0': {} - '@cspell/cspell-types@9.4.0': {} + '@cspell/cspell-types@9.6.0': {} '@cspell/dict-ada@4.1.1': {} '@cspell/dict-al@1.1.1': {} - '@cspell/dict-aws@4.0.16': {} + '@cspell/dict-aws@4.0.17': {} '@cspell/dict-bash@4.2.2': dependencies: '@cspell/dict-shell': 1.1.2 - '@cspell/dict-companies@3.2.7': {} + '@cspell/dict-companies@3.2.10': {} - '@cspell/dict-cpp@6.0.15': {} + '@cspell/dict-cpp@7.0.2': {} '@cspell/dict-cryptocurrencies@5.0.5': {} - '@cspell/dict-csharp@4.0.7': {} + '@cspell/dict-csharp@4.0.8': {} - '@cspell/dict-css@4.0.18': {} + '@cspell/dict-css@4.0.19': {} - '@cspell/dict-dart@2.3.1': {} + '@cspell/dict-dart@2.3.2': {} '@cspell/dict-data-science@2.0.13': {} - '@cspell/dict-django@4.1.5': {} + '@cspell/dict-django@4.1.6': {} - '@cspell/dict-docker@1.1.16': {} + '@cspell/dict-docker@1.1.17': {} - '@cspell/dict-dotnet@5.0.10': {} + '@cspell/dict-dotnet@5.0.11': {} '@cspell/dict-elixir@4.0.8': {} - '@cspell/dict-en-common-misspellings@2.1.8': {} + '@cspell/dict-en-common-misspellings@2.1.11': {} - '@cspell/dict-en-gb-mit@3.1.14': {} + '@cspell/dict-en-gb-mit@3.1.16': {} - '@cspell/dict-en_us@4.4.24': {} + '@cspell/dict-en_us@4.4.27': {} - '@cspell/dict-filetypes@3.0.14': {} + '@cspell/dict-filetypes@3.0.15': {} '@cspell/dict-flutter@1.1.1': {} @@ -9507,15 +9509,15 @@ snapshots: '@cspell/dict-git@3.0.7': {} - '@cspell/dict-golang@6.0.24': {} + '@cspell/dict-golang@6.0.26': {} '@cspell/dict-google@1.0.9': {} '@cspell/dict-haskell@4.0.6': {} - '@cspell/dict-html-symbol-entities@4.0.4': {} + '@cspell/dict-html-symbol-entities@4.0.5': {} - '@cspell/dict-html@4.0.13': {} + '@cspell/dict-html@4.0.14': {} '@cspell/dict-java@5.0.12': {} @@ -9533,40 +9535,40 @@ snapshots: '@cspell/dict-makefile@1.0.5': {} - '@cspell/dict-markdown@2.0.13(@cspell/dict-css@4.0.18)(@cspell/dict-html-symbol-entities@4.0.4)(@cspell/dict-html@4.0.13)(@cspell/dict-typescript@3.2.3)': + '@cspell/dict-markdown@2.0.14(@cspell/dict-css@4.0.19)(@cspell/dict-html-symbol-entities@4.0.5)(@cspell/dict-html@4.0.14)(@cspell/dict-typescript@3.2.3)': dependencies: - '@cspell/dict-css': 4.0.18 - '@cspell/dict-html': 4.0.13 - '@cspell/dict-html-symbol-entities': 4.0.4 + '@cspell/dict-css': 4.0.19 + '@cspell/dict-html': 4.0.14 + '@cspell/dict-html-symbol-entities': 4.0.5 '@cspell/dict-typescript': 3.2.3 - '@cspell/dict-monkeyc@1.0.11': {} + '@cspell/dict-monkeyc@1.0.12': {} '@cspell/dict-node@5.0.8': {} - '@cspell/dict-npm@5.2.26': {} + '@cspell/dict-npm@5.2.29': {} - '@cspell/dict-php@4.1.0': {} + '@cspell/dict-php@4.1.1': {} '@cspell/dict-powershell@5.0.15': {} '@cspell/dict-public-licenses@2.0.15': {} - '@cspell/dict-python@4.2.24': + '@cspell/dict-python@4.2.25': dependencies: '@cspell/dict-data-science': 2.0.13 '@cspell/dict-r@2.1.1': {} - '@cspell/dict-ruby@5.0.9': {} + '@cspell/dict-ruby@5.1.0': {} - '@cspell/dict-rust@4.0.12': {} + '@cspell/dict-rust@4.1.1': {} - '@cspell/dict-scala@5.0.8': {} + '@cspell/dict-scala@5.0.9': {} '@cspell/dict-shell@1.1.2': {} - '@cspell/dict-software-terms@5.1.16': {} + '@cspell/dict-software-terms@5.1.20': {} '@cspell/dict-sql@2.2.1': {} @@ -9582,16 +9584,16 @@ snapshots: '@cspell/dict-zig@1.0.0': {} - '@cspell/dynamic-import@9.4.0': + '@cspell/dynamic-import@9.6.0': dependencies: - '@cspell/url': 9.4.0 + '@cspell/url': 9.6.0 import-meta-resolve: 4.2.0 - '@cspell/filetypes@9.4.0': {} + '@cspell/filetypes@9.6.0': {} - '@cspell/strong-weak-map@9.4.0': {} + '@cspell/strong-weak-map@9.6.0': {} - '@cspell/url@9.4.0': {} + '@cspell/url@9.6.0': {} '@cspotcode/source-map-support@0.8.1': dependencies: @@ -12376,7 +12378,7 @@ snapshots: commander@8.3.0: {} - comment-json@4.4.1: + comment-json@4.5.1: dependencies: array-timsort: 1.0.3 core-util-is: 1.0.3 @@ -12530,58 +12532,58 @@ snapshots: cspell-ban-words@0.0.4: {} - cspell-config-lib@9.4.0: + cspell-config-lib@9.6.0: dependencies: - '@cspell/cspell-types': 9.4.0 - comment-json: 4.4.1 - smol-toml: 1.5.2 + '@cspell/cspell-types': 9.6.0 + comment-json: 4.5.1 + smol-toml: 1.6.0 yaml: 2.8.2 - cspell-dictionary@9.4.0: + cspell-dictionary@9.6.0: dependencies: - '@cspell/cspell-pipe': 9.4.0 - '@cspell/cspell-types': 9.4.0 - cspell-trie-lib: 9.4.0 - fast-equals: 5.3.3 + '@cspell/cspell-pipe': 9.6.0 + '@cspell/cspell-types': 9.6.0 + cspell-trie-lib: 9.6.0(@cspell/cspell-types@9.6.0) + fast-equals: 6.0.0 - cspell-gitignore@9.4.0: + cspell-gitignore@9.6.0: dependencies: - '@cspell/url': 9.4.0 - cspell-glob: 9.4.0 - cspell-io: 9.4.0 + '@cspell/url': 9.6.0 + cspell-glob: 9.6.0 + cspell-io: 9.6.0 - cspell-glob@9.4.0: + cspell-glob@9.6.0: dependencies: - '@cspell/url': 9.4.0 + '@cspell/url': 9.6.0 picomatch: 4.0.3 - cspell-grammar@9.4.0: + cspell-grammar@9.6.0: dependencies: - '@cspell/cspell-pipe': 9.4.0 - '@cspell/cspell-types': 9.4.0 + '@cspell/cspell-pipe': 9.6.0 + '@cspell/cspell-types': 9.6.0 - cspell-io@9.4.0: + cspell-io@9.6.0: dependencies: - '@cspell/cspell-service-bus': 9.4.0 - '@cspell/url': 9.4.0 + '@cspell/cspell-service-bus': 9.6.0 + '@cspell/url': 9.6.0 - cspell-lib@9.4.0: + cspell-lib@9.6.0: dependencies: - '@cspell/cspell-bundled-dicts': 9.4.0 - '@cspell/cspell-pipe': 9.4.0 - '@cspell/cspell-resolver': 9.4.0 - '@cspell/cspell-types': 9.4.0 - '@cspell/dynamic-import': 9.4.0 - '@cspell/filetypes': 9.4.0 - '@cspell/strong-weak-map': 9.4.0 - '@cspell/url': 9.4.0 + '@cspell/cspell-bundled-dicts': 9.6.0 + '@cspell/cspell-pipe': 9.6.0 + '@cspell/cspell-resolver': 9.6.0 + '@cspell/cspell-types': 9.6.0 + '@cspell/dynamic-import': 9.6.0 + '@cspell/filetypes': 9.6.0 + '@cspell/strong-weak-map': 9.6.0 + '@cspell/url': 9.6.0 clear-module: 4.1.2 - cspell-config-lib: 9.4.0 - cspell-dictionary: 9.4.0 - cspell-glob: 9.4.0 - cspell-grammar: 9.4.0 - cspell-io: 9.4.0 - cspell-trie-lib: 9.4.0 + cspell-config-lib: 9.6.0 + cspell-dictionary: 9.6.0 + cspell-glob: 9.6.0 + cspell-grammar: 9.6.0 + cspell-io: 9.6.0 + cspell-trie-lib: 9.6.0(@cspell/cspell-types@9.6.0) env-paths: 3.0.0 gensequence: 8.0.8 import-fresh: 3.3.1 @@ -12590,29 +12592,27 @@ snapshots: vscode-uri: 3.1.0 xdg-basedir: 5.1.0 - cspell-trie-lib@9.4.0: + cspell-trie-lib@9.6.0(@cspell/cspell-types@9.6.0): dependencies: - '@cspell/cspell-pipe': 9.4.0 - '@cspell/cspell-types': 9.4.0 - gensequence: 8.0.8 + '@cspell/cspell-types': 9.6.0 - cspell@9.4.0: + cspell@9.6.0: dependencies: - '@cspell/cspell-json-reporter': 9.4.0 - '@cspell/cspell-pipe': 9.4.0 - '@cspell/cspell-types': 9.4.0 - '@cspell/dynamic-import': 9.4.0 - '@cspell/url': 9.4.0 + '@cspell/cspell-json-reporter': 9.6.0 + '@cspell/cspell-pipe': 9.6.0 + '@cspell/cspell-types': 9.6.0 + '@cspell/dynamic-import': 9.6.0 + '@cspell/url': 9.6.0 ansi-regex: 6.2.2 chalk: 5.6.2 chalk-template: 1.1.2 commander: 14.0.2 - cspell-config-lib: 9.4.0 - cspell-dictionary: 9.4.0 - cspell-gitignore: 9.4.0 - cspell-glob: 9.4.0 - cspell-io: 9.4.0 - cspell-lib: 9.4.0 + cspell-config-lib: 9.6.0 + cspell-dictionary: 9.6.0 + cspell-gitignore: 9.6.0 + cspell-glob: 9.6.0 + cspell-io: 9.6.0 + cspell-lib: 9.6.0 fast-json-stable-stringify: 2.1.0 flatted: 3.3.3 semver: 7.7.3 @@ -13352,7 +13352,7 @@ snapshots: fast-deep-equal@3.1.3: {} - fast-equals@5.3.3: {} + fast-equals@6.0.0: {} fast-glob@3.3.3: dependencies: @@ -16331,7 +16331,7 @@ snapshots: ansi-styles: 6.2.3 is-fullwidth-code-point: 5.1.0 - smol-toml@1.5.2: {} + smol-toml@1.6.0: {} sockjs@0.3.24: dependencies: diff --git a/website/package.json b/website/package.json index 96e9a1d63ea8..e28499c15c73 100644 --- a/website/package.json +++ b/website/package.json @@ -38,7 +38,7 @@ "@types/react": "^19.2.8", "@types/semver": "^7.7.1", "case-police": "~2.1.1", - "cspell": "^9.4.0", + "cspell": "^9.6.0", "cspell-ban-words": "0.0.4", "heading-case": "^1.0.4", "rsbuild-plugin-google-analytics": "1.0.4", From 8f850305e01e0328e155c9c4ca391acfe69d3412 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 18 Jan 2026 00:47:15 +0000 Subject: [PATCH 71/87] chore(deps): update dependency emnapi to ^1.8.1 (#12769) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- crates/node_binding/package.json | 2 +- .../package.json | 2 +- pnpm-lock.yaml | 22 +++++++++---------- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/crates/node_binding/package.json b/crates/node_binding/package.json index 4834bb072882..b3dce9fe1ae8 100644 --- a/crates/node_binding/package.json +++ b/crates/node_binding/package.json @@ -34,7 +34,7 @@ "devDependencies": { "@napi-rs/cli": "3.0.4", "@napi-rs/wasm-runtime": "1.0.7", - "emnapi": "^1.7.1", + "emnapi": "^1.8.1", "typescript": "^5.9.3" }, "napi": { diff --git a/crates/rspack_binding_builder_testing/package.json b/crates/rspack_binding_builder_testing/package.json index eef96ea5cfd4..ef2ce8391f72 100644 --- a/crates/rspack_binding_builder_testing/package.json +++ b/crates/rspack_binding_builder_testing/package.json @@ -24,7 +24,7 @@ "devDependencies": { "@napi-rs/cli": "3.0.4", "@napi-rs/wasm-runtime": "1.0.7", - "emnapi": "^1.7.1", + "emnapi": "^1.8.1", "typescript": "^5.9.3" }, "napi": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7a9f5cdb1990..b9aba1f0aff3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -81,13 +81,13 @@ importers: devDependencies: '@napi-rs/cli': specifier: 3.0.4 - version: 3.0.4(@emnapi/runtime@1.5.0)(@types/node@20.19.29)(emnapi@1.7.1(node-addon-api@7.1.1)) + version: 3.0.4(@emnapi/runtime@1.5.0)(@types/node@20.19.29)(emnapi@1.8.1(node-addon-api@7.1.1)) '@napi-rs/wasm-runtime': specifier: 1.0.7 version: 1.0.7 emnapi: - specifier: ^1.7.1 - version: 1.7.1(node-addon-api@7.1.1) + specifier: ^1.8.1 + version: 1.8.1(node-addon-api@7.1.1) typescript: specifier: ^5.9.3 version: 5.9.3 @@ -127,13 +127,13 @@ importers: devDependencies: '@napi-rs/cli': specifier: 3.0.4 - version: 3.0.4(@emnapi/runtime@1.5.0)(@types/node@20.19.29)(emnapi@1.7.1(node-addon-api@7.1.1)) + version: 3.0.4(@emnapi/runtime@1.5.0)(@types/node@20.19.29)(emnapi@1.8.1(node-addon-api@7.1.1)) '@napi-rs/wasm-runtime': specifier: 1.0.7 version: 1.0.7 emnapi: - specifier: ^1.7.1 - version: 1.7.1(node-addon-api@7.1.1) + specifier: ^1.8.1 + version: 1.8.1(node-addon-api@7.1.1) typescript: specifier: ^5.9.3 version: 5.9.3 @@ -5164,8 +5164,8 @@ packages: elliptic@6.6.1: resolution: {integrity: sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==} - emnapi@1.7.1: - resolution: {integrity: sha512-wlLK2xFq+T+rCBlY6+lPlFVDEyE93b7hSn9dMrfWBIcPf4ArwUvymvvMnN9M5WWuiryYQe9M+UJrkqw4trdyRA==} + emnapi@1.8.1: + resolution: {integrity: sha512-34i2BbgHx1LnEO4JCGQYo6h6s4e4KrdWtdTHfllBNLbXSHPmdIHplxKejfabsRK+ukNciqVdalB+fxMibqHdaQ==} peerDependencies: node-addon-api: '>= 6.1.0' peerDependenciesMeta: @@ -10199,7 +10199,7 @@ snapshots: '@module-federation/runtime': 0.22.0 '@module-federation/sdk': 0.22.0 - '@napi-rs/cli@3.0.4(@emnapi/runtime@1.5.0)(@types/node@20.19.29)(emnapi@1.7.1(node-addon-api@7.1.1))': + '@napi-rs/cli@3.0.4(@emnapi/runtime@1.5.0)(@types/node@20.19.29)(emnapi@1.8.1(node-addon-api@7.1.1))': dependencies: '@inquirer/prompts': 7.8.6(@types/node@20.19.29) '@napi-rs/cross-toolchain': 1.0.3 @@ -10215,7 +10215,7 @@ snapshots: typanion: 3.14.0 optionalDependencies: '@emnapi/runtime': 1.5.0 - emnapi: 1.7.1(node-addon-api@7.1.1) + emnapi: 1.8.1(node-addon-api@7.1.1) transitivePeerDependencies: - '@napi-rs/cross-toolchain-arm64-target-aarch64' - '@napi-rs/cross-toolchain-arm64-target-armv7' @@ -13025,7 +13025,7 @@ snapshots: minimalistic-assert: 1.0.1 minimalistic-crypto-utils: 1.0.1 - emnapi@1.7.1(node-addon-api@7.1.1): + emnapi@1.8.1(node-addon-api@7.1.1): optionalDependencies: node-addon-api: 7.1.1 From 2f0bc179c529d000670c23fa9d1b980902664f79 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 18 Jan 2026 00:47:48 +0000 Subject: [PATCH 72/87] chore(deps): update dependency memfs to v4.53.0 (#12770) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- packages/rspack-browser/package.json | 2 +- packages/rspack-test-tools/package.json | 2 +- packages/rspack/package.json | 2 +- pnpm-lock.yaml | 26 ++++++++++++------------- tests/rspack-test/package.json | 2 +- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/packages/rspack-browser/package.json b/packages/rspack-browser/package.json index c6c5abcdf943..305f2c4f5e14 100644 --- a/packages/rspack-browser/package.json +++ b/packages/rspack-browser/package.json @@ -37,7 +37,7 @@ "@rspack/lite-tapable": "1.1.0", "@swc/types": "0.1.25", "@types/watchpack": "^2.4.5", - "memfs": "4.51.1", + "memfs": "4.53.0", "webpack-sources": "3.3.3" }, "peerDependencies": { diff --git a/packages/rspack-test-tools/package.json b/packages/rspack-test-tools/package.json index f92246f768fe..51dc34045bd9 100644 --- a/packages/rspack-test-tools/package.json +++ b/packages/rspack-test-tools/package.json @@ -53,7 +53,7 @@ "jest-diff": "^30.2.0", "jest-snapshot": "29.7.0", "jsdom": "^26.1.0", - "memfs": "4.51.1", + "memfs": "4.53.0", "path-serializer": "0.5.1", "pretty-format": "30.2.0", "rimraf": "^5.0.10", diff --git a/packages/rspack/package.json b/packages/rspack/package.json index 808c625ec961..dd4f5f7ecd95 100644 --- a/packages/rspack/package.json +++ b/packages/rspack/package.json @@ -56,7 +56,7 @@ "browserslist-load-config": "^1.0.1", "enhanced-resolve": "5.18.4", "glob-to-regexp": "^0.4.1", - "memfs": "4.51.1", + "memfs": "4.53.0", "prebundle": "^1.6.0", "tinypool": "^1.1.1", "tsx": "^4.21.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b9aba1f0aff3..324bc562fba5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -388,8 +388,8 @@ importers: specifier: ^0.4.1 version: 0.4.1 memfs: - specifier: 4.51.1 - version: 4.51.1 + specifier: 4.53.0 + version: 4.53.0 prebundle: specifier: ^1.6.0 version: 1.6.0(typescript@5.9.3) @@ -427,8 +427,8 @@ importers: specifier: ^2.4.5 version: 2.4.5 memfs: - specifier: 4.51.1 - version: 4.51.1 + specifier: 4.53.0 + version: 4.53.0 webpack-sources: specifier: 3.3.3 version: 3.3.3(patch_hash=b2a26650f08a2359d0a3cd81fa6fa272aa7441a28dd7e601792da5ed5d2b4aee) @@ -527,8 +527,8 @@ importers: specifier: ^26.1.0 version: 26.1.0 memfs: - specifier: 4.51.1 - version: 4.51.1 + specifier: 4.53.0 + version: 4.53.0 path-serializer: specifier: 0.5.1 version: 0.5.1 @@ -835,8 +835,8 @@ importers: specifier: ^4.17.22 version: 4.17.22 memfs: - specifier: 4.51.1 - version: 4.51.1 + specifier: 4.53.0 + version: 4.53.0 mime-types: specifier: ^3.0.2 version: 3.0.2 @@ -6494,8 +6494,8 @@ packages: resolution: {integrity: sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==} engines: {node: '>= 4.0.0'} - memfs@4.51.1: - resolution: {integrity: sha512-Eyt3XrufitN2ZL9c/uIRMyDwXanLI88h/L3MoWqNY747ha3dMR9dWqp8cRT5ntjZ0U1TNuq4U91ZXK0sMBjYOQ==} + memfs@4.53.0: + resolution: {integrity: sha512-TKFRsKjJA30iAc9ZeGH/77v5nLcNUD0GBOL/tAj4O63RPIKNxGDZ54ZyuQM4KjEKEj7gfer/Ta1xAzB+HrEnrA==} merge-descriptors@1.0.3: resolution: {integrity: sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==} @@ -14678,7 +14678,7 @@ snapshots: dependencies: fs-monkey: 1.1.0 - memfs@4.51.1: + memfs@4.53.0: dependencies: '@jsonjoy.com/json-pack': 1.14.0(tslib@2.8.1) '@jsonjoy.com/util': 1.9.0(tslib@2.8.1) @@ -17042,7 +17042,7 @@ snapshots: webpack-dev-middleware@7.4.5(webpack@5.102.1): dependencies: colorette: 2.0.20 - memfs: 4.51.1 + memfs: 4.53.0 mime-types: 3.0.2 on-finished: 2.4.1 range-parser: 1.2.1 @@ -17053,7 +17053,7 @@ snapshots: webpack-dev-middleware@7.4.5(webpack@5.99.9): dependencies: colorette: 2.0.20 - memfs: 4.51.1 + memfs: 4.53.0 mime-types: 3.0.2 on-finished: 2.4.1 range-parser: 1.2.1 diff --git a/tests/rspack-test/package.json b/tests/rspack-test/package.json index 3678d5dd0f2e..c92bdcf5f5ba 100644 --- a/tests/rspack-test/package.json +++ b/tests/rspack-test/package.json @@ -42,7 +42,7 @@ "html-webpack-plugin": "^5.6.5", "less-loader": "^12.3.0", "lodash": "^4.17.21", - "memfs": "4.51.1", + "memfs": "4.53.0", "mini-svg-data-uri": "^1.4.4", "node-polyfill-webpack-plugin": "^4.1.0", "postcss-loader": "^8.2.0", From 1dc4b725c773bd773d087cffdb011ab611eeba6f Mon Sep 17 00:00:00 2001 From: pshu Date: Mon, 19 Jan 2026 11:14:09 +0800 Subject: [PATCH 73/87] refactor: use compilation readonly ref in codegen optimization hook (#12743) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: use compilation readonly ref in code generation optimization hook * chore: debug bench ci * fix: 🐛 use offical codseed action * Debug ci * Remove debugger * Limit tokio and rayon worker threads * Revert "Limit tokio and rayon worker threads" This reverts commit 10fe6acd6bf8c32ab502230bcd89acf1108f4ad5. * Update crates/rspack_plugin_progress/src/lib.rs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: CPunisher <1343316114@qq.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- crates/rspack_core/src/compilation/mod.rs | 2 +- .../compilation/optimize_code_generation/mod.rs | 15 ++++++++++++++- .../src/plugin/mangle_exports_plugin.rs | 16 +++++++++++----- crates/rspack_plugin_progress/src/lib.rs | 7 ++++++- 4 files changed, 32 insertions(+), 8 deletions(-) diff --git a/crates/rspack_core/src/compilation/mod.rs b/crates/rspack_core/src/compilation/mod.rs index d30ba2de0f44..548fc97d158f 100644 --- a/crates/rspack_core/src/compilation/mod.rs +++ b/crates/rspack_core/src/compilation/mod.rs @@ -113,7 +113,7 @@ define_hook!(CompilationAdditionalChunkRuntimeRequirements: Series(compilation: define_hook!(CompilationRuntimeRequirementInChunk: SeriesBail(compilation: &mut Compilation, chunk_ukey: &ChunkUkey, all_runtime_requirements: &RuntimeGlobals, runtime_requirements: &RuntimeGlobals, runtime_requirements_mut: &mut RuntimeGlobals)); define_hook!(CompilationAdditionalTreeRuntimeRequirements: Series(compilation: &mut Compilation, chunk_ukey: &ChunkUkey, runtime_requirements: &mut RuntimeGlobals)); define_hook!(CompilationRuntimeRequirementInTree: SeriesBail(compilation: &mut Compilation, chunk_ukey: &ChunkUkey, all_runtime_requirements: &RuntimeGlobals, runtime_requirements: &RuntimeGlobals, runtime_requirements_mut: &mut RuntimeGlobals)); -define_hook!(CompilationOptimizeCodeGeneration: Series(compilation: &mut Compilation)); +define_hook!(CompilationOptimizeCodeGeneration: Series(compilation: &Compilation, build_module_graph_artifact: &mut BuildModuleGraphArtifact, diagnostics: &mut Vec)); define_hook!(CompilationAfterCodeGeneration: Series(compilation: &Compilation, diagnostics: &mut Vec)); define_hook!(CompilationChunkHash: Series(compilation: &Compilation, chunk_ukey: &ChunkUkey, hasher: &mut RspackHash),tracing=false); define_hook!(CompilationContentHash: Series(compilation: &Compilation, chunk_ukey: &ChunkUkey, hashes: &mut HashMap)); diff --git a/crates/rspack_core/src/compilation/optimize_code_generation/mod.rs b/crates/rspack_core/src/compilation/optimize_code_generation/mod.rs index 280b91cbb6ae..59ad2a8a0e4b 100644 --- a/crates/rspack_core/src/compilation/optimize_code_generation/mod.rs +++ b/crates/rspack_core/src/compilation/optimize_code_generation/mod.rs @@ -7,12 +7,25 @@ pub async fn optimize_code_generation_pass( ) -> Result<()> { let logger = compilation.get_logger("rspack.Compilation"); let start = logger.time("optimize code generation"); + + let mut build_module_graph_artifact = compilation.build_module_graph_artifact.take(); + let mut diagnostics = vec![]; plugin_driver .compilation_hooks .optimize_code_generation - .call(compilation) + .call( + compilation, + &mut build_module_graph_artifact, + &mut diagnostics, + ) .await .map_err(|e| e.wrap_err("caused by plugins in Compilation.hooks.optimizeCodeGeneration"))?; + + compilation + .build_module_graph_artifact + .replace(build_module_graph_artifact); + compilation.extend_diagnostics(diagnostics); + logger.time_end(start); Ok(()) } diff --git a/crates/rspack_plugin_javascript/src/plugin/mangle_exports_plugin.rs b/crates/rspack_plugin_javascript/src/plugin/mangle_exports_plugin.rs index c5d965053442..4f02dd4d6f80 100644 --- a/crates/rspack_plugin_javascript/src/plugin/mangle_exports_plugin.rs +++ b/crates/rspack_plugin_javascript/src/plugin/mangle_exports_plugin.rs @@ -6,9 +6,10 @@ use regex::Regex; use rspack_core::{ BuildMetaExportsType, Compilation, CompilationOptimizeCodeGeneration, ExportInfo, ExportProvided, ExportsInfo, ExportsInfoGetter, ModuleGraph, Plugin, PrefetchExportsInfoMode, - PrefetchedExportsInfoWrapper, UsageState, UsedNameItem, incremental::IncrementalPasses, + PrefetchedExportsInfoWrapper, UsageState, UsedNameItem, + build_module_graph::BuildModuleGraphArtifact, incremental::IncrementalPasses, }; -use rspack_error::Result; +use rspack_error::{Diagnostic, Result}; use rspack_hook::{plugin, plugin_hook}; use rspack_ids::id_helpers::assign_deterministic_ids; use rspack_util::atom::Atom; @@ -59,17 +60,22 @@ struct ExportInfoCache { } #[plugin_hook(CompilationOptimizeCodeGeneration for MangleExportsPlugin)] -async fn optimize_code_generation(&self, compilation: &mut Compilation) -> Result<()> { +async fn optimize_code_generation( + &self, + compilation: &Compilation, + build_module_graph_artifact: &mut BuildModuleGraphArtifact, + diagnostics: &mut Vec, +) -> Result<()> { if let Some(diagnostic) = compilation.incremental.disable_passes( IncrementalPasses::MODULES_HASHES, "MangleExportsPlugin (optimization.mangleExports = true)", "it requires calculating the export names of all the modules, which is a global effect", ) && let Some(diagnostic) = diagnostic { - compilation.push_diagnostic(diagnostic); + diagnostics.push(diagnostic); } - let mg = compilation.get_module_graph_mut(); + let mg = build_module_graph_artifact.get_module_graph_mut(); let modules = mg.modules(); let mut exports_info_cache = FxHashMap::default(); diff --git a/crates/rspack_plugin_progress/src/lib.rs b/crates/rspack_plugin_progress/src/lib.rs index 80a99516e3fa..8a9e4bc81e83 100644 --- a/crates/rspack_plugin_progress/src/lib.rs +++ b/crates/rspack_plugin_progress/src/lib.rs @@ -509,7 +509,12 @@ async fn chunk_ids( } #[plugin_hook(CompilationOptimizeCodeGeneration for ProgressPlugin)] -async fn optimize_code_generation(&self, _compilation: &mut Compilation) -> Result<()> { +async fn optimize_code_generation( + &self, + _compilation: &Compilation, + _build_module_graph_artifact: &mut BuildModuleGraphArtifact, + _diagnostics: &mut Vec, +) -> Result<()> { self.sealing_hooks_report("code generation", 26).await } From 5b35090e32d10de22ed21dd23ca886caa884f5cc Mon Sep 17 00:00:00 2001 From: CPunisher <1343316114@qq.com> Date: Mon, 19 Jan 2026 11:27:34 +0800 Subject: [PATCH 74/87] fix(browser): update worker format and add e2e test (#12747) * fix: remove lazyCompilationMiddleware * chore: change worker entry to iife * chore: add e2e test * chore: fix format * fix: add await for e2e * fix: remove unused imports * chore: fix ci yml * chore: fix ci WASM env injection --- .github/workflows/reusable-build-test.yml | 19 +- packages/rspack/rslib.browser.config.mts | 6 +- packages/rspack/src/browser/middleware.ts | 3 + pnpm-lock.yaml | 3 + .../browser-cases/basic-react/index.test.ts | 13 ++ .../basic-react/rspack.config.js | 25 ++ .../browser-cases/basic-react/src/files.js | 213 ++++++++++++++++++ .../browser-cases/basic-react/src/index.js | 20 ++ tests/e2e/package.json | 1 + tests/e2e/playwright.config.ts | 2 +- tests/e2e/tsconfig.json | 9 +- 11 files changed, 310 insertions(+), 4 deletions(-) create mode 100644 packages/rspack/src/browser/middleware.ts create mode 100644 tests/e2e/browser-cases/basic-react/index.test.ts create mode 100644 tests/e2e/browser-cases/basic-react/rspack.config.js create mode 100644 tests/e2e/browser-cases/basic-react/src/files.js create mode 100644 tests/e2e/browser-cases/basic-react/src/index.js diff --git a/.github/workflows/reusable-build-test.yml b/.github/workflows/reusable-build-test.yml index 653b70db4e73..dd71aee68af9 100644 --- a/.github/workflows/reusable-build-test.yml +++ b/.github/workflows/reusable-build-test.yml @@ -16,7 +16,7 @@ on: jobs: e2e: name: E2E Testing - if: inputs.target == 'x86_64-unknown-linux-gnu' + if: inputs.target == 'x86_64-unknown-linux-gnu' || inputs.target == 'wasm32-wasip1-threads' runs-on: ${{ fromJSON(inputs.runner) }} defaults: run: @@ -51,6 +51,7 @@ jobs: - name: Run e2e uses: ./.github/actions/docker/run + if: inputs.target == 'x86_64-unknown-linux-gnu' with: # Jammy uses ubuntu 22.04 # If this is to change, make sure to upgrade the ubuntu version in GitHub Actions @@ -63,6 +64,22 @@ jobs: pnpm run build:js pnpm run test:e2e + - name: Run e2e for @rspack/browser + uses: ./.github/actions/docker/run + if: inputs.target == 'wasm32-wasip1-threads' + with: + # Jammy uses ubuntu 22.04 + # If this is to change, make sure to upgrade the ubuntu version in GitHub Actions + image: mcr.microsoft.com/playwright:v1.57.0-jammy + # .cache is required by download artifact, and mount in ./.github/actions/docker/run + # .tool_cache is required by pnpm + options: -v ${{ runner.tool_cache }}:${{runner.tool_cache}} + script: | + export PATH=${{ steps.calculate-node-bin-path.outputs.path }}:$PATH + export WASM=1 + pnpm run build:js + pnpm run test:e2e + test: runs-on: ${{ fromJSON(inputs.runner) }} timeout-minutes: 60 diff --git a/packages/rspack/rslib.browser.config.mts b/packages/rspack/rslib.browser.config.mts index 2d1a16262fd5..0555f966f887 100644 --- a/packages/rspack/rslib.browser.config.mts +++ b/packages/rspack/rslib.browser.config.mts @@ -23,7 +23,7 @@ export default defineConfig({ }, }, { - format: 'esm', + format: 'iife', syntax: 'es2021', dts: false, autoExtension: false, @@ -109,6 +109,10 @@ export default defineConfig({ /src[/\\]loader-runner[/\\]service\.ts/, path.resolve('./src/browser/service.ts'), ), + new rspack.NormalModuleReplacementPlugin( + /src[/\\]builtin-plugin[/\\]lazy-compilation[/\\]middleware\.ts/, + path.resolve('./src/browser/middleware.ts'), + ), ); }, }, diff --git a/packages/rspack/src/browser/middleware.ts b/packages/rspack/src/browser/middleware.ts new file mode 100644 index 000000000000..3d66bf2e1d03 --- /dev/null +++ b/packages/rspack/src/browser/middleware.ts @@ -0,0 +1,3 @@ +export const lazyCompilationMiddleware = () => { + throw new Error('lazy compilation middleware is not supported in browser'); +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 324bc562fba5..e9c1764a5b7a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -648,6 +648,9 @@ importers: '@playwright/test': specifier: 1.57.0 version: 1.57.0 + '@rspack/browser': + specifier: workspace:* + version: link:../../packages/rspack-browser '@rspack/core': specifier: workspace:* version: link:../../packages/rspack diff --git a/tests/e2e/browser-cases/basic-react/index.test.ts b/tests/e2e/browser-cases/basic-react/index.test.ts new file mode 100644 index 000000000000..3f3283034ae0 --- /dev/null +++ b/tests/e2e/browser-cases/basic-react/index.test.ts @@ -0,0 +1,13 @@ +import { test, expect } from '@/fixtures'; + +test('@rspack/browser should bundle react app successfully', async ({ + page, +}) => { + // There should be a long bundle result + await expect + .poll(async () => { + const text = await page.locator('#output').innerText(); + return text.length; + }) + .toBeGreaterThan(500); +}); diff --git a/tests/e2e/browser-cases/basic-react/rspack.config.js b/tests/e2e/browser-cases/basic-react/rspack.config.js new file mode 100644 index 000000000000..0be1285f81d4 --- /dev/null +++ b/tests/e2e/browser-cases/basic-react/rspack.config.js @@ -0,0 +1,25 @@ +const rspack = require('@rspack/core'); + +/** @type {import("@rspack/core").Configuration} */ +module.exports = { + entry: './src/index.js', + context: __dirname, + mode: 'development', + plugins: [new rspack.HtmlRspackPlugin()], + module: { + rules: [ + { + test: /\.js$/, + exclude: [/node_modules/], + include: [/src/], + loader: 'builtin:swc-loader', + }, + ], + }, + devServer: { + headers: { + 'Cross-Origin-Opener-Policy': 'same-origin', + 'Cross-Origin-Embedder-Policy': 'require-corp', + }, + }, +}; diff --git a/tests/e2e/browser-cases/basic-react/src/files.js b/tests/e2e/browser-cases/basic-react/src/files.js new file mode 100644 index 000000000000..71aaffcdec2f --- /dev/null +++ b/tests/e2e/browser-cases/basic-react/src/files.js @@ -0,0 +1,213 @@ +import { BrowserHttpImportEsmPlugin } from '@rspack/browser'; + +export const files = { + './src/assets/react.svg': ``, + './src/main.jsx': `import React from "react"; +import ReactDOM from "react-dom/client"; +import App from "./App"; +import "./index.css"; + +ReactDOM.createRoot(document.getElementById("root")).render( + + + +); +`, + './src/index.css': `:root { + font-family: Inter, Avenir, Helvetica, Arial, sans-serif; + font-size: 16px; + line-height: 24px; + font-weight: 400; + + color-scheme: light dark; + color: rgba(255, 255, 255, 0.87); + background-color: #242424; + + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + -webkit-text-size-adjust: 100%; +} + +a { + font-weight: 500; + color: #646cff; + text-decoration: inherit; +} +a:hover { + color: #535bf2; +} + +body { + margin: 0; + display: flex; + place-items: center; + min-width: 320px; + min-height: 100vh; +} + +h1 { + font-size: 3.2em; + line-height: 1.1; +} + +button { + border-radius: 8px; + border: 1px solid transparent; + padding: 0.6em 1.2em; + font-size: 1em; + font-weight: 500; + font-family: inherit; + background-color: #1a1a1a; + cursor: pointer; + transition: border-color 0.25s; +} +button:hover { + border-color: #646cff; +} +button:focus, +button:focus-visible { + outline: 4px auto -webkit-focus-ring-color; +} + +@media (prefers-color-scheme: light) { + :root { + color: #213547; + background-color: #ffffff; + } + a:hover { + color: #747bff; + } + button { + background-color: #f9f9f9; + } +} +`, + './src/App.jsx': `import React from "react"; +import { useState } from "react"; +import reactLogo from "./assets/react.svg"; +import "./App.css"; + +function App() { + const [count, setCount] = useState(0); + + return ( +
+ +

Rspack + React

+
+ +

+ Edit src/App.jsx and save to test HMR +

+
+

+ Click on the Rspack and React logos to learn more +

+
+ ); +} + +export default App; +`, + './src/App.css': `#root { + max-width: 1280px; + margin: 0 auto; + padding: 2rem; + text-align: center; +} + +.logo { + height: 6em; + padding: 1.5em; + will-change: filter; +} +.logo:hover { + filter: drop-shadow(0 0 2em #646cffaa); +} +.logo.react:hover { + filter: drop-shadow(0 0 2em #61dafbaa); +} + +@keyframes logo-spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} + +@media (prefers-reduced-motion: no-preference) { + a > .logo { + animation: logo-spin infinite 20s linear; + } +} + +.card { + padding: 2em; +} + +.read-the-docs { + color: #888; +} +`, +}; + +export const config = { + mode: 'development', + devtool: false, + entry: './src/main.jsx', + resolve: { + extensions: ['.js', '.jsx', '.json'], + }, + module: { + rules: [ + { + test: /\.jsx$/, + use: { + loader: 'builtin:swc-loader', + options: { + jsc: { + parser: { + syntax: 'ecmascript', + jsx: true, + }, + transform: { + react: { + pragma: 'React.createElement', + pragmaFrag: 'React.Fragment', + throwIfNamespace: true, + development: false, + }, + }, + }, + }, + }, + type: 'javascript/auto', + }, + { + test: /\.(png|svg|jpg)$/, + type: 'asset/resource', + }, + ], + }, + plugins: [ + new BrowserHttpImportEsmPlugin({ + domain: 'https://esm.sh', + }), + ], + experiments: { + css: true, + buildHttp: { + allowedUris: ['https://'], + }, + }, +}; diff --git a/tests/e2e/browser-cases/basic-react/src/index.js b/tests/e2e/browser-cases/basic-react/src/index.js new file mode 100644 index 000000000000..765bc499eb55 --- /dev/null +++ b/tests/e2e/browser-cases/basic-react/src/index.js @@ -0,0 +1,20 @@ +import { rspack, builtinMemFs } from '@rspack/browser'; +import { files, config } from './files'; + +builtinMemFs.volume.fromJSON({ + ...files, +}); + +const promise = new Promise((resolve) => { + rspack(config, () => { + const json = builtinMemFs.volume.toJSON(); + + const outputDOM = document.createElement('div'); + outputDOM.id = 'output'; + outputDOM.innerHTML = json['/dist/main.js']; + document.body.appendChild(outputDOM); + resolve(); + }); +}); + +await promise; diff --git a/tests/e2e/package.json b/tests/e2e/package.json index 69d3b0601d72..cbd3de6a195b 100644 --- a/tests/e2e/package.json +++ b/tests/e2e/package.json @@ -12,6 +12,7 @@ "@playwright/test": "1.57.0", "core-js": "3.47.0", "@rspack/core": "workspace:*", + "@rspack/browser": "workspace:*", "@rspack/dev-server": "~1.1.5", "@rspack/plugin-react-refresh": "^1.6.0", "@swc/helpers": "0.5.18", diff --git a/tests/e2e/playwright.config.ts b/tests/e2e/playwright.config.ts index d3c7b7a9782e..7ba417d1c2ef 100644 --- a/tests/e2e/playwright.config.ts +++ b/tests/e2e/playwright.config.ts @@ -5,7 +5,7 @@ const TIMEOUT = 60 * 1000; export default defineConfig({ // Look for test files in the "fixtures" directory, relative to this configuration file. - testDir: './cases', + testDir: process.env.WASM ? './browser-cases' : './cases', // globalSetup: require.resolve("./scripts/globalSetup"), diff --git a/tests/e2e/tsconfig.json b/tests/e2e/tsconfig.json index f08a76f1ce7f..dea9f7fd0e50 100644 --- a/tests/e2e/tsconfig.json +++ b/tests/e2e/tsconfig.json @@ -1,6 +1,13 @@ { "extends": "../../tsconfig.base.json", - "include": ["custom.d.ts", "./scripts", "./fixtures", "./cases", "./utils"], + "include": [ + "custom.d.ts", + "./scripts", + "./fixtures", + "./cases", + "./browser-cases", + "./utils" + ], "compilerOptions": { "strict": true, "baseUrl": ".", From ce291859c99a842b95d917e06e21742bf495aa6e Mon Sep 17 00:00:00 2001 From: "zhanghang.heal" Date: Mon, 19 Jan 2026 14:12:28 +0800 Subject: [PATCH 75/87] fix: update shared global name --- crates/node_binding/rspack.wasi-browser.js | 61 +------------------ crates/node_binding/rspack.wasi.cjs | 61 +------------------ .../src/sharing/IndependentSharedPlugin.ts | 7 +-- .../sharing/reshake-share/index.js | 4 +- 4 files changed, 5 insertions(+), 128 deletions(-) diff --git a/crates/node_binding/rspack.wasi-browser.js b/crates/node_binding/rspack.wasi-browser.js index e3e5c0a99d48..ee65959b37bc 100644 --- a/crates/node_binding/rspack.wasi-browser.js +++ b/crates/node_binding/rspack.wasi-browser.js @@ -63,63 +63,4 @@ const { }, }) export default __napiModule.exports -export const Assets = __napiModule.exports.Assets -export const AsyncDependenciesBlock = __napiModule.exports.AsyncDependenciesBlock -export const Chunk = __napiModule.exports.Chunk -export const ChunkGraph = __napiModule.exports.ChunkGraph -export const ChunkGroup = __napiModule.exports.ChunkGroup -export const Chunks = __napiModule.exports.Chunks -export const CodeGenerationResult = __napiModule.exports.CodeGenerationResult -export const CodeGenerationResults = __napiModule.exports.CodeGenerationResults -export const ConcatenatedModule = __napiModule.exports.ConcatenatedModule -export const ContextModule = __napiModule.exports.ContextModule -export const Dependency = __napiModule.exports.Dependency -export const Diagnostics = __napiModule.exports.Diagnostics -export const EntryDataDto = __napiModule.exports.EntryDataDto -export const EntryDataDTO = __napiModule.exports.EntryDataDTO -export const EntryDependency = __napiModule.exports.EntryDependency -export const EntryOptionsDto = __napiModule.exports.EntryOptionsDto -export const EntryOptionsDTO = __napiModule.exports.EntryOptionsDTO -export const ExternalModule = __napiModule.exports.ExternalModule -export const JsCompilation = __napiModule.exports.JsCompilation -export const JsCompiler = __napiModule.exports.JsCompiler -export const JsContextModuleFactoryAfterResolveData = __napiModule.exports.JsContextModuleFactoryAfterResolveData -export const JsContextModuleFactoryBeforeResolveData = __napiModule.exports.JsContextModuleFactoryBeforeResolveData -export const JsDependencies = __napiModule.exports.JsDependencies -export const JsEntries = __napiModule.exports.JsEntries -export const JsExportsInfo = __napiModule.exports.JsExportsInfo -export const JsModuleGraph = __napiModule.exports.JsModuleGraph -export const JsResolver = __napiModule.exports.JsResolver -export const JsResolverFactory = __napiModule.exports.JsResolverFactory -export const JsStats = __napiModule.exports.JsStats -export const KnownBuildInfo = __napiModule.exports.KnownBuildInfo -export const Module = __napiModule.exports.Module -export const ModuleGraphConnection = __napiModule.exports.ModuleGraphConnection -export const NativeWatcher = __napiModule.exports.NativeWatcher -export const NativeWatchResult = __napiModule.exports.NativeWatchResult -export const NormalModule = __napiModule.exports.NormalModule -export const RawExternalItemFnCtx = __napiModule.exports.RawExternalItemFnCtx -export const ReadonlyResourceData = __napiModule.exports.ReadonlyResourceData -export const ResolverFactory = __napiModule.exports.ResolverFactory -export const Sources = __napiModule.exports.Sources -export const VirtualFileStore = __napiModule.exports.VirtualFileStore -export const JsVirtualFileStore = __napiModule.exports.JsVirtualFileStore -export const async = __napiModule.exports.async -export const BuiltinPluginName = __napiModule.exports.BuiltinPluginName -export const cleanupGlobalTrace = __napiModule.exports.cleanupGlobalTrace -export const EnforceExtension = __napiModule.exports.EnforceExtension -export const EXPECTED_RSPACK_CORE_VERSION = __napiModule.exports.EXPECTED_RSPACK_CORE_VERSION -export const formatDiagnostic = __napiModule.exports.formatDiagnostic -export const JsLoaderState = __napiModule.exports.JsLoaderState -export const JsRspackSeverity = __napiModule.exports.JsRspackSeverity -export const loadBrowserslist = __napiModule.exports.loadBrowserslist -export const minify = __napiModule.exports.minify -export const minifySync = __napiModule.exports.minifySync -export const RawJavascriptParserCommonjsExports = __napiModule.exports.RawJavascriptParserCommonjsExports -export const RawRuleSetConditionType = __napiModule.exports.RawRuleSetConditionType -export const registerGlobalTrace = __napiModule.exports.registerGlobalTrace -export const RegisterJsTapKind = __napiModule.exports.RegisterJsTapKind -export const sync = __napiModule.exports.sync -export const syncTraceEvent = __napiModule.exports.syncTraceEvent -export const transform = __napiModule.exports.transform -export const transformSync = __napiModule.exports.transformSync + diff --git a/crates/node_binding/rspack.wasi.cjs b/crates/node_binding/rspack.wasi.cjs index a251ce4d0d7d..1ad96db4aac4 100644 --- a/crates/node_binding/rspack.wasi.cjs +++ b/crates/node_binding/rspack.wasi.cjs @@ -108,63 +108,4 @@ const { instance: __napiInstance, module: __wasiModule, napiModule: __napiModule }, }) module.exports = __napiModule.exports -module.exports.Assets = __napiModule.exports.Assets -module.exports.AsyncDependenciesBlock = __napiModule.exports.AsyncDependenciesBlock -module.exports.Chunk = __napiModule.exports.Chunk -module.exports.ChunkGraph = __napiModule.exports.ChunkGraph -module.exports.ChunkGroup = __napiModule.exports.ChunkGroup -module.exports.Chunks = __napiModule.exports.Chunks -module.exports.CodeGenerationResult = __napiModule.exports.CodeGenerationResult -module.exports.CodeGenerationResults = __napiModule.exports.CodeGenerationResults -module.exports.ConcatenatedModule = __napiModule.exports.ConcatenatedModule -module.exports.ContextModule = __napiModule.exports.ContextModule -module.exports.Dependency = __napiModule.exports.Dependency -module.exports.Diagnostics = __napiModule.exports.Diagnostics -module.exports.EntryDataDto = __napiModule.exports.EntryDataDto -module.exports.EntryDataDTO = __napiModule.exports.EntryDataDTO -module.exports.EntryDependency = __napiModule.exports.EntryDependency -module.exports.EntryOptionsDto = __napiModule.exports.EntryOptionsDto -module.exports.EntryOptionsDTO = __napiModule.exports.EntryOptionsDTO -module.exports.ExternalModule = __napiModule.exports.ExternalModule -module.exports.JsCompilation = __napiModule.exports.JsCompilation -module.exports.JsCompiler = __napiModule.exports.JsCompiler -module.exports.JsContextModuleFactoryAfterResolveData = __napiModule.exports.JsContextModuleFactoryAfterResolveData -module.exports.JsContextModuleFactoryBeforeResolveData = __napiModule.exports.JsContextModuleFactoryBeforeResolveData -module.exports.JsDependencies = __napiModule.exports.JsDependencies -module.exports.JsEntries = __napiModule.exports.JsEntries -module.exports.JsExportsInfo = __napiModule.exports.JsExportsInfo -module.exports.JsModuleGraph = __napiModule.exports.JsModuleGraph -module.exports.JsResolver = __napiModule.exports.JsResolver -module.exports.JsResolverFactory = __napiModule.exports.JsResolverFactory -module.exports.JsStats = __napiModule.exports.JsStats -module.exports.KnownBuildInfo = __napiModule.exports.KnownBuildInfo -module.exports.Module = __napiModule.exports.Module -module.exports.ModuleGraphConnection = __napiModule.exports.ModuleGraphConnection -module.exports.NativeWatcher = __napiModule.exports.NativeWatcher -module.exports.NativeWatchResult = __napiModule.exports.NativeWatchResult -module.exports.NormalModule = __napiModule.exports.NormalModule -module.exports.RawExternalItemFnCtx = __napiModule.exports.RawExternalItemFnCtx -module.exports.ReadonlyResourceData = __napiModule.exports.ReadonlyResourceData -module.exports.ResolverFactory = __napiModule.exports.ResolverFactory -module.exports.Sources = __napiModule.exports.Sources -module.exports.VirtualFileStore = __napiModule.exports.VirtualFileStore -module.exports.JsVirtualFileStore = __napiModule.exports.JsVirtualFileStore -module.exports.async = __napiModule.exports.async -module.exports.BuiltinPluginName = __napiModule.exports.BuiltinPluginName -module.exports.cleanupGlobalTrace = __napiModule.exports.cleanupGlobalTrace -module.exports.EnforceExtension = __napiModule.exports.EnforceExtension -module.exports.EXPECTED_RSPACK_CORE_VERSION = __napiModule.exports.EXPECTED_RSPACK_CORE_VERSION -module.exports.formatDiagnostic = __napiModule.exports.formatDiagnostic -module.exports.JsLoaderState = __napiModule.exports.JsLoaderState -module.exports.JsRspackSeverity = __napiModule.exports.JsRspackSeverity -module.exports.loadBrowserslist = __napiModule.exports.loadBrowserslist -module.exports.minify = __napiModule.exports.minify -module.exports.minifySync = __napiModule.exports.minifySync -module.exports.RawJavascriptParserCommonjsExports = __napiModule.exports.RawJavascriptParserCommonjsExports -module.exports.RawRuleSetConditionType = __napiModule.exports.RawRuleSetConditionType -module.exports.registerGlobalTrace = __napiModule.exports.registerGlobalTrace -module.exports.RegisterJsTapKind = __napiModule.exports.RegisterJsTapKind -module.exports.sync = __napiModule.exports.sync -module.exports.syncTraceEvent = __napiModule.exports.syncTraceEvent -module.exports.transform = __napiModule.exports.transform -module.exports.transformSync = __napiModule.exports.transformSync + diff --git a/packages/rspack/src/sharing/IndependentSharedPlugin.ts b/packages/rspack/src/sharing/IndependentSharedPlugin.ts index cd0e71001462..0775146d67d6 100644 --- a/packages/rspack/src/sharing/IndependentSharedPlugin.ts +++ b/packages/rspack/src/sharing/IndependentSharedPlugin.ts @@ -201,11 +201,6 @@ export class IndependentSharedPlugin { runCount++; }); - // clean hooks - compiler.hooks.shutdown.tapAsync('IndependentSharedPlugin', (callback) => { - callback(); - }); - // inject buildAssets to stats if (manifest) { compiler.hooks.compilation.tap( @@ -346,7 +341,7 @@ export class IndependentSharedPlugin { }); } else { extraPlugin = new SharedContainerPlugin({ - mfName, + mfName: `${mfName}_${treeShaking ? 't' : 'f'}`, library, ...extraOptions.currentShare, }); diff --git a/tests/rspack-test/configCases/sharing/reshake-share/index.js b/tests/rspack-test/configCases/sharing/reshake-share/index.js index 1f2f88d31ef2..243bcb1b2050 100644 --- a/tests/rspack-test/configCases/sharing/reshake-share/index.js +++ b/tests/rspack-test/configCases/sharing/reshake-share/index.js @@ -36,7 +36,7 @@ it("should build independent share file", () => { }); it("secondary tree shaking shared container should only have specify usedExports", async () => { - const uiLibDepShareContainerModule = __non_webpack_require__(uiLibDepShareContainerPath).secondary_tree_shaking_share_ui_lib_dep_100; + const uiLibDepShareContainerModule = __non_webpack_require__(uiLibDepShareContainerPath).secondary_tree_shaking_share_t_ui_lib_dep_100; await uiLibDepShareContainerModule.init({},{ installInitialConsumes: async ()=>{ return 'call init' @@ -50,7 +50,7 @@ it("secondary tree shaking shared container should only have specify usedExports it("correct handle share dep while secondary tree shaking", async () => { - const uiLibShareContainerModule = __non_webpack_require__(uiLibShareContainerPath).secondary_tree_shaking_share_ui_lib_100; + const uiLibShareContainerModule = __non_webpack_require__(uiLibShareContainerPath).secondary_tree_shaking_share_t_ui_lib_100; await uiLibShareContainerModule.init({},{ installInitialConsumes: async ({webpackRequire})=>{ webpackRequire.m['webpack/sharing/consume/default/ui-lib-dep'] = (m)=>{ From 3282b3d5312a504609127a301417605941674841 Mon Sep 17 00:00:00 2001 From: "zhanghang.heal" Date: Wed, 21 Jan 2026 21:42:12 +0800 Subject: [PATCH 76/87] perf: reuse container plugin --- .../src/raw_options/raw_builtins/raw_mf.rs | 2 +- .../container/container_entry_dependency.rs | 30 +- .../src/container/container_entry_module.rs | 222 +++++++++++++-- .../container_entry_module_factory.rs | 34 ++- .../container/container_exposed_dependency.rs | 16 +- crates/rspack_plugin_mf/src/lib.rs | 1 - crates/rspack_plugin_mf/src/sharing/mod.rs | 4 - .../sharing/shared_container_dependency.rs | 71 ----- .../shared_container_entry_dependency.rs | 78 ----- .../sharing/shared_container_entry_module.rs | 268 ------------------ .../shared_container_entry_module_factory.rs | 26 -- .../src/sharing/shared_container_plugin.rs | 14 +- .../shared_used_exports_optimizer_plugin.rs | 54 ++-- 13 files changed, 287 insertions(+), 533 deletions(-) delete mode 100644 crates/rspack_plugin_mf/src/sharing/shared_container_dependency.rs delete mode 100644 crates/rspack_plugin_mf/src/sharing/shared_container_entry_dependency.rs delete mode 100644 crates/rspack_plugin_mf/src/sharing/shared_container_entry_module.rs delete mode 100644 crates/rspack_plugin_mf/src/sharing/shared_container_entry_module_factory.rs diff --git a/crates/rspack_binding_api/src/raw_options/raw_builtins/raw_mf.rs b/crates/rspack_binding_api/src/raw_options/raw_builtins/raw_mf.rs index 292a195bcac7..ca70e07ef396 100644 --- a/crates/rspack_binding_api/src/raw_options/raw_builtins/raw_mf.rs +++ b/crates/rspack_binding_api/src/raw_options/raw_builtins/raw_mf.rs @@ -7,7 +7,7 @@ use rspack_plugin_mf::{ ContainerPluginOptions, ContainerReferencePluginOptions, ExposeOptions, ManifestExposeOption, ManifestSharedOption, ModuleFederationManifestPluginOptions, ModuleFederationRuntimePluginOptions, OptimizeSharedConfig, ProvideOptions, ProvideVersion, - RemoteAliasTarget, RemoteOptions, ShareContainerEntryOptions, SharedContainerPluginOptions, + RemoteAliasTarget, RemoteOptions, SharedContainerPluginOptions, SharedUsedExportsOptimizerPluginOptions, StatsBuildInfo, }; diff --git a/crates/rspack_plugin_mf/src/container/container_entry_dependency.rs b/crates/rspack_plugin_mf/src/container/container_entry_dependency.rs index 276da8957b39..11600e882f47 100644 --- a/crates/rspack_plugin_mf/src/container/container_entry_dependency.rs +++ b/crates/rspack_plugin_mf/src/container/container_entry_dependency.rs @@ -13,8 +13,11 @@ pub struct ContainerEntryDependency { pub name: String, pub exposes: Vec<(String, ExposeOptions)>, pub share_scope: String, + pub request: Option, + pub version: Option, resource_identifier: ResourceIdentifier, pub(crate) enhanced: bool, + dependency_type: DependencyType, factorize_info: FactorizeInfo, } @@ -31,8 +34,27 @@ impl ContainerEntryDependency { name, exposes, share_scope, + request: None, + version: None, resource_identifier, enhanced, + dependency_type: DependencyType::ContainerEntry, + factorize_info: Default::default(), + } + } + + pub fn new_share_container_entry(name: String, request: String, version: String) -> Self { + let resource_identifier = format!("share-container-entry-{}", &name).into(); + Self { + id: DependencyId::new(), + name, + exposes: vec![], + share_scope: String::new(), + request: Some(request), + version: Some(version), + resource_identifier, + enhanced: false, + dependency_type: DependencyType::ShareContainerEntry, factorize_info: Default::default(), } } @@ -49,7 +71,7 @@ impl Dependency for ContainerEntryDependency { } fn dependency_type(&self) -> &DependencyType { - &DependencyType::ContainerEntry + &self.dependency_type } fn resource_identifier(&self) -> Option<&str> { @@ -64,7 +86,11 @@ impl Dependency for ContainerEntryDependency { #[cacheable_dyn] impl ModuleDependency for ContainerEntryDependency { fn request(&self) -> &str { - &self.resource_identifier + if self.dependency_type == DependencyType::ShareContainerEntry { + self.request.as_deref().unwrap_or_default() + } else { + &self.resource_identifier + } } fn factorize_info(&self) -> &FactorizeInfo { diff --git a/crates/rspack_plugin_mf/src/container/container_entry_module.rs b/crates/rspack_plugin_mf/src/container/container_entry_module.rs index 66ec0e9dd74a..98c88c6e2b9d 100644 --- a/crates/rspack_plugin_mf/src/container/container_entry_module.rs +++ b/crates/rspack_plugin_mf/src/container/container_entry_module.rs @@ -7,9 +7,10 @@ use rspack_core::{ AsyncDependenciesBlock, AsyncDependenciesBlockIdentifier, BoxDependency, BuildContext, BuildInfo, BuildMeta, BuildMetaExportsType, BuildResult, ChunkGroupOptions, CodeGenerationResult, Compilation, ConcatenationScope, Context, DependenciesBlock, Dependency, DependencyId, - FactoryMeta, GroupOptions, LibIdentOptions, Module, ModuleDependency, ModuleGraph, - ModuleIdentifier, ModuleType, RuntimeGlobals, RuntimeSpec, SourceType, StaticExportsDependency, - StaticExportsSpec, impl_module_meta_info, impl_source_map_config, module_update_hash, + DependencyType, FactoryMeta, GroupOptions, LibIdentOptions, Module, ModuleDependency, + ModuleGraph, ModuleIdentifier, ModuleType, RuntimeGlobals, RuntimeSpec, SourceType, + StaticExportsDependency, StaticExportsSpec, impl_module_meta_info, impl_source_map_config, + module_update_hash, rspack_sources::{BoxSource, RawStringSource, SourceExt}, }; use rspack_error::{Result, impl_empty_diagnosable_trait}; @@ -36,6 +37,10 @@ pub struct ContainerEntryModule { build_info: BuildInfo, build_meta: BuildMeta, enhanced: bool, + request: Option, + version: Option, + dependency_type: DependencyType, + name: String, } impl ContainerEntryModule { @@ -67,14 +72,50 @@ impl ContainerEntryModule { exports_type: BuildMetaExportsType::Namespace, ..Default::default() }, - source_map_kind: SourceMapKind::empty(), enhanced, + request: None, + version: None, + dependency_type: DependencyType::ContainerEntry, + source_map_kind: SourceMapKind::empty(), + name, + } + } + + pub fn new_share_container_entry(name: String, request: String, version: String) -> Self { + let lib_ident = format!("webpack/share/container/{}", &name); + Self { + blocks: Vec::new(), + dependencies: Vec::new(), + identifier: ModuleIdentifier::from(format!("share container entry {}@{}", &name, &version,)), + lib_ident, + exposes: vec![], + share_scope: String::new(), + factory_meta: None, + build_info: BuildInfo { + strict: true, + top_level_declarations: Some(FxHashSet::default()), + ..Default::default() + }, + build_meta: BuildMeta { + exports_type: BuildMetaExportsType::Namespace, + ..Default::default() + }, + enhanced: false, + request: Some(request), + version: Some(version), + dependency_type: DependencyType::ShareContainerEntry, + source_map_kind: SourceMapKind::empty(), + name, } } pub fn exposes(&self) -> &[(String, ExposeOptions)] { &self.exposes } + + pub fn name(&self) -> &str { + &self.name + } } impl Identifiable for ContainerEntryModule { @@ -115,7 +156,11 @@ impl Module for ContainerEntryModule { } fn module_type(&self) -> &ModuleType { - &ModuleType::JsDynamic + if self.dependency_type == DependencyType::ShareContainerEntry { + &ModuleType::ShareContainerShared + } else { + &ModuleType::JsDynamic + } } fn source_types(&self, _module_graph: &ModuleGraph) -> &[SourceType] { @@ -127,7 +172,11 @@ impl Module for ContainerEntryModule { } fn readable_identifier(&self, _context: &Context) -> Cow<'_, str> { - "container entry".into() + if self.dependency_type == DependencyType::ShareContainerEntry { + "share container entry".into() + } else { + "container entry".into() + } } fn lib_ident(&self, _options: LibIdentOptions) -> Option> { @@ -141,32 +190,49 @@ impl Module for ContainerEntryModule { ) -> Result { let mut blocks = vec![]; let mut dependencies: Vec = vec![]; - for (name, options) in &self.exposes { - let mut block = AsyncDependenciesBlock::new( - self.identifier, - None, - Some(name), - options - .import - .iter() - .map(|request| { - Box::new(ContainerExposedDependency::new( - name.clone(), - request.clone(), - )) as Box - }) - .collect(), - None, - ); - block.set_group_options(GroupOptions::ChunkGroup( - ChunkGroupOptions::default().name_optional(options.name.clone()), - )); - blocks.push(Box::new(block)); + + if self.dependency_type == DependencyType::ShareContainerEntry { + // Shared Container logic + dependencies.push(Box::new(StaticExportsDependency::new( + StaticExportsSpec::Array(vec!["get".into(), "init".into()]), + false, + ))); + if let Some(request) = &self.request { + let dep = ContainerExposedDependency::new_shared_fallback(request.clone()); + dependencies.push(Box::new(dep)); + } + } else { + // Container logic + for (name, options) in &self.exposes { + let mut block = AsyncDependenciesBlock::new( + self.identifier, + None, + Some(name), + options + .import + .iter() + .map(|request| { + Box::new(ContainerExposedDependency::new( + name.clone(), + request.clone(), + )) as Box + }) + .collect(), + None, + ); + block.set_group_options(GroupOptions::ChunkGroup( + ChunkGroupOptions::default().name_optional(options.name.clone()), + )); + blocks.push(Box::new(block)); + } + dependencies.push(Box::new(StaticExportsDependency::new( + StaticExportsSpec::Array(vec!["get".into(), "init".into()]), + false, + ))); } - dependencies.push(Box::new(StaticExportsDependency::new( - StaticExportsSpec::Array(vec!["get".into(), "init".into()]), - false, - ))); + + // I need `name` for SharedContainer logic. + // I will add `name` field to struct. Ok(BuildResult { dependencies, @@ -192,6 +258,100 @@ impl Module for ContainerEntryModule { code_generation_result .runtime_requirements .insert(RuntimeGlobals::REQUIRE); + + if self.dependency_type == DependencyType::ShareContainerEntry { + let module_graph = compilation.get_module_graph(); + let mut factory = String::new(); + for dependency_id in self.get_dependencies() { + let dependency = module_graph.dependency_by_id(dependency_id); + if let Some(dependency) = dependency + .as_any() + .downcast_ref::() + { + if *dependency.dependency_type() == DependencyType::ShareContainerFallback { + let request: &str = dependency.user_request(); + let module_expr = compilation.runtime_template.module_raw( + compilation, + &mut code_generation_result.runtime_requirements, + dependency_id, + request, + false, + ); + factory = compilation + .runtime_template + .returning_function(&module_expr, ""); + } + } + } + + let federation_global = format!( + "{}.federation", + compilation + .runtime_template + .render_runtime_globals(&RuntimeGlobals::REQUIRE) + ); + + // Generate installInitialConsumes function using returning_function + let install_initial_consumes_call = r#"localBundlerRuntime.installInitialConsumes({ + installedModules: localInstalledModules, + initialConsumes: __webpack_require__.consumesLoadingData.initialConsumes, + moduleToHandlerMapping: __webpack_require__.federation.consumesLoadingModuleToHandlerMapping || {}, + webpackRequire: __webpack_require__, + asyncLoad: true + })"#; + let install_initial_consumes_fn = compilation + .runtime_template + .returning_function(install_initial_consumes_call, ""); + + // Create initShareContainer function using basic_function, supporting multi-statement body + let init_body = format!( + r#" + var installedModules = {{}}; + {federation_global}.instance = mfInstance; + {federation_global}.bundlerRuntime = bundlerRuntime; + + // Save parameters to local variables to avoid closure issues + var localBundlerRuntime = bundlerRuntime; + var localInstalledModules = installedModules; + + if(!__webpack_require__.consumesLoadingData){{return; }} + {federation_global}.installInitialConsumes = {install_initial_consumes_fn}; + + return {federation_global}.installInitialConsumes(); + "#, + federation_global = federation_global, + install_initial_consumes_fn = install_initial_consumes_fn + ); + let init_share_container_fn = compilation + .runtime_template + .basic_function("mfInstance, bundlerRuntime", &init_body); + + // Generate the final source string + let source = format!( + r#" + __webpack_require__.federation = {{ instance: undefined,bundlerRuntime: undefined }} + var factory = ()=>{factory}; + var initShareContainer = {init_share_container_fn}; + {runtime}(exports, {{ + get: function() {{ return factory;}}, + init: function() {{ return initShareContainer;}} + }}); + "#, + runtime = compilation + .runtime_template + .render_runtime_globals(&RuntimeGlobals::DEFINE_PROPERTY_GETTERS), + factory = factory, + init_share_container_fn = init_share_container_fn + ); + + // Update the code generation result with the generated source + code_generation_result = + code_generation_result.with_javascript(RawStringSource::from(source).boxed()); + code_generation_result.add(SourceType::Expose, RawStringSource::from_static("").boxed()); + return Ok(code_generation_result); + } + + // Normal Container Logic code_generation_result .runtime_requirements .insert(RuntimeGlobals::CURRENT_REMOTE_GET_SCOPE); diff --git a/crates/rspack_plugin_mf/src/container/container_entry_module_factory.rs b/crates/rspack_plugin_mf/src/container/container_entry_module_factory.rs index d0f348dae927..8b54667082f8 100644 --- a/crates/rspack_plugin_mf/src/container/container_entry_module_factory.rs +++ b/crates/rspack_plugin_mf/src/container/container_entry_module_factory.rs @@ -1,5 +1,8 @@ use async_trait::async_trait; -use rspack_core::{ModuleExt, ModuleFactory, ModuleFactoryCreateData, ModuleFactoryResult}; +use rspack_core::{ + Dependency, DependencyType, ModuleExt, ModuleFactory, ModuleFactoryCreateData, + ModuleFactoryResult, +}; use rspack_error::Result; use super::{ @@ -16,14 +19,25 @@ impl ModuleFactory for ContainerEntryModuleFactory { let dep = data.dependencies[0] .downcast_ref::() .expect("dependency of ContainerEntryModuleFactory should be ContainerEntryDependency"); - Ok(ModuleFactoryResult::new_with_module( - ContainerEntryModule::new( - dep.name.clone(), - dep.exposes.clone(), - dep.share_scope.clone(), - dep.enhanced, - ) - .boxed(), - )) + if *dep.dependency_type() == DependencyType::ShareContainerEntry { + Ok(ModuleFactoryResult::new_with_module( + ContainerEntryModule::new_share_container_entry( + dep.name.clone(), + dep.request.clone().expect("should have request"), + dep.version.clone().expect("should have version"), + ) + .boxed(), + )) + } else { + Ok(ModuleFactoryResult::new_with_module( + ContainerEntryModule::new( + dep.name.clone(), + dep.exposes.clone(), + dep.share_scope.clone(), + dep.enhanced, + ) + .boxed(), + )) + } } } diff --git a/crates/rspack_plugin_mf/src/container/container_exposed_dependency.rs b/crates/rspack_plugin_mf/src/container/container_exposed_dependency.rs index 729792bf3622..789d76ed39d3 100644 --- a/crates/rspack_plugin_mf/src/container/container_exposed_dependency.rs +++ b/crates/rspack_plugin_mf/src/container/container_exposed_dependency.rs @@ -11,6 +11,7 @@ pub struct ContainerExposedDependency { request: String, pub exposed_name: String, resource_identifier: ResourceIdentifier, + dependency_type: DependencyType, factorize_info: FactorizeInfo, } @@ -22,6 +23,19 @@ impl ContainerExposedDependency { request, exposed_name, resource_identifier, + dependency_type: DependencyType::ContainerExposed, + factorize_info: Default::default(), + } + } + + pub fn new_shared_fallback(request: String) -> Self { + let resource_identifier = format!("share-container-fallback:{}", request).into(); + Self { + id: DependencyId::new(), + request, + exposed_name: String::new(), + resource_identifier, + dependency_type: DependencyType::ShareContainerFallback, factorize_info: Default::default(), } } @@ -38,7 +52,7 @@ impl Dependency for ContainerExposedDependency { } fn dependency_type(&self) -> &DependencyType { - &DependencyType::ContainerExposed + &self.dependency_type } fn resource_identifier(&self) -> Option<&str> { diff --git a/crates/rspack_plugin_mf/src/lib.rs b/crates/rspack_plugin_mf/src/lib.rs index e2422e90e8bd..594e6485d27c 100644 --- a/crates/rspack_plugin_mf/src/lib.rs +++ b/crates/rspack_plugin_mf/src/lib.rs @@ -27,7 +27,6 @@ pub use sharing::{ CodeGenerationDataShareInit, DataInitStage, ShareInitData, ShareRuntimeModule, }, share_runtime_plugin::ShareRuntimePlugin, - shared_container_entry_dependency::ShareContainerEntryOptions, shared_container_plugin::{SharedContainerPlugin, SharedContainerPluginOptions}, shared_used_exports_optimizer_plugin::{ OptimizeSharedConfig, SharedUsedExportsOptimizerPlugin, SharedUsedExportsOptimizerPluginOptions, diff --git a/crates/rspack_plugin_mf/src/sharing/mod.rs b/crates/rspack_plugin_mf/src/sharing/mod.rs index 606f650bc5f1..941eb4345f82 100644 --- a/crates/rspack_plugin_mf/src/sharing/mod.rs +++ b/crates/rspack_plugin_mf/src/sharing/mod.rs @@ -10,10 +10,6 @@ pub mod provide_shared_module_factory; pub mod provide_shared_plugin; pub mod share_runtime_module; pub mod share_runtime_plugin; -pub mod shared_container_dependency; -pub mod shared_container_entry_dependency; -pub mod shared_container_entry_module; -pub mod shared_container_entry_module_factory; pub mod shared_container_plugin; pub mod shared_container_runtime_module; pub mod shared_used_exports_optimizer_plugin; diff --git a/crates/rspack_plugin_mf/src/sharing/shared_container_dependency.rs b/crates/rspack_plugin_mf/src/sharing/shared_container_dependency.rs deleted file mode 100644 index 81909a2bafed..000000000000 --- a/crates/rspack_plugin_mf/src/sharing/shared_container_dependency.rs +++ /dev/null @@ -1,71 +0,0 @@ -use rspack_cacheable::{cacheable, cacheable_dyn}; -use rspack_core::{ - AsContextDependency, AsDependencyCodeGeneration, Dependency, DependencyCategory, DependencyId, - DependencyType, FactorizeInfo, ModuleDependency, -}; - -#[cacheable] -#[derive(Debug, Clone)] -pub struct SharedContainerDependency { - id: DependencyId, - request: String, - resource_identifier: String, - factorize_info: FactorizeInfo, -} - -impl SharedContainerDependency { - pub fn new(request: String) -> Self { - let resource_identifier = format!("share-container-fallback:{}", request); - Self { - id: DependencyId::new(), - request, - resource_identifier, - factorize_info: Default::default(), - } - } -} - -#[cacheable_dyn] -impl Dependency for SharedContainerDependency { - fn id(&self) -> &DependencyId { - &self.id - } - - fn category(&self) -> &DependencyCategory { - &DependencyCategory::Esm - } - - fn dependency_type(&self) -> &DependencyType { - &DependencyType::ShareContainerFallback - } - - fn resource_identifier(&self) -> Option<&str> { - Some(&self.resource_identifier) - } - - fn could_affect_referencing_module(&self) -> rspack_core::AffectType { - rspack_core::AffectType::True - } -} - -#[cacheable_dyn] -impl ModuleDependency for SharedContainerDependency { - fn request(&self) -> &str { - &self.request - } - - fn user_request(&self) -> &str { - &self.request - } - - fn factorize_info(&self) -> &FactorizeInfo { - &self.factorize_info - } - - fn factorize_info_mut(&mut self) -> &mut FactorizeInfo { - &mut self.factorize_info - } -} - -impl AsContextDependency for SharedContainerDependency {} -impl AsDependencyCodeGeneration for SharedContainerDependency {} diff --git a/crates/rspack_plugin_mf/src/sharing/shared_container_entry_dependency.rs b/crates/rspack_plugin_mf/src/sharing/shared_container_entry_dependency.rs deleted file mode 100644 index 73190d3d86e3..000000000000 --- a/crates/rspack_plugin_mf/src/sharing/shared_container_entry_dependency.rs +++ /dev/null @@ -1,78 +0,0 @@ -use rspack_cacheable::{cacheable, cacheable_dyn}; -use rspack_core::{ - AsContextDependency, AsDependencyCodeGeneration, Dependency, DependencyCategory, DependencyId, - DependencyType, FactorizeInfo, ModuleDependency, -}; -use serde::Serialize; - -#[cacheable] -#[derive(Debug, Clone)] -pub struct SharedContainerEntryDependency { - id: DependencyId, - pub name: String, - pub request: String, - pub version: String, - resource_identifier: String, - factorize_info: FactorizeInfo, -} - -#[cacheable] -#[derive(Debug, Clone, Serialize)] -pub struct ShareContainerEntryOptions { - pub request: String, -} - -impl SharedContainerEntryDependency { - pub fn new(name: String, request: String, version: String) -> Self { - let resource_identifier = format!("share-container-entry-{}", &name); - Self { - id: DependencyId::new(), - name, - request, - version, - resource_identifier, - factorize_info: Default::default(), - } - } -} - -#[cacheable_dyn] -impl Dependency for SharedContainerEntryDependency { - fn id(&self) -> &DependencyId { - &self.id - } - - fn category(&self) -> &DependencyCategory { - &DependencyCategory::Esm - } - - fn dependency_type(&self) -> &DependencyType { - &DependencyType::ShareContainerEntry - } - - fn resource_identifier(&self) -> Option<&str> { - Some(&self.resource_identifier) - } - - fn could_affect_referencing_module(&self) -> rspack_core::AffectType { - rspack_core::AffectType::Transitive - } -} - -#[cacheable_dyn] -impl ModuleDependency for SharedContainerEntryDependency { - fn request(&self) -> &str { - &self.request - } - - fn factorize_info(&self) -> &FactorizeInfo { - &self.factorize_info - } - - fn factorize_info_mut(&mut self) -> &mut FactorizeInfo { - &mut self.factorize_info - } -} - -impl AsContextDependency for SharedContainerEntryDependency {} -impl AsDependencyCodeGeneration for SharedContainerEntryDependency {} diff --git a/crates/rspack_plugin_mf/src/sharing/shared_container_entry_module.rs b/crates/rspack_plugin_mf/src/sharing/shared_container_entry_module.rs deleted file mode 100644 index 3bf9709215e4..000000000000 --- a/crates/rspack_plugin_mf/src/sharing/shared_container_entry_module.rs +++ /dev/null @@ -1,268 +0,0 @@ -use std::borrow::Cow; - -use async_trait::async_trait; -use rspack_cacheable::{cacheable, cacheable_dyn}; -use rspack_collections::{Identifiable, Identifier}; -use rspack_core::{ - AsyncDependenciesBlock, AsyncDependenciesBlockIdentifier, BoxDependency, BuildContext, BuildInfo, - BuildMeta, BuildMetaExportsType, BuildResult, CodeGenerationResult, Compilation, - ConcatenationScope, Context, DependenciesBlock, DependencyId, FactoryMeta, LibIdentOptions, - Module, ModuleDependency, ModuleGraph, ModuleIdentifier, ModuleType, RuntimeGlobals, RuntimeSpec, - SourceType, StaticExportsDependency, StaticExportsSpec, impl_module_meta_info, - module_update_hash, - rspack_sources::{BoxSource, RawStringSource, SourceExt}, -}; -use rspack_error::{Result, impl_empty_diagnosable_trait}; -use rspack_hash::{RspackHash, RspackHashDigest}; -use rspack_util::source_map::{ModuleSourceMapConfig, SourceMapKind}; -use rustc_hash::FxHashSet; - -use super::shared_container_dependency::SharedContainerDependency; - -#[cacheable] -#[derive(Debug)] -pub struct SharedContainerEntryModule { - blocks: Vec, - dependencies: Vec, - identifier: ModuleIdentifier, - lib_ident: String, - name: String, - request: String, - version: String, - factory_meta: Option, - build_info: BuildInfo, - build_meta: BuildMeta, - source_map_kind: SourceMapKind, -} - -impl SharedContainerEntryModule { - pub fn new(name: String, request: String, version: String) -> Self { - let lib_ident = format!("webpack/share/container/{}", &name); - Self { - blocks: Vec::new(), - dependencies: Vec::new(), - identifier: ModuleIdentifier::from(format!("share container entry {}@{}", &name, &version,)), - lib_ident, - name, - request, - version, - factory_meta: None, - build_info: BuildInfo { - strict: true, - top_level_declarations: Some(FxHashSet::default()), - ..Default::default() - }, - build_meta: BuildMeta { - exports_type: BuildMetaExportsType::Namespace, - ..Default::default() - }, - source_map_kind: SourceMapKind::empty(), - } - } -} - -impl Identifiable for SharedContainerEntryModule { - fn identifier(&self) -> Identifier { - self.identifier - } -} - -impl DependenciesBlock for SharedContainerEntryModule { - fn add_block_id(&mut self, block: AsyncDependenciesBlockIdentifier) { - self.blocks.push(block) - } - - fn get_blocks(&self) -> &[AsyncDependenciesBlockIdentifier] { - &self.blocks - } - - fn add_dependency_id(&mut self, dependency: DependencyId) { - self.dependencies.push(dependency) - } - - fn remove_dependency_id(&mut self, dependency: DependencyId) { - self.dependencies.retain(|d| d != &dependency) - } - - fn get_dependencies(&self) -> &[DependencyId] { - &self.dependencies - } -} - -#[cacheable_dyn] -#[async_trait] -impl Module for SharedContainerEntryModule { - impl_module_meta_info!(); - - fn size(&self, _source_type: Option<&SourceType>, _compilation: Option<&Compilation>) -> f64 { - 42.0 - } - - fn module_type(&self) -> &ModuleType { - &ModuleType::ShareContainerShared - } - - fn source_types(&self, _module_graph: &ModuleGraph) -> &[SourceType] { - &[SourceType::JavaScript, SourceType::Expose] - } - - fn source(&self) -> Option<&BoxSource> { - None - } - - fn readable_identifier(&self, _context: &Context) -> Cow<'_, str> { - "share container entry".into() - } - - fn lib_ident(&self, _options: LibIdentOptions) -> Option> { - Some(self.lib_ident.as_str().into()) - } - - async fn build( - &mut self, - _build_context: BuildContext, - _: Option<&Compilation>, - ) -> Result { - let dependencies: Vec = vec![ - Box::new(StaticExportsDependency::new( - StaticExportsSpec::Array(vec!["get".into(), "init".into()]), - false, - )), - Box::new(SharedContainerDependency::new(self.name.clone())), - ]; - - Ok(BuildResult { - dependencies, - blocks: Vec::>::new(), - ..Default::default() - }) - } - - async fn code_generation( - &self, - compilation: &Compilation, - _runtime: Option<&RuntimeSpec>, - _: Option, - ) -> Result { - let mut code_generation_result = CodeGenerationResult::default(); - code_generation_result - .runtime_requirements - .insert(RuntimeGlobals::DEFINE_PROPERTY_GETTERS); - code_generation_result - .runtime_requirements - .insert(RuntimeGlobals::EXPORTS); - code_generation_result - .runtime_requirements - .insert(RuntimeGlobals::REQUIRE); - - let module_graph = compilation.get_module_graph(); - let mut factory = String::new(); - for dependency_id in self.get_dependencies() { - let dependency = module_graph.dependency_by_id(dependency_id); - if let Some(dependency) = dependency - .as_any() - .downcast_ref::() - { - let request: &str = dependency.user_request(); - let module_expr = compilation.runtime_template.module_raw( - compilation, - &mut code_generation_result.runtime_requirements, - dependency_id, - request, - false, - ); - factory = compilation - .runtime_template - .returning_function(&module_expr, ""); - } - } - - let federation_global = format!( - "{}.federation", - compilation - .runtime_template - .render_runtime_globals(&RuntimeGlobals::REQUIRE) - ); - - // Generate installInitialConsumes function using returning_function - let install_initial_consumes_call = r#"localBundlerRuntime.installInitialConsumes({ - installedModules: localInstalledModules, - initialConsumes: __webpack_require__.consumesLoadingData.initialConsumes, - moduleToHandlerMapping: __webpack_require__.federation.consumesLoadingModuleToHandlerMapping || {}, - webpackRequire: __webpack_require__, - asyncLoad: true - })"#; - let install_initial_consumes_fn = compilation - .runtime_template - .returning_function(install_initial_consumes_call, ""); - - // Create initShareContainer function using basic_function, supporting multi-statement body - let init_body = format!( - r#" - var installedModules = {{}}; - {federation_global}.instance = mfInstance; - {federation_global}.bundlerRuntime = bundlerRuntime; - - // Save parameters to local variables to avoid closure issues - var localBundlerRuntime = bundlerRuntime; - var localInstalledModules = installedModules; - - if(!__webpack_require__.consumesLoadingData){{return; }} - {federation_global}.installInitialConsumes = {install_initial_consumes_fn}; - - return {federation_global}.installInitialConsumes(); - "#, - federation_global = federation_global, - install_initial_consumes_fn = install_initial_consumes_fn - ); - let init_share_container_fn = compilation - .runtime_template - .basic_function("mfInstance, bundlerRuntime", &init_body); - - // Generate the final source string - let source = format!( - r#" - __webpack_require__.federation = {{ instance: undefined,bundlerRuntime: undefined }} - var factory = ()=>{factory}; - var initShareContainer = {init_share_container_fn}; -{runtime}(exports, {{ - get: function() {{ return factory;}}, - init: function() {{ return initShareContainer;}} -}}); -"#, - runtime = compilation - .runtime_template - .render_runtime_globals(&RuntimeGlobals::DEFINE_PROPERTY_GETTERS), - factory = factory, - init_share_container_fn = init_share_container_fn - ); - - // Update the code generation result with the generated source - code_generation_result = - code_generation_result.with_javascript(RawStringSource::from(source).boxed()); - code_generation_result.add(SourceType::Expose, RawStringSource::from_static("").boxed()); - Ok(code_generation_result) - } - - async fn get_runtime_hash( - &self, - compilation: &Compilation, - runtime: Option<&RuntimeSpec>, - ) -> Result { - let mut hasher = RspackHash::from(&compilation.options.output); - module_update_hash(self, &mut hasher, compilation, runtime); - Ok(hasher.digest(&compilation.options.output.hash_digest)) - } -} - -impl_empty_diagnosable_trait!(SharedContainerEntryModule); - -impl ModuleSourceMapConfig for SharedContainerEntryModule { - fn get_source_map_kind(&self) -> &SourceMapKind { - &self.source_map_kind - } - - fn set_source_map_kind(&mut self, source_map: SourceMapKind) { - self.source_map_kind = source_map; - } -} diff --git a/crates/rspack_plugin_mf/src/sharing/shared_container_entry_module_factory.rs b/crates/rspack_plugin_mf/src/sharing/shared_container_entry_module_factory.rs deleted file mode 100644 index d7c9d5c6a42c..000000000000 --- a/crates/rspack_plugin_mf/src/sharing/shared_container_entry_module_factory.rs +++ /dev/null @@ -1,26 +0,0 @@ -use async_trait::async_trait; -use rspack_core::{ModuleExt, ModuleFactory, ModuleFactoryCreateData, ModuleFactoryResult}; -use rspack_error::Result; - -use super::{ - shared_container_entry_dependency::SharedContainerEntryDependency, - shared_container_entry_module::SharedContainerEntryModule, -}; - -#[derive(Debug)] -pub struct SharedContainerEntryModuleFactory; - -#[async_trait] -impl ModuleFactory for SharedContainerEntryModuleFactory { - async fn create(&self, data: &mut ModuleFactoryCreateData) -> Result { - let dep = data.dependencies[0] - .downcast_ref::() - .expect( - "dependency of SharedContainerEntryModuleFactory should be SharedContainerEntryDependency", - ); - Ok(ModuleFactoryResult::new_with_module( - SharedContainerEntryModule::new(dep.name.clone(), dep.request.clone(), dep.version.clone()) - .boxed(), - )) - } -} diff --git a/crates/rspack_plugin_mf/src/sharing/shared_container_plugin.rs b/crates/rspack_plugin_mf/src/sharing/shared_container_plugin.rs index bf4ae375f968..04f2dabd1ca3 100644 --- a/crates/rspack_plugin_mf/src/sharing/shared_container_plugin.rs +++ b/crates/rspack_plugin_mf/src/sharing/shared_container_plugin.rs @@ -8,11 +8,13 @@ use rspack_core::{ use rspack_error::Result; use rspack_hook::{plugin, plugin_hook}; -use super::{ - shared_container_entry_dependency::SharedContainerEntryDependency, - shared_container_entry_module_factory::SharedContainerEntryModuleFactory, +use crate::{ + container::{ + container_entry_dependency::ContainerEntryDependency, + container_entry_module_factory::ContainerEntryModuleFactory, + }, + sharing::shared_container_runtime_module::ShareContainerRuntimeModule, }; -use crate::sharing::shared_container_runtime_module::ShareContainerRuntimeModule; #[derive(Debug)] pub struct SharedContainerPluginOptions { @@ -43,7 +45,7 @@ async fn compilation( ) -> Result<()> { compilation.set_dependency_factory( DependencyType::ShareContainerEntry, - Arc::new(SharedContainerEntryModuleFactory), + Arc::new(ContainerEntryModuleFactory), ); compilation.set_dependency_factory( DependencyType::ShareContainerFallback, @@ -54,7 +56,7 @@ async fn compilation( #[plugin_hook(CompilerMake for SharedContainerPlugin)] async fn make(&self, compilation: &mut Compilation) -> Result<()> { - let dep = SharedContainerEntryDependency::new( + let dep = ContainerEntryDependency::new_share_container_entry( self.options.name.clone(), self.options.request.clone(), self.options.version.clone(), diff --git a/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_plugin.rs b/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_plugin.rs index d9a1dfd067d3..dd807a924bc7 100644 --- a/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_plugin.rs +++ b/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_plugin.rs @@ -1,6 +1,5 @@ use std::sync::{Arc, RwLock}; -use rspack_collections::Identifiable; use rspack_core::{ AsyncDependenciesBlockIdentifier, ChunkUkey, Compilation, CompilationAdditionalTreeRuntimeRequirements, CompilationDependencyReferencedExports, @@ -18,10 +17,9 @@ use rustc_hash::{FxHashMap, FxHashSet}; use super::{ consume_shared_module::ConsumeSharedModule, provide_shared_module::ProvideSharedModule, - shared_container_entry_module::SharedContainerEntryModule, shared_used_exports_optimizer_runtime_module::SharedUsedExportsOptimizerRuntimeModule, }; -use crate::manifest::StatsRoot; +use crate::{container::container_entry_module::ContainerEntryModule, manifest::StatsRoot}; #[derive(Debug, Clone)] pub struct OptimizeSharedConfig { pub share_key: String, @@ -89,10 +87,11 @@ impl SharedUsedExportsOptimizerPlugin { .write() .expect("lock poisoned"); for (share_key, shared_entry_data) in &self.shared_map { - if let Some(export_set) = shared_referenced_exports.get_mut(share_key) { - for used_export in &shared_entry_data.used_exports { - export_set.insert(used_export.to_string()); - } + let export_set = shared_referenced_exports + .entry(share_key.clone()) + .or_default(); + for used_export in &shared_entry_data.used_exports { + export_set.insert(used_export.to_string()); } } } @@ -151,7 +150,7 @@ async fn optimize_dependencies( ) { return None; } - + dbg!(&module_type); let mut modules_to_process = Vec::new(); let share_key = match module_type { rspack_core::ModuleType::ConsumeShared => { @@ -195,23 +194,11 @@ async fn optimize_dependencies( sk } rspack_core::ModuleType::ShareContainerShared => { - let share_container_entry_module = module - .as_any() - .downcast_ref::()?; - // Use the identifier to extract the share key - // The identifier is in format "share container entry {name}@{version}" - let identifier = share_container_entry_module.identifier().to_string(); - let parts: Vec<&str> = identifier.split(' ').collect(); - if parts.len() < 3 { - return None; - } - let name_part = parts[3]; - let name_end = if let Some(stripped) = name_part.strip_prefix('@') { - stripped.find('@').map(|i| i + 1).unwrap_or(name_part.len()) - } else { - name_part.find('@').unwrap_or(name_part.len()) - }; - let sk = name_part[..name_end].to_string(); + let share_container_entry_module = + module.as_any().downcast_ref::()?; + let sk = share_container_entry_module.name().to_string(); + dbg!(&sk); + dbg!(&share_container_entry_module); collect_processed_modules( module_graph, share_container_entry_module.get_blocks(), @@ -244,6 +231,9 @@ async fn optimize_dependencies( .get(&share_key) .cloned() }; + dbg!(&share_key); + dbg!(&self.shared_map); + dbg!(&modules_to_process); // Check if this share key is in our shared map and has tree_shaking enabled if !self.shared_map.contains_key(&share_key) { continue; @@ -253,15 +243,7 @@ async fn optimize_dependencies( continue; } - let real_shared_identifier = { - module_graph.modules().into_iter().find_map(|(id, module)| { - module - .as_any() - .downcast_ref::() - .filter(|normal| normal.raw_request() == share_key) - .map(|_| id) - }) - }; + let real_shared_identifier = modules_to_process.first().copied(); // Check if the real shared module is side effect free if let Some(real_shared_identifier) = real_shared_identifier { @@ -318,10 +300,12 @@ async fn optimize_dependencies( }) } }; + dbg!(&can_update_module_used_stage); if can_update_module_used_stage { // mark used exports per runtime // Mark used exports for export_info in exports_info_data.exports_mut().values_mut() { + dbg!(&export_info); export_info.set_used_conditionally( Box::new(|used| *used == rspack_core::UsageState::Unknown), rspack_core::UsageState::Unused, @@ -329,6 +313,7 @@ async fn optimize_dependencies( ); export_info.set_can_mangle_provide(Some(false)); export_info.set_can_mangle_use(Some(false)); + dbg!(&export_info); } } } @@ -433,6 +418,7 @@ async fn dependency_referenced_exports( return Ok(()); } let mut final_exports = exports.clone(); + // If it's an import dependency and referenced exports indicate "exports object referenced", // clear any recorded shared referenced exports for this share key and stop here. let is_exports_object = matches!( From 2a85e0a58a20df59aa02459d4ba2cacec3b15b4b Mon Sep 17 00:00:00 2001 From: "zhanghang.heal" Date: Tue, 27 Jan 2026 17:32:26 +0800 Subject: [PATCH 77/87] chore: fix merge conflict --- .../shared_used_exports_optimizer_plugin.rs | 9 - .../src/container/ModuleFederationPlugin.ts | 1 + .../src/sharing/TreeShakingSharedPlugin.ts | 3 + pnpm-lock.yaml | 8 +- tests/e2e/package.json | 2 +- .../plugin-with-params.js | 5 +- .../runtime-plugin.js | 5 +- .../__snapshot__/e.js.txt | 2 +- .../tree-shaking-shared/rspack.config.js | 1 + .../share-plugin/__snapshots__/web/0.snap.txt | 13 + .../share-plugin/__snapshots__/web/1.snap.txt | 1288 +++++++++++++++++ tests/rspack-test/package.json | 2 +- 12 files changed, 1321 insertions(+), 18 deletions(-) create mode 100644 tests/rspack-test/hotCases/sharing/share-plugin/__snapshots__/web/0.snap.txt create mode 100644 tests/rspack-test/hotCases/sharing/share-plugin/__snapshots__/web/1.snap.txt diff --git a/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_plugin.rs b/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_plugin.rs index be550420b2e1..fa2f3d1b07e0 100644 --- a/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_plugin.rs +++ b/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_plugin.rs @@ -151,7 +151,6 @@ async fn optimize_dependencies( ) { return None; } - dbg!(&module_type); let mut modules_to_process = Vec::new(); let share_key = match module_type { rspack_core::ModuleType::ConsumeShared => { @@ -198,8 +197,6 @@ async fn optimize_dependencies( let share_container_entry_module = module.as_any().downcast_ref::()?; let sk = share_container_entry_module.name().to_string(); - dbg!(&sk); - dbg!(&share_container_entry_module); collect_processed_modules( module_graph, share_container_entry_module.get_blocks(), @@ -232,9 +229,6 @@ async fn optimize_dependencies( .get(&share_key) .cloned() }; - dbg!(&share_key); - dbg!(&self.shared_map); - dbg!(&modules_to_process); // Check if this share key is in our shared map and has tree_shaking enabled if !self.shared_map.contains_key(&share_key) { continue; @@ -301,12 +295,10 @@ async fn optimize_dependencies( }) } }; - dbg!(&can_update_module_used_stage); if can_update_module_used_stage { // mark used exports per runtime // Mark used exports for export_info in exports_info_data.exports_mut().values_mut() { - dbg!(&export_info); export_info.set_used_conditionally( Box::new(|used| *used == rspack_core::UsageState::Unknown), rspack_core::UsageState::Unused, @@ -314,7 +306,6 @@ async fn optimize_dependencies( ); export_info.set_can_mangle_provide(Some(false)); export_info.set_can_mangle_use(Some(false)); - dbg!(&export_info); } } } diff --git a/packages/rspack/src/container/ModuleFederationPlugin.ts b/packages/rspack/src/container/ModuleFederationPlugin.ts index 083df77c6c98..40d5b7c31978 100644 --- a/packages/rspack/src/container/ModuleFederationPlugin.ts +++ b/packages/rspack/src/container/ModuleFederationPlugin.ts @@ -85,6 +85,7 @@ export class ModuleFederationPlugin { ); new ModuleFederationRuntimePlugin({ entryRuntime, + experiments: runtimeExperiments, }).apply(compiler); }, ); diff --git a/packages/rspack/src/sharing/TreeShakingSharedPlugin.ts b/packages/rspack/src/sharing/TreeShakingSharedPlugin.ts index d630f50d14a1..5d812bfc6c94 100644 --- a/packages/rspack/src/sharing/TreeShakingSharedPlugin.ts +++ b/packages/rspack/src/sharing/TreeShakingSharedPlugin.ts @@ -1,9 +1,12 @@ +import { createRequire } from 'node:module'; import type { Compiler } from '../Compiler'; import type { ModuleFederationPluginOptions } from '../container/ModuleFederationPlugin'; import { IndependentSharedPlugin } from './IndependentSharedPlugin'; import { SharedUsedExportsOptimizerPlugin } from './SharedUsedExportsOptimizerPlugin'; import { normalizeSharedOptions } from './SharePlugin'; +const require = createRequire(import.meta.url); + export interface TreeshakingSharedPluginOptions { mfConfig: ModuleFederationPluginOptions; secondary?: boolean; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1fcc97f87074..ccb6e0d4e9b1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -661,8 +661,8 @@ importers: specifier: ^7.28.5 version: 7.28.5(@babel/core@7.28.6) '@module-federation/runtime-tools': - specifier: ^0.22.0 - version: 0.22.0 + specifier: 0.0.0-feat-shared-treeshake-poc-20260114091859 + version: 0.0.0-feat-shared-treeshake-poc-20260114091859 '@playwright/test': specifier: 1.57.0 version: 1.57.0 @@ -736,8 +736,8 @@ importers: specifier: ^7.28.5 version: 7.28.5(@babel/core@7.28.6) '@module-federation/runtime-tools': - specifier: ^0.22.0 - version: 0.22.0 + specifier: 0.0.0-feat-shared-treeshake-poc-20260114091859 + version: 0.0.0-feat-shared-treeshake-poc-20260114091859 '@rspack/binding-testing': specifier: workspace:* version: link:../../crates/rspack_binding_builder_testing diff --git a/tests/e2e/package.json b/tests/e2e/package.json index 06f02a25b22b..c3de248f1978 100644 --- a/tests/e2e/package.json +++ b/tests/e2e/package.json @@ -16,7 +16,7 @@ "@rspack/browser": "workspace:*", "@rspack/dev-server": "~1.2.1", "@rspack/plugin-react-refresh": "^1.6.0", - "@module-federation/runtime-tools": "^0.22.0", + "@module-federation/runtime-tools": "0.0.0-feat-shared-treeshake-poc-20260114091859", "@swc/helpers": "0.5.18", "@types/fs-extra": "11.0.4", "babel-loader": "^10.0.0", diff --git a/tests/rspack-test/configCases/container-1-5/runtime-plugin-with-params/plugin-with-params.js b/tests/rspack-test/configCases/container-1-5/runtime-plugin-with-params/plugin-with-params.js index 4aa407133e22..99684bc4fdf2 100644 --- a/tests/rspack-test/configCases/container-1-5/runtime-plugin-with-params/plugin-with-params.js +++ b/tests/rspack-test/configCases/container-1-5/runtime-plugin-with-params/plugin-with-params.js @@ -11,7 +11,10 @@ module.exports = function(params) { shareScopeMap[scope][pkgName][version] = { lib: ()=>()=> 'This is react 0.2.1' }; - return shareScopeMap[scope][pkgName][version]; + return { + shared: shareScopeMap[scope][pkgName][version], + useTreesShaking:false + }; }; return args; } diff --git a/tests/rspack-test/configCases/container-1-5/runtime-plugin-with-used-exports/runtime-plugin.js b/tests/rspack-test/configCases/container-1-5/runtime-plugin-with-used-exports/runtime-plugin.js index c09dfa834686..86d773aa503f 100644 --- a/tests/rspack-test/configCases/container-1-5/runtime-plugin-with-used-exports/runtime-plugin.js +++ b/tests/rspack-test/configCases/container-1-5/runtime-plugin-with-used-exports/runtime-plugin.js @@ -7,7 +7,10 @@ module.exports = function MyRuntimePlugin() { shareScopeMap[scope][pkgName][version] = { lib: ()=>()=> 'This is react 0.2.1' }; - return shareScopeMap[scope][pkgName][version]; + return { + shared: shareScopeMap[scope][pkgName][version], + useTreesShaking:false + }; }; return args; } diff --git a/tests/rspack-test/configCases/library/modern-module-force-concaten/__snapshot__/e.js.txt b/tests/rspack-test/configCases/library/modern-module-force-concaten/__snapshot__/e.js.txt index c3cdcfc2d8f1..c3253dfbd9b1 100644 --- a/tests/rspack-test/configCases/library/modern-module-force-concaten/__snapshot__/e.js.txt +++ b/tests/rspack-test/configCases/library/modern-module-force-concaten/__snapshot__/e.js.txt @@ -14,4 +14,4 @@ var bar_default_0 = bar_default(); var e_foo = (/* inlined export .foo */"foo"); -export { bar_default_0 as bar, e_foo as foo }; +export { bar_default_0 as bar, e_foo as foo }; \ No newline at end of file diff --git a/tests/rspack-test/configCases/sharing/tree-shaking-shared/rspack.config.js b/tests/rspack-test/configCases/sharing/tree-shaking-shared/rspack.config.js index 8aae02817a36..9b215235d487 100644 --- a/tests/rspack-test/configCases/sharing/tree-shaking-shared/rspack.config.js +++ b/tests/rspack-test/configCases/sharing/tree-shaking-shared/rspack.config.js @@ -4,6 +4,7 @@ const { ModuleFederationPlugin } = container; /** @type {import("@rspack/core").Configuration} */ module.exports = { + // entry: './index.js', target:'async-node', optimization:{ minimize: true, diff --git a/tests/rspack-test/hotCases/sharing/share-plugin/__snapshots__/web/0.snap.txt b/tests/rspack-test/hotCases/sharing/share-plugin/__snapshots__/web/0.snap.txt new file mode 100644 index 000000000000..823a7e782977 --- /dev/null +++ b/tests/rspack-test/hotCases/sharing/share-plugin/__snapshots__/web/0.snap.txt @@ -0,0 +1,13 @@ +# Case share-plugin: Step 0 + +## Changed Files + + +## Asset Files +- Bundle: bundle.js +- Bundle: common_js_2.chunk.CURRENT_HASH.js + +## Manifest + + +## Update \ No newline at end of file diff --git a/tests/rspack-test/hotCases/sharing/share-plugin/__snapshots__/web/1.snap.txt b/tests/rspack-test/hotCases/sharing/share-plugin/__snapshots__/web/1.snap.txt new file mode 100644 index 000000000000..4cbaa6b63730 --- /dev/null +++ b/tests/rspack-test/hotCases/sharing/share-plugin/__snapshots__/web/1.snap.txt @@ -0,0 +1,1288 @@ +# Case share-plugin: Step 1 + +## Changed Files +- module.js + +## Asset Files +- Bundle: bundle.js +- Bundle: common_js_2.chunk.CURRENT_HASH.js +- Manifest: main.LAST_HASH.hot-update.json, size: 28 +- Update: main.LAST_HASH.hot-update.js, size: 42334 + +## Manifest + +### main.LAST_HASH.hot-update.json + +```json +{"c":["main"],"r":[],"m":[]} +``` + + +## Update + + +### main.LAST_HASH.hot-update.js + +#### Changed Modules +- ./module.js + +#### Changed Runtime Modules +- webpack/runtime/compat_get_default_export +- webpack/runtime/consumes_loading +- webpack/runtime/create_fake_namespace_object +- webpack/runtime/get_full_hash +- webpack/runtime/jsonp_chunk_loading + +#### Changed Content +```js +"use strict"; +self["rspackHotUpdate"]("main", { +"./module.js"(__unused_rspack_module, __webpack_exports__, __webpack_require__) { +__webpack_require__.r(__webpack_exports__); +__webpack_require__.d(__webpack_exports__, { + "default": () => (/* reexport default from dynamic */ common__rspack_import_0_default.a), + getValue: () => (getValue) +}); +/* import */ var common__rspack_import_0 = __webpack_require__("webpack/sharing/consume/default/common/./common?1"); +/* import */ var common__rspack_import_0_default = /*#__PURE__*/__webpack_require__.n(common__rspack_import_0); + + +const getValue = () => __webpack_require__.e(/* import() */ "webpack_sharing_consume_default_common2_common_2").then(__webpack_require__.t.bind(__webpack_require__, "webpack/sharing/consume/default/common2/./common?2", 23)); + + +}, + +},function(__webpack_require__) { +// webpack/runtime/compat_get_default_export +(() => { +// getDefaultExport function for compatibility with non-ESM modules +__webpack_require__.n = (module) => { + var getter = module && module.__esModule ? + () => (module['default']) : + () => (module); + __webpack_require__.d(getter, { a: getter }); + return getter; +}; + +})(); +// webpack/runtime/create_fake_namespace_object +(() => { +var getProto = Object.getPrototypeOf ? (obj) => (Object.getPrototypeOf(obj)) : (obj) => (obj.__proto__); +var leafPrototypes; +// create a fake namespace object +// mode & 1: value is a module id, require it +// mode & 2: merge all properties of value into the ns +// mode & 4: return value when already ns object +// mode & 16: return value when it's Promise-like +// mode & 8|1: behave like require +__webpack_require__.t = function(value, mode) { + if(mode & 1) value = this(value); + if(mode & 8) return value; + if(typeof value === 'object' && value) { + if((mode & 4) && value.__esModule) return value; + if((mode & 16) && typeof value.then === 'function') return value; + } + var ns = Object.create(null); + __webpack_require__.r(ns); + var def = {}; + leafPrototypes = leafPrototypes || [null, getProto({}), getProto([]), getProto(getProto)]; + for(var current = mode & 2 && value; (typeof current == 'object' || typeof current == 'function') && !~leafPrototypes.indexOf(current); current = getProto(current)) { + Object.getOwnPropertyNames(current).forEach((key) => { def[key] = () => (value[key]) }); + } + def['default'] = () => (value); + __webpack_require__.d(ns, def); + return ns; +}; +})(); +// webpack/runtime/get_full_hash +(() => { +__webpack_require__.h = () => ("CURRENT_HASH") +})(); +// webpack/runtime/consumes_loading +(() => { + +__webpack_require__.consumesLoadingData = { chunkMapping: {"main":["webpack/sharing/consume/default/common/./common?1"],"webpack_sharing_consume_default_common2_common_2":["webpack/sharing/consume/default/common2/./common?2"]}, moduleIdToConsumeDataMapping: {"webpack/sharing/consume/default/common2/./common?2": { shareScope: "default", shareKey: "common2", import: "./common?2", requiredVersion: "1.1.1", strictVersion: true, singleton: false, eager: false, fallback: () => (__webpack_require__.e("common_js_2").then(() => (() => (__webpack_require__("./common.js?2"))))), treeShakingMode: null }, "webpack/sharing/consume/default/common/./common?1": { shareScope: "default", shareKey: "common", import: "./common?1", requiredVersion: "1.1.1", strictVersion: true, singleton: false, eager: true, fallback: () => (() => (__webpack_require__("./common.js?1"))), treeShakingMode: null }}, initialConsumes: ["webpack/sharing/consume/default/common/./common?1"] }; +var splitAndConvert = function(str) { + return str.split(".").map(function(item) { + return +item == item ? +item : item; + }); +}; +var parseRange = function(str) { + // see https://docs.npmjs.com/misc/semver#range-grammar for grammar + var parsePartial = function(str) { + var match = /^([^-+]+)?(?:-([^+]+))?(?:\+(.+))?$/.exec(str); + var ver = match[1] ? [0].concat(splitAndConvert(match[1])) : [0]; + if (match[2]) { + ver.length++; + ver.push.apply(ver, splitAndConvert(match[2])); + } + + // remove trailing any matchers + let last = ver[ver.length - 1]; + while ( + ver.length && + (last === undefined || /^[*xX]$/.test(/** @type {string} */ (last))) + ) { + ver.pop(); + last = ver[ver.length - 1]; + } + + return ver; + }; + var toFixed = function(range) { + if (range.length === 1) { + // Special case for "*" is "x.x.x" instead of "=" + return [0]; + } else if (range.length === 2) { + // Special case for "1" is "1.x.x" instead of "=1" + return [1].concat(range.slice(1)); + } else if (range.length === 3) { + // Special case for "1.2" is "1.2.x" instead of "=1.2" + return [2].concat(range.slice(1)); + } else { + return [range.length].concat(range.slice(1)); + } + }; + var negate = function(range) { + return [-range[0] - 1].concat(range.slice(1)); + }; + var parseSimple = function(str) { + // simple ::= primitive | partial | tilde | caret + // primitive ::= ( '<' | '>' | '>=' | '<=' | '=' | '!' ) ( ' ' ) * partial + // tilde ::= '~' ( ' ' ) * partial + // caret ::= '^' ( ' ' ) * partial + const match = /^(\^|~|<=|<|>=|>|=|v|!)/.exec(str); + const start = match ? match[0] : ""; + const remainder = parsePartial( + start.length ? str.slice(start.length).trim() : str.trim() + ); + switch (start) { + case "^": + if (remainder.length > 1 && remainder[1] === 0) { + if (remainder.length > 2 && remainder[2] === 0) { + return [3].concat(remainder.slice(1)); + } + return [2].concat(remainder.slice(1)); + } + return [1].concat(remainder.slice(1)); + case "~": + return [2].concat(remainder.slice(1)); + case ">=": + return remainder; + case "=": + case "v": + case "": + return toFixed(remainder); + case "<": + return negate(remainder); + case ">": { + // and( >=, not( = ) ) => >=, =, not, and + const fixed = toFixed(remainder); + return [, fixed, 0, remainder, 2]; + } + case "<=": + // or( <, = ) => <, =, or + return [, toFixed(remainder), negate(remainder), 1]; + case "!": { + // not = + const fixed = toFixed(remainder); + return [, fixed, 0]; + } + default: + throw new Error("Unexpected start value"); + } + }; + var combine = function(items, fn) { + if (items.length === 1) return items[0]; + const arr = []; + for (const item of items.slice().reverse()) { + if (0 in item) { + arr.push(item); + } else { + arr.push.apply(arr, item.slice(1)); + } + } + return [,].concat(arr, items.slice(1).map(() => fn)); + }; + var parseRange = function(str) { + // range ::= hyphen | simple ( ' ' ( ' ' ) * simple ) * | '' + // hyphen ::= partial ( ' ' ) * ' - ' ( ' ' ) * partial + const items = str.split(/\s+-\s+/); + if (items.length === 1) { + str = str.trim(); + const items = []; + const r = /[-0-9A-Za-z]\s+/g; + var start = 0; + var match; + while ((match = r.exec(str))) { + const end = match.index + 1; + items.push(parseSimple(str.slice(start, end).trim())); + start = end; + } + items.push(parseSimple(str.slice(start).trim())); + return combine(items, 2); + } + const a = parsePartial(items[0]); + const b = parsePartial(items[1]); + // >=a <=b => and( >=a, or( >=a, = a.length) return i < b.length && (typeof b[i])[0] != "u"; + + var aValue = a[i]; + var aType = (typeof aValue)[0]; + + // Handles first column in table + if (i >= b.length) return aType == "u"; + + var bValue = b[i]; + var bType = (typeof bValue)[0]; + + if (aType == bType) { + if (aType != "o" && aType != "u" && aValue != bValue) { + return aValue < bValue; + } + i++; + } else { + // Handles remaining cases + if (aType == "o" && bType == "n") return true; + return bType == "s" || aType == "u"; + } + } +} +var rangeToString = function(range) { + var fixCount = range[0]; + var str = ""; + if (range.length === 1) { + return "*"; + } else if (fixCount + 0.5) { + str += + fixCount == 0 + ? ">=" + : fixCount == -1 + ? "<" + : fixCount == 1 + ? "^" + : fixCount == 2 + ? "~" + : fixCount > 0 + ? "=" + : "!="; + var needDot = 1; + for (var i = 1; i < range.length; i++) { + var item = range[i]; + var t = (typeof item)[0]; + needDot--; + str += + t == "u" + ? // undefined: prerelease marker, add an "-" + "-" + : // number or string: add the item, set flag to add an "." between two of them + (needDot > 0 ? "." : "") + ((needDot = 2), item); + } + return str; + } else { + var stack = []; + for (var i = 1; i < range.length; i++) { + var item = range[i]; + stack.push( + item === 0 + ? "not(" + pop() + ")" + : item === 1 + ? "(" + pop() + " || " + pop() + ")" + : item === 2 + ? stack.pop() + " " + stack.pop() + : rangeToString(item) + ); + } + return pop(); + } + function pop() { + return stack.pop().replace(/^\((.+)\)$/, "$1"); + } +} +var satisfy = function(range, version) { + if (0 in range) { + version = parseVersion(version); + var fixCount = /** @type {number} */ (range[0]); + // when negated is set it swill set for < instead of >= + var negated = fixCount < 0; + if (negated) fixCount = -fixCount - 1; + for (var i = 0, j = 1, isEqual = true; ; j++, i++) { + // cspell:word nequal nequ + + // when isEqual = true: + // range version: EOA/object undefined number string + // EOA equal block big-ver big-ver + // undefined bigger next big-ver big-ver + // number smaller block cmp big-cmp + // fixed number smaller block cmp-fix differ + // string smaller block differ cmp + // fixed string smaller block small-cmp cmp-fix + + // when isEqual = false: + // range version: EOA/object undefined number string + // EOA nequal block next-ver next-ver + // undefined nequal block next-ver next-ver + // number nequal block next next + // fixed number nequal block next next (this never happens) + // string nequal block next next + // fixed string nequal block next next (this never happens) + + // EOA end of array + // equal (version is equal range): + // when !negated: return true, + // when negated: return false + // bigger (version is bigger as range): + // when fixed: return false, + // when !negated: return true, + // when negated: return false, + // smaller (version is smaller as range): + // when !negated: return false, + // when negated: return true + // nequal (version is not equal range (> resp <)): return true + // block (version is in different prerelease area): return false + // differ (version is different from fixed range (string vs. number)): return false + // next: continues to the next items + // next-ver: when fixed: return false, continues to the next item only for the version, sets isEqual=false + // big-ver: when fixed || negated: return false, continues to the next item only for the version, sets isEqual=false + // next-nequ: continues to the next items, sets isEqual=false + // cmp (negated === false): version < range => return false, version > range => next-nequ, else => next + // cmp (negated === true): version > range => return false, version < range => next-nequ, else => next + // cmp-fix: version == range => next, else => return false + // big-cmp: when negated => return false, else => next-nequ + // small-cmp: when negated => next-nequ, else => return false + + var rangeType = j < range.length ? (typeof range[j])[0] : ""; + + var versionValue; + var versionType; + + // Handles first column in both tables (end of version or object) + if ( + i >= version.length || + ((versionValue = version[i]), + (versionType = (typeof versionValue)[0]) == "o") + ) { + // Handles nequal + if (!isEqual) return true; + // Handles bigger + if (rangeType == "u") return j > fixCount && !negated; + // Handles equal and smaller: (range === EOA) XOR negated + return (rangeType == "") != negated; // equal + smaller + } + + // Handles second column in both tables (version = undefined) + if (versionType == "u") { + if (!isEqual || rangeType != "u") { + return false; + } + } + + // switch between first and second table + else if (isEqual) { + // Handle diagonal + if (rangeType == versionType) { + if (j <= fixCount) { + // Handles "cmp-fix" cases + if (versionValue != range[j]) { + return false; + } + } else { + // Handles "cmp" cases + if (negated ? versionValue > range[j] : versionValue < range[j]) { + return false; + } + if (versionValue != range[j]) isEqual = false; + } + } + + // Handle big-ver + else if (rangeType != "s" && rangeType != "n") { + if (negated || j <= fixCount) return false; + isEqual = false; + j--; + } + + // Handle differ, big-cmp and small-cmp + else if (j <= fixCount || versionType < rangeType != negated) { + return false; + } else { + isEqual = false; + } + } else { + // Handles all "next-ver" cases in the second table + if (rangeType != "s" && rangeType != "n") { + isEqual = false; + j--; + } + + // next is applied by default + } + } + } + /** @type {(boolean | number)[]} */ + var stack = []; + var p = stack.pop.bind(stack); + for (var i = 1; i < range.length; i++) { + var item = /** @type {SemVerRange | 0 | 1 | 2} */ (range[i]); + stack.push( + item == 1 + ? p() | p() + : item == 2 + ? p() & p() + : item + ? satisfy(item, version) + : !p() + ); + } + return !!p(); +} +var ensureExistence = function(scopeName, key) { + var scope = __webpack_require__.S[scopeName]; + if(!scope || !__webpack_require__.o(scope, key)) throw new Error("Shared module " + key + " doesn't exist in shared scope " + scopeName); + return scope; +}; +var findVersion = function(scope, key) { + var versions = scope[key]; + var key = Object.keys(versions).reduce(function(a, b) { + return !a || versionLt(a, b) ? b : a; + }, 0); + return key && versions[key] +}; +var findSingletonVersionKey = function(scope, key) { + var versions = scope[key]; + return Object.keys(versions).reduce(function(a, b) { + return !a || (!versions[a].loaded && versionLt(a, b)) ? b : a; + }, 0); +}; +var getInvalidSingletonVersionMessage = function(scope, key, version, requiredVersion) { + return "Unsatisfied version " + version + " from " + (version && scope[key][version].from) + " of shared singleton module " + key + " (required " + rangeToString(requiredVersion) + ")" +}; +var getSingleton = function(scope, scopeName, key, requiredVersion) { + var version = findSingletonVersionKey(scope, key); + return get(scope[key][version]); +}; +var getSingletonVersion = function(scope, scopeName, key, requiredVersion) { + var version = findSingletonVersionKey(scope, key); + if (!satisfy(requiredVersion, version)) warn(getInvalidSingletonVersionMessage(scope, key, version, requiredVersion)); + return get(scope[key][version]); +}; +var getStrictSingletonVersion = function(scope, scopeName, key, requiredVersion) { + var version = findSingletonVersionKey(scope, key); + if (!satisfy(requiredVersion, version)) throw new Error(getInvalidSingletonVersionMessage(scope, key, version, requiredVersion)); + return get(scope[key][version]); +}; +var findValidVersion = function(scope, key, requiredVersion) { + var versions = scope[key]; + var key = Object.keys(versions).reduce(function(a, b) { + if (!satisfy(requiredVersion, b)) return a; + return !a || versionLt(a, b) ? b : a; + }, 0); + return key && versions[key] +}; +var getInvalidVersionMessage = function(scope, scopeName, key, requiredVersion) { + var versions = scope[key]; + return "No satisfying version (" + rangeToString(requiredVersion) + ") of shared module " + key + " found in shared scope " + scopeName + ".\n" + + "Available versions: " + Object.keys(versions).map(function(key) { + return key + " from " + versions[key].from; + }).join(", "); +}; +var getValidVersion = function(scope, scopeName, key, requiredVersion) { + var entry = findValidVersion(scope, key, requiredVersion); + if(entry) return get(entry); + throw new Error(getInvalidVersionMessage(scope, scopeName, key, requiredVersion)); +}; +var warn = function(msg) { + if (typeof console !== "undefined" && console.warn) console.warn(msg); +}; +var warnInvalidVersion = function(scope, scopeName, key, requiredVersion) { + warn(getInvalidVersionMessage(scope, scopeName, key, requiredVersion)); +}; +var get = function(entry) { + entry.loaded = 1; + return entry.get() +}; +var init = function(fn) { return function(scopeName, a, b, c) { + var promise = __webpack_require__.I(scopeName); + if (promise && promise.then) return promise.then(fn.bind(fn, scopeName, __webpack_require__.S[scopeName], a, b, c)); + return fn(scopeName, __webpack_require__.S[scopeName], a, b, c); +}; }; + +var load = /*#__PURE__*/ init(function(scopeName, scope, key) { + ensureExistence(scopeName, key); + return get(findVersion(scope, key)); +}); +var loadFallback = /*#__PURE__*/ init(function(scopeName, scope, key, fallback) { + return scope && __webpack_require__.o(scope, key) ? get(findVersion(scope, key)) : fallback(); +}); +var loadVersionCheck = /*#__PURE__*/ init(function(scopeName, scope, key, version) { + ensureExistence(scopeName, key); + return get(findValidVersion(scope, key, version) || warnInvalidVersion(scope, scopeName, key, version) || findVersion(scope, key)); +}); +var loadSingleton = /*#__PURE__*/ init(function(scopeName, scope, key) { + ensureExistence(scopeName, key); + return getSingleton(scope, scopeName, key); +}); +var loadSingletonVersionCheck = /*#__PURE__*/ init(function(scopeName, scope, key, version) { + ensureExistence(scopeName, key); + return getSingletonVersion(scope, scopeName, key, version); +}); +var loadStrictVersionCheck = /*#__PURE__*/ init(function(scopeName, scope, key, version) { + ensureExistence(scopeName, key); + return getValidVersion(scope, scopeName, key, version); +}); +var loadStrictSingletonVersionCheck = /*#__PURE__*/ init(function(scopeName, scope, key, version) { + ensureExistence(scopeName, key); + return getStrictSingletonVersion(scope, scopeName, key, version); +}); +var loadVersionCheckFallback = /*#__PURE__*/ init(function(scopeName, scope, key, version, fallback) { + if(!scope || !__webpack_require__.o(scope, key)) return fallback(); + return get(findValidVersion(scope, key, version) || warnInvalidVersion(scope, scopeName, key, version) || findVersion(scope, key)); +}); +var loadSingletonFallback = /*#__PURE__*/ init(function(scopeName, scope, key, fallback) { + if(!scope || !__webpack_require__.o(scope, key)) return fallback(); + return getSingleton(scope, scopeName, key); +}); +var loadSingletonVersionCheckFallback = /*#__PURE__*/ init(function(scopeName, scope, key, version, fallback) { + if(!scope || !__webpack_require__.o(scope, key)) return fallback(); + return getSingletonVersion(scope, scopeName, key, version); +}); +var loadStrictVersionCheckFallback = /*#__PURE__*/ init(function(scopeName, scope, key, version, fallback) { + var entry = scope && __webpack_require__.o(scope, key) && findValidVersion(scope, key, version); + return entry ? get(entry) : fallback(); +}); +var loadStrictSingletonVersionCheckFallback = /*#__PURE__*/ init(function(scopeName, scope, key, version, fallback) { + if(!scope || !__webpack_require__.o(scope, key)) return fallback(); + return getStrictSingletonVersion(scope, scopeName, key, version); +}); +var resolveHandler = function(data) { + var strict = false + var singleton = false + var versionCheck = false + var fallback = false + var args = [data.shareScope, data.shareKey]; + if (data.requiredVersion) { + if (data.strictVersion) strict = true; + if (data.singleton) singleton = true; + args.push(parseRange(data.requiredVersion)); + versionCheck = true + } else if (data.singleton) singleton = true; + if (data.fallback) { + fallback = true; + args.push(data.fallback); + } + if (strict && singleton && versionCheck && fallback) return function() { return loadStrictSingletonVersionCheckFallback.apply(null, args); } + if (strict && versionCheck && fallback) return function() { return loadStrictVersionCheckFallback.apply(null, args); } + if (singleton && versionCheck && fallback) return function() { return loadSingletonVersionCheckFallback.apply(null, args); } + if (strict && singleton && versionCheck) return function() { return loadStrictSingletonVersionCheck.apply(null, args); } + if (singleton && fallback) return function() { return loadSingletonFallback.apply(null, args); } + if (versionCheck && fallback) return function() { return loadVersionCheckFallback.apply(null, args); } + if (strict && versionCheck) return function() { return loadStrictVersionCheck.apply(null, args); } + if (singleton && versionCheck) return function() { return loadSingletonVersionCheck.apply(null, args); } + if (singleton) return function() { return loadSingleton.apply(null, args); } + if (versionCheck) return function() { return loadVersionCheck.apply(null, args); } + if (fallback) return function() { return loadFallback.apply(null, args); } + return function() { return load.apply(null, args); } +}; +var installedModules = {}; +__webpack_require__.consumesLoadingData.initialConsumes.forEach(function(id) { + __webpack_require__.m[id] = function(module) { + // Handle case when module is used sync + installedModules[id] = 0; + delete __webpack_require__.c[id]; + var factory = resolveHandler(__webpack_require__.consumesLoadingData.moduleIdToConsumeDataMapping[id])(); + if (typeof factory !== "function") + throw new Error( + "Shared module is not available for eager consumption: " + id + ); + module.exports = factory(); + }; +}); +__webpack_require__.f.consumes = function(chunkId, promises) { + var moduleIdToConsumeDataMapping = __webpack_require__.consumesLoadingData.moduleIdToConsumeDataMapping + var chunkMapping = __webpack_require__.consumesLoadingData.chunkMapping; + if(__webpack_require__.o(chunkMapping, chunkId)) { + chunkMapping[chunkId].forEach(function(id) { + if(__webpack_require__.o(installedModules, id)) return promises.push(installedModules[id]); + var onFactory = function(factory) { + installedModules[id] = 0; + __webpack_require__.m[id] = function(module) { + delete __webpack_require__.c[id]; + module.exports = factory(); + } + }; + var onError = function(error) { + delete installedModules[id]; + __webpack_require__.m[id] = function(module) { + delete __webpack_require__.c[id]; + throw error; + } + }; + try { + var promise = resolveHandler(moduleIdToConsumeDataMapping[id])(); + if(promise.then) { + promises.push(installedModules[id] = promise.then(onFactory)['catch'](onError)); + } else onFactory(promise); + } catch(e) { onError(e); } + }); + } +} + +})(); +// webpack/runtime/jsonp_chunk_loading +(() => { + + // object to store loaded and loading chunks + // undefined = chunk not loaded, null = chunk preloaded/prefetched + // [resolve, reject, Promise] = chunk loading, 0 = chunk loaded + var installedChunks = __webpack_require__.hmrS_jsonp = __webpack_require__.hmrS_jsonp || {"main": 0,}; + + __webpack_require__.f.j = function (chunkId, promises) { + // JSONP chunk loading for javascript +var installedChunkData = __webpack_require__.o(installedChunks, chunkId) + ? installedChunks[chunkId] + : undefined; +if (installedChunkData !== 0) { + // 0 means "already installed". + + // a Promise means "currently loading". + if (installedChunkData) { + promises.push(installedChunkData[2]); + } else { + if ("webpack_sharing_consume_default_common2_common_2" != chunkId) { + // setup Promise in chunk cache + var promise = new Promise((resolve, reject) => (installedChunkData = installedChunks[chunkId] = [resolve, reject])); + promises.push((installedChunkData[2] = promise)); + + // start chunk loading + var url = __webpack_require__.p + __webpack_require__.u(chunkId); + // create error before stack unwound to get useful stacktrace later + var error = new Error(); + var loadingEnded = function (event) { + if (__webpack_require__.o(installedChunks, chunkId)) { + installedChunkData = installedChunks[chunkId]; + if (installedChunkData !== 0) installedChunks[chunkId] = undefined; + if (installedChunkData) { + var errorType = + event && (event.type === 'load' ? 'missing' : event.type); + var realSrc = event && event.target && event.target.src; + error.message = + 'Loading chunk ' + + chunkId + + ' failed.\n(' + + errorType + + ': ' + + realSrc + + ')'; + error.name = 'ChunkLoadError'; + error.type = errorType; + error.request = realSrc; + installedChunkData[1](error); + } + } + }; + __webpack_require__.l(url, loadingEnded, "chunk-" + chunkId, chunkId); + } else installedChunks[chunkId] = 0; + } +} + + } + var currentUpdatedModulesList; +var waitingUpdateResolves = {}; +function loadUpdateChunk(chunkId, updatedModulesList) { + currentUpdatedModulesList = updatedModulesList; + return new Promise((resolve, reject) => { + waitingUpdateResolves[chunkId] = resolve; + // start update chunk loading + var url = __webpack_require__.p + __webpack_require__.hu(chunkId); + // create error before stack unwound to get useful stacktrace later + var error = new Error(); + var loadingEnded = (event) => { + if (waitingUpdateResolves[chunkId]) { + waitingUpdateResolves[chunkId] = undefined; + var errorType = + event && (event.type === 'load' ? 'missing' : event.type); + var realSrc = event && event.target && event.target.src; + error.message = + 'Loading hot update chunk ' + + chunkId + + ' failed.\n(' + + errorType + + ': ' + + realSrc + + ')'; + error.name = 'ChunkLoadError'; + error.type = errorType; + error.request = realSrc; + reject(error); + } + }; + __webpack_require__.l(url, loadingEnded); + }); +} + +self["rspackHotUpdate"] = (chunkId, moreModules, runtime) => { + for (var moduleId in moreModules) { + if (__webpack_require__.o(moreModules, moduleId)) { + currentUpdate[moduleId] = moreModules[moduleId]; + if (currentUpdatedModulesList) currentUpdatedModulesList.push(moduleId); + } + } + if (runtime) currentUpdateRuntime.push(runtime); + if (waitingUpdateResolves[chunkId]) { + waitingUpdateResolves[chunkId](); + waitingUpdateResolves[chunkId] = undefined; + } +}; +var currentUpdateChunks; +var currentUpdate; +var currentUpdateRemovedChunks; +var currentUpdateRuntime; +function applyHandler(options) { + if (__webpack_require__.f) delete __webpack_require__.f.jsonpHmr; + currentUpdateChunks = undefined; + function getAffectedModuleEffects(updateModuleId) { + var outdatedModules = [updateModuleId]; + var outdatedDependencies = {}; + var queue = outdatedModules.map(function (id) { + return { + chain: [id], + id: id + }; + }); + while (queue.length > 0) { + var queueItem = queue.pop(); + var moduleId = queueItem.id; + var chain = queueItem.chain; + var module = __webpack_require__.c[moduleId]; + if ( + !module || + (module.hot._selfAccepted && !module.hot._selfInvalidated) + ) { + continue; + } + + if (module.hot._selfDeclined) { + return { + type: "self-declined", + chain: chain, + moduleId: moduleId + }; + } + + if (module.hot._main) { + return { + type: "unaccepted", + chain: chain, + moduleId: moduleId + }; + } + + for (var i = 0; i < module.parents.length; i++) { + var parentId = module.parents[i]; + var parent = __webpack_require__.c[parentId]; + if (!parent) { + continue; + } + if (parent.hot._declinedDependencies[moduleId]) { + return { + type: "declined", + chain: chain.concat([parentId]), + moduleId: moduleId, + parentId: parentId + }; + } + if (outdatedModules.indexOf(parentId) !== -1) { + continue; + } + if (parent.hot._acceptedDependencies[moduleId]) { + if (!outdatedDependencies[parentId]) { + outdatedDependencies[parentId] = []; + } + addAllToSet(outdatedDependencies[parentId], [moduleId]); + continue; + } + delete outdatedDependencies[parentId]; + outdatedModules.push(parentId); + queue.push({ + chain: chain.concat([parentId]), + id: parentId + }); + } + } + + return { + type: "accepted", + moduleId: updateModuleId, + outdatedModules: outdatedModules, + outdatedDependencies: outdatedDependencies + }; + } + + function addAllToSet(a, b) { + for (var i = 0; i < b.length; i++) { + var item = b[i]; + if (a.indexOf(item) === -1) a.push(item); + } + } + + var outdatedDependencies = {}; + var outdatedModules = []; + var appliedUpdate = {}; + + var warnUnexpectedRequire = function warnUnexpectedRequire(module) { + console.warn( + "[HMR] unexpected require(" + module.id + ") to disposed module" + ); + throw Error("RuntimeError: factory is undefined(" + module.id + ")"); + }; + + for (var moduleId in currentUpdate) { + if (__webpack_require__.o(currentUpdate, moduleId)) { + var newModuleFactory = currentUpdate[moduleId]; + var result = newModuleFactory ? getAffectedModuleEffects(moduleId) : { + type: "disposed", + moduleId: moduleId + }; + var abortError = false; + var doApply = false; + var doDispose = false; + var chainInfo = ""; + if (result.chain) { + chainInfo = "\nUpdate propagation: " + result.chain.join(" -> "); + } + switch (result.type) { + case "self-declined": + if (options.onDeclined) options.onDeclined(result); + if (!options.ignoreDeclined) + abortError = new Error( + "Aborted because of self decline: " + result.moduleId + chainInfo + ); + break; + case "declined": + if (options.onDeclined) options.onDeclined(result); + if (!options.ignoreDeclined) + abortError = new Error( + "Aborted because of declined dependency: " + + result.moduleId + + " in " + + result.parentId + + chainInfo + ); + break; + case "unaccepted": + if (options.onUnaccepted) options.onUnaccepted(result); + if (!options.ignoreUnaccepted) + abortError = new Error( + "Aborted because " + moduleId + " is not accepted" + chainInfo + ); + break; + case "accepted": + if (options.onAccepted) options.onAccepted(result); + doApply = true; + break; + case "disposed": + if (options.onDisposed) options.onDisposed(result); + doDispose = true; + break; + default: + throw new Error("Unexception type " + result.type); + } + if (abortError) { + return { + error: abortError + }; + } + if (doApply) { + appliedUpdate[moduleId] = newModuleFactory; + addAllToSet(outdatedModules, result.outdatedModules); + for (moduleId in result.outdatedDependencies) { + if (__webpack_require__.o(result.outdatedDependencies, moduleId)) { + if (!outdatedDependencies[moduleId]) + outdatedDependencies[moduleId] = []; + addAllToSet( + outdatedDependencies[moduleId], + result.outdatedDependencies[moduleId] + ); + } + } + } + if (doDispose) { + addAllToSet(outdatedModules, [result.moduleId]); + appliedUpdate[moduleId] = warnUnexpectedRequire; + } + } + } + currentUpdate = undefined; + + var outdatedSelfAcceptedModules = []; + for (var j = 0; j < outdatedModules.length; j++) { + var outdatedModuleId = outdatedModules[j]; + var module = __webpack_require__.c[outdatedModuleId]; + if ( + module && + (module.hot._selfAccepted || module.hot._main) && + // removed self-accepted modules should not be required + appliedUpdate[outdatedModuleId] !== warnUnexpectedRequire && + // when called invalidate self-accepting is not possible + !module.hot._selfInvalidated + ) { + outdatedSelfAcceptedModules.push({ + module: outdatedModuleId, + require: module.hot._requireSelf, + errorHandler: module.hot._selfAccepted + }); + } + } + + if (self.__HMR_UPDATED_RUNTIME__) { + self.__HMR_UPDATED_RUNTIME__.javascript.outdatedModules = outdatedModules; + self.__HMR_UPDATED_RUNTIME__.javascript.outdatedDependencies = outdatedDependencies; + } + + + var moduleOutdatedDependencies; + return { + dispose: function () { + currentUpdateRemovedChunks.forEach(function (chunkId) { + delete installedChunks[chunkId]; + }); + currentUpdateRemovedChunks = undefined; + + var idx; + var queue = outdatedModules.slice(); + while (queue.length > 0) { + var moduleId = queue.pop(); + var module = __webpack_require__.c[moduleId]; + if (!module) continue; + + var data = {}; + + // Call dispose handlers + var disposeHandlers = module.hot._disposeHandlers; + + if (disposeHandlers.length > 0 && self.__HMR_UPDATED_RUNTIME__) { + self.__HMR_UPDATED_RUNTIME__.javascript.disposedModules.push(moduleId); + } + + for (j = 0; j < disposeHandlers.length; j++) { + disposeHandlers[j].call(null, data); + } + __webpack_require__.hmrD[moduleId] = data; + + module.hot.active = false; + + delete __webpack_require__.c[moduleId]; + + delete outdatedDependencies[moduleId]; + + for (j = 0; j < module.children.length; j++) { + var child = __webpack_require__.c[module.children[j]]; + if (!child) continue; + idx = child.parents.indexOf(moduleId); + if (idx >= 0) { + child.parents.splice(idx, 1); + } + } + } + + var dependency; + for (var outdatedModuleId in outdatedDependencies) { + if (__webpack_require__.o(outdatedDependencies, outdatedModuleId)) { + module = __webpack_require__.c[outdatedModuleId]; + if (module) { + moduleOutdatedDependencies = outdatedDependencies[outdatedModuleId]; + for (j = 0; j < moduleOutdatedDependencies.length; j++) { + dependency = moduleOutdatedDependencies[j]; + idx = module.children.indexOf(dependency); + if (idx >= 0) module.children.splice(idx, 1); + } + } + } + } + }, + apply: function (reportError) { + // insert new code + for (var updateModuleId in appliedUpdate) { + if (__webpack_require__.o(appliedUpdate, updateModuleId)) { + __webpack_require__.m[updateModuleId] = appliedUpdate[updateModuleId]; + + if (self.__HMR_UPDATED_RUNTIME__) { + self.__HMR_UPDATED_RUNTIME__.javascript.updatedModules.push(updateModuleId); + } + + } + } + + // run new runtime modules + for (var i = 0; i < currentUpdateRuntime.length; i++) { + + currentUpdateRuntime[i](new Proxy(__webpack_require__, { + set(target, prop, value, receiver) { + if (self.__HMR_UPDATED_RUNTIME__) { + self.__HMR_UPDATED_RUNTIME__.javascript.updatedRuntime.push(`__webpack_require__.${prop}`); + } + return Reflect.set(target, prop, value, receiver); + } + })); + + } + + // call accept handlers + for (var outdatedModuleId in outdatedDependencies) { + if (__webpack_require__.o(outdatedDependencies, outdatedModuleId)) { + var module = __webpack_require__.c[outdatedModuleId]; + if (module) { + moduleOutdatedDependencies = outdatedDependencies[outdatedModuleId]; + var callbacks = []; + var errorHandlers = []; + var dependenciesForCallbacks = []; + for (var j = 0; j < moduleOutdatedDependencies.length; j++) { + var dependency = moduleOutdatedDependencies[j]; + var acceptCallback = module.hot._acceptedDependencies[dependency]; + var errorHandler = module.hot._acceptedErrorHandlers[dependency]; + if (acceptCallback) { + if (callbacks.indexOf(acceptCallback) !== -1) continue; + callbacks.push(acceptCallback); + errorHandlers.push(errorHandler); + + if (self.__HMR_UPDATED_RUNTIME__) { + self.__HMR_UPDATED_RUNTIME__.javascript.acceptedModules.push(dependency); + } + + dependenciesForCallbacks.push(dependency); + } + } + for (var k = 0; k < callbacks.length; k++) { + try { + callbacks[k].call(null, moduleOutdatedDependencies); + } catch (err) { + if (typeof errorHandlers[k] === "function") { + try { + errorHandlers[k](err, { + moduleId: outdatedModuleId, + dependencyId: dependenciesForCallbacks[k] + }); + } catch (err2) { + if (options.onErrored) { + options.onErrored({ + type: "accept-error-handler-errored", + moduleId: outdatedModuleId, + dependencyId: dependenciesForCallbacks[k], + error: err2, + originalError: err + }); + } + if (!options.ignoreErrored) { + reportError(err2); + reportError(err); + } + } + } else { + if (options.onErrored) { + options.onErrored({ + type: "accept-errored", + moduleId: outdatedModuleId, + dependencyId: dependenciesForCallbacks[k], + error: err + }); + } + if (!options.ignoreErrored) { + reportError(err); + } + } + } + } + } + } + } + + // Load self accepted modules + for (var o = 0; o < outdatedSelfAcceptedModules.length; o++) { + var item = outdatedSelfAcceptedModules[o]; + var moduleId = item.module; + try { + item.require(moduleId); + } catch (err) { + if (typeof item.errorHandler === "function") { + try { + item.errorHandler(err, { + moduleId: moduleId, + module: __webpack_require__.c[moduleId] + }); + } catch (err1) { + if (options.onErrored) { + options.onErrored({ + type: "self-accept-error-handler-errored", + moduleId: moduleId, + error: err1, + originalError: err + }); + } + if (!options.ignoreErrored) { + reportError(err1); + reportError(err); + } + } + } else { + if (options.onErrored) { + options.onErrored({ + type: "self-accept-errored", + moduleId: moduleId, + error: err + }); + } + if (!options.ignoreErrored) { + reportError(err); + } + } + } + } + + return outdatedModules; + } + }; +} + +__webpack_require__.hmrI.jsonp = function (moduleId, applyHandlers) { + if (!currentUpdate) { + currentUpdate = {}; + currentUpdateRuntime = []; + currentUpdateRemovedChunks = []; + applyHandlers.push(applyHandler); + } + if (!__webpack_require__.o(currentUpdate, moduleId)) { + currentUpdate[moduleId] = __webpack_require__.m[moduleId]; + } +}; + +__webpack_require__.hmrC.jsonp = function ( + chunkIds, + removedChunks, + removedModules, + promises, + applyHandlers, + updatedModulesList +) { + applyHandlers.push(applyHandler); + currentUpdateChunks = {}; + currentUpdateRemovedChunks = removedChunks; + currentUpdate = removedModules.reduce(function (obj, key) { + obj[key] = false; + return obj; + }, {}); + currentUpdateRuntime = []; + chunkIds.forEach(function (chunkId) { + if ( + __webpack_require__.o(installedChunks, chunkId) && + installedChunks[chunkId] !== undefined + ) { + promises.push(loadUpdateChunk(chunkId, updatedModulesList)); + currentUpdateChunks[chunkId] = true; + } else { + currentUpdateChunks[chunkId] = false; + } + }); + if (__webpack_require__.f) { + __webpack_require__.f.jsonpHmr = function (chunkId, promises) { + if ( + currentUpdateChunks && + __webpack_require__.o(currentUpdateChunks, chunkId) && + !currentUpdateChunks[chunkId] + ) { + promises.push(loadUpdateChunk(chunkId)); + currentUpdateChunks[chunkId] = true; + } + }; + } +}; +__webpack_require__.hmrM = () => { + if (typeof fetch === "undefined") + throw new Error("No browser support: need fetch API"); + return fetch(__webpack_require__.p + __webpack_require__.hmrF()).then( + (response) => { + if (response.status === 404) return; // no update available + if (!response.ok) + throw new Error( + "Failed to fetch update manifest " + response.statusText + ); + return response.json(); + } + ); +}; +// install a JSONP callback for chunk loading +var __rspack_jsonp = (parentChunkLoadingFunction, data) => { + var [chunkIds, moreModules, runtime] = data; + // add "moreModules" to the modules object, + // then flag all "chunkIds" as loaded and fire callback + var moduleId, chunkId, i = 0; + if (chunkIds.some((id) => (installedChunks[id] !== 0))) { + for (moduleId in moreModules) { + if (__webpack_require__.o(moreModules, moduleId)) { + __webpack_require__.m[moduleId] = moreModules[moduleId]; + } + } + if (runtime) var result = runtime(__webpack_require__); + } + if (parentChunkLoadingFunction) parentChunkLoadingFunction(data); + for (; i < chunkIds.length; i++) { + chunkId = chunkIds[i]; + if ( + __webpack_require__.o(installedChunks, chunkId) && + installedChunks[chunkId] + ) { + installedChunks[chunkId][0](); + } + installedChunks[chunkId] = 0; + } + +}; + +var chunkLoadingGlobal = self["rspackChunk"] = self["rspackChunk"] || []; +chunkLoadingGlobal.forEach(__rspack_jsonp.bind(null, 0)); +chunkLoadingGlobal.push = __rspack_jsonp.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal)); + +})(); + +} +); +``` \ No newline at end of file diff --git a/tests/rspack-test/package.json b/tests/rspack-test/package.json index 764cb0272aba..5ce0a83fe7c2 100644 --- a/tests/rspack-test/package.json +++ b/tests/rspack-test/package.json @@ -13,7 +13,7 @@ "test:hot": "rstest --project hottest" }, "devDependencies": { - "@module-federation/runtime-tools": "^0.22.0", + "@module-federation/runtime-tools": "0.0.0-feat-shared-treeshake-poc-20260114091859", "@rspack/binding-testing": "workspace:*", "@rspack/cli": "workspace:*", "@rspack/core": "workspace:*", From fbf727b935e5ead5f0a7aed02a1db0abf0f206f9 Mon Sep 17 00:00:00 2001 From: "zhanghang.heal" Date: Tue, 3 Feb 2026 15:02:26 +0800 Subject: [PATCH 78/87] chore: use official version and update docs --- .../src/container/container_entry_module.rs | 3 +- packages/rspack/package.json | 2 +- pnpm-lock.yaml | 156 +++++++++--------- tests/e2e/package.json | 2 +- tests/rspack-test/package.json | 2 +- .../webpack/module-federation-plugin.mdx | 74 ++++++++- .../webpack/module-federation-plugin.mdx | 78 ++++++++- 7 files changed, 232 insertions(+), 85 deletions(-) diff --git a/crates/rspack_plugin_mf/src/container/container_entry_module.rs b/crates/rspack_plugin_mf/src/container/container_entry_module.rs index 67d096256e6d..d069e8abe09d 100644 --- a/crates/rspack_plugin_mf/src/container/container_entry_module.rs +++ b/crates/rspack_plugin_mf/src/container/container_entry_module.rs @@ -316,12 +316,13 @@ impl Module for ContainerEntryModule { __webpack_require__.federation = {{ instance: undefined,bundlerRuntime: undefined }} var factory = ()=>{factory}; var initShareContainer = {init_share_container_fn}; - {runtime}(exports, {{ + {runtime}({exports}, {{ get: function() {{ return factory;}}, init: function() {{ return initShareContainer;}} }}); "#, runtime = runtime_template.render_runtime_globals(&RuntimeGlobals::DEFINE_PROPERTY_GETTERS), + exports = runtime_template.render_exports_argument(ExportsArgument::Exports), factory = factory, init_share_container_fn = init_share_container_fn ); diff --git a/packages/rspack/package.json b/packages/rspack/package.json index 521a997c415a..28f0cd9ea254 100644 --- a/packages/rspack/package.json +++ b/packages/rspack/package.json @@ -70,7 +70,7 @@ "@rspack/lite-tapable": "1.1.0" }, "peerDependencies": { - "@module-federation/runtime-tools": "0.0.0-feat-shared-treeshake-poc-20260114091859", + "@module-federation/runtime-tools": "0.24.0", "@swc/helpers": ">=0.5.1" }, "peerDependenciesMeta": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fb78ae2a5860..08cf81641636 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -363,8 +363,8 @@ importers: packages/rspack: dependencies: '@module-federation/runtime-tools': - specifier: 0.0.0-feat-shared-treeshake-poc-20260114091859 - version: 0.0.0-feat-shared-treeshake-poc-20260114091859 + specifier: 0.24.0 + version: 0.24.0 '@rspack/binding': specifier: workspace:* version: link:../../crates/node_binding @@ -383,7 +383,7 @@ importers: version: 1.0.7 '@rsbuild/plugin-node-polyfill': specifier: ^1.4.3 - version: 1.4.3(@rsbuild/core@2.0.0-beta.0(@module-federation/runtime-tools@0.22.0)(core-js@3.47.0)) + version: 1.4.3(@rsbuild/core@2.0.0-beta.0(@module-federation/runtime-tools@0.24.0)(core-js@3.47.0)) '@rslib/core': specifier: 0.19.3 version: 0.19.3(@microsoft/api-extractor@7.55.2(@types/node@20.19.30))(typescript@5.9.3) @@ -661,8 +661,8 @@ importers: specifier: ^7.28.5 version: 7.28.5(@babel/core@7.28.6) '@module-federation/runtime-tools': - specifier: 0.0.0-feat-shared-treeshake-poc-20260114091859 - version: 0.0.0-feat-shared-treeshake-poc-20260114091859 + specifier: 0.24.0 + version: 0.24.0 '@playwright/test': specifier: 1.57.0 version: 1.57.0 @@ -736,8 +736,8 @@ importers: specifier: ^7.28.5 version: 7.28.5(@babel/core@7.28.6) '@module-federation/runtime-tools': - specifier: 0.0.0-feat-shared-treeshake-poc-20260114091859 - version: 0.0.0-feat-shared-treeshake-poc-20260114091859 + specifier: 0.24.0 + version: 0.24.0 '@rspack/binding-testing': specifier: workspace:* version: link:../../crates/rspack_binding_builder_testing @@ -984,22 +984,22 @@ importers: devDependencies: '@rsbuild/plugin-sass': specifier: ^1.5.0 - version: 1.5.0(@rsbuild/core@2.0.0-beta.0(@module-federation/runtime-tools@0.22.0)(core-js@3.47.0)) + version: 1.5.0(@rsbuild/core@2.0.0-beta.0(@module-federation/runtime-tools@0.24.0)(core-js@3.47.0)) '@rspress/core': specifier: ^2.0.1 - version: 2.0.1(@module-federation/runtime-tools@0.22.0)(@types/react@19.2.10)(core-js@3.47.0) + version: 2.0.1(@module-federation/runtime-tools@0.24.0)(@types/react@19.2.10)(core-js@3.47.0) '@rspress/plugin-algolia': specifier: ^2.0.1 - version: 2.0.1(@rspress/core@2.0.1(@module-federation/runtime-tools@0.22.0)(@types/react@19.2.10)(core-js@3.47.0))(@types/react@19.2.10)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(search-insights@2.17.3) + version: 2.0.1(@rspress/core@2.0.1(@module-federation/runtime-tools@0.24.0)(@types/react@19.2.10)(core-js@3.47.0))(@types/react@19.2.10)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(search-insights@2.17.3) '@rspress/plugin-client-redirects': specifier: ^2.0.1 - version: 2.0.1(@rspress/core@2.0.1(@module-federation/runtime-tools@0.22.0)(@types/react@19.2.10)(core-js@3.47.0)) + version: 2.0.1(@rspress/core@2.0.1(@module-federation/runtime-tools@0.24.0)(@types/react@19.2.10)(core-js@3.47.0)) '@rspress/plugin-rss': specifier: ^2.0.1 - version: 2.0.1(@rspress/core@2.0.1(@module-federation/runtime-tools@0.22.0)(@types/react@19.2.10)(core-js@3.47.0)) + version: 2.0.1(@rspress/core@2.0.1(@module-federation/runtime-tools@0.24.0)(@types/react@19.2.10)(core-js@3.47.0)) '@rspress/plugin-sitemap': specifier: ^2.0.1 - version: 2.0.1(@rspress/core@2.0.1(@module-federation/runtime-tools@0.22.0)(@types/react@19.2.10)(core-js@3.47.0)) + version: 2.0.1(@rspress/core@2.0.1(@module-federation/runtime-tools@0.24.0)(@types/react@19.2.10)(core-js@3.47.0)) '@shikijs/transformers': specifier: ^3.21.0 version: 3.21.0 @@ -1026,13 +1026,13 @@ importers: version: 1.0.4 rsbuild-plugin-google-analytics: specifier: 1.0.5 - version: 1.0.5(@rsbuild/core@2.0.0-beta.0(@module-federation/runtime-tools@0.22.0)(core-js@3.47.0)) + version: 1.0.5(@rsbuild/core@2.0.0-beta.0(@module-federation/runtime-tools@0.24.0)(core-js@3.47.0)) rsbuild-plugin-open-graph: specifier: 1.1.2 - version: 1.1.2(@rsbuild/core@2.0.0-beta.0(@module-federation/runtime-tools@0.22.0)(core-js@3.47.0)) + version: 1.1.2(@rsbuild/core@2.0.0-beta.0(@module-federation/runtime-tools@0.24.0)(core-js@3.47.0)) rspress-plugin-font-open-sans: specifier: 1.0.3 - version: 1.0.3(@rspress/core@2.0.1(@module-federation/runtime-tools@0.22.0)(@types/react@19.2.10)(core-js@3.47.0)) + version: 1.0.3(@rspress/core@2.0.1(@module-federation/runtime-tools@0.24.0)(@types/react@19.2.10)(core-js@3.47.0)) typescript: specifier: ^5.9.3 version: 5.9.3 @@ -2398,44 +2398,42 @@ packages: '@microsoft/tsdoc@0.16.0': resolution: {integrity: sha512-xgAyonlVVS+q7Vc7qLW0UrJU7rSFcETRWsqdXZtjzRU8dF+6CkozTK4V4y1LwOX7j8r/vHphjDeMeGI4tNGeGA==} - '@module-federation/error-codes@0.0.0-feat-shared-treeshake-poc-20260114091859': - resolution: {integrity: sha512-9OWijy+79YkHNWjuw0V8pLBoJPyIrjnVDfoC/2Ojg1QdWCRHld8oVj5JozU5J/GbFEzqm8ChOEmU6IWF5mNHNg==} - '@module-federation/error-codes@0.22.0': resolution: {integrity: sha512-xF9SjnEy7vTdx+xekjPCV5cIHOGCkdn3pIxo9vU7gEZMIw0SvAEdsy6Uh17xaCpm8V0FWvR0SZoK9Ik6jGOaug==} - '@module-federation/runtime-core@0.0.0-feat-shared-treeshake-poc-20260114091859': - resolution: {integrity: sha512-KmLnVDlMSeMRI3pnhhplO4f1t7j7CQJv49Wf+s6P4K6lRxoAD9+OOf29RDfo7Lqvux/nYfmxGGFUGJ8mh22QrA==} + '@module-federation/error-codes@0.24.0': + resolution: {integrity: sha512-T6rRYTHOZtFyni9ffZjfj5YbUDpQ7TAhP9TW0o2PVLk2ss3nmqWe6ZtN4o9PVt5wFOdktlE5p8+P+t1pAuKXPw==} '@module-federation/runtime-core@0.22.0': resolution: {integrity: sha512-GR1TcD6/s7zqItfhC87zAp30PqzvceoeDGYTgF3Vx2TXvsfDrhP6Qw9T4vudDQL3uJRne6t7CzdT29YyVxlgIA==} - '@module-federation/runtime-tools@0.0.0-feat-shared-treeshake-poc-20260114091859': - resolution: {integrity: sha512-v1sAMviM9OtPeOQKu4eW7SEo0d57M0ojWgI9rubvRdUX/lee3p02rpA8D8ouXsTvWR8zkBT+arrMhKwfv8/U+g==} + '@module-federation/runtime-core@0.24.0': + resolution: {integrity: sha512-f5kQZRfw00qK/KjyLuxbgtbYMPTMl7Dt4egRCgctSjVJZHibtL8BRLUr1Clf+Zr19Uhan2s90fo1Xs6rqgzvng==} '@module-federation/runtime-tools@0.22.0': resolution: {integrity: sha512-4ScUJ/aUfEernb+4PbLdhM/c60VHl698Gn1gY21m9vyC1Ucn69fPCA1y2EwcCB7IItseRMoNhdcWQnzt/OPCNA==} - '@module-federation/runtime@0.0.0-feat-shared-treeshake-poc-20260114091859': - resolution: {integrity: sha512-Sp+3lm1Z+7xZcBDkEozF78LSLhR3gAySSMKLhmv14NRls0EkPwEuaDZAS6SZwpWeZ9zubwch977jDq4hRcCgeA==} - deprecated: Pre-release version deprecated + '@module-federation/runtime-tools@0.24.0': + resolution: {integrity: sha512-3kffMSJBqV9M4HJ6a2+I8P/03PdeTD3mBLZ71czzmYtDpYPe7GGjpiSlJebW+dUYrlMeqWG4tKM20xWNfaj4QQ==} '@module-federation/runtime@0.22.0': resolution: {integrity: sha512-38g5iPju2tPC3KHMPxRKmy4k4onNp6ypFPS1eKGsNLUkXgHsPMBFqAjDw96iEcjri91BrahG4XcdyKi97xZzlA==} - '@module-federation/sdk@0.0.0-feat-shared-treeshake-poc-20260114091859': - resolution: {integrity: sha512-KD8otMLAzLNYGO7W6eGv0ddXt58KO4OJJ4NJsvCNpGDBf3XhbPUOWeswcGxk0dSiAcAGh9qLu9FEslRW+5/3AQ==} + '@module-federation/runtime@0.24.0': + resolution: {integrity: sha512-fZYLS3S0CwTP9SYiFmchPM1JZPqbR9GpiI4egSWsPrub53znMBMVtf4DAKfcpQFaaKTjsUZs1RxXmCyt30Uqzg==} '@module-federation/sdk@0.22.0': resolution: {integrity: sha512-x4aFNBKn2KVQRuNVC5A7SnrSCSqyfIWmm1DvubjbO9iKFe7ith5niw8dqSFBekYBg2Fwy+eMg4sEFNVvCAdo6g==} - '@module-federation/webpack-bundler-runtime@0.0.0-feat-shared-treeshake-poc-20260114091859': - resolution: {integrity: sha512-q+PPBcIT8rBUobBvS6eEcP9IZn9jBv796LNtpsYLwy643aAvMsRefAUJnI9KmMdJLQLareO6j/6uNkzYJ4mAmA==} - deprecated: Pre-release version deprecated + '@module-federation/sdk@0.24.0': + resolution: {integrity: sha512-3AxOPr3uKxLcT2Ek2ne3+5cUDrQ/0Ncoz3t2hgFqmHcZ+6sTPcEmS7Sr0T04yRCM/Dyv3TrJR8EebevRtILc2A==} '@module-federation/webpack-bundler-runtime@0.22.0': resolution: {integrity: sha512-aM8gCqXu+/4wBmJtVeMeeMN5guw3chf+2i6HajKtQv7SJfxV/f4IyNQJUeUQu9HfiAZHjqtMV5Lvq/Lvh8LdyA==} + '@module-federation/webpack-bundler-runtime@0.24.0': + resolution: {integrity: sha512-MAgRVgWi+LdxkGmL78RxunzZkJhAjOQAzYUYEXDR36wcKKKXynvgZWhTEpkyCG/wNB26QGPqHWgaT+lud8oYdQ==} + '@napi-rs/cli@3.0.4': resolution: {integrity: sha512-ilbCI69DVDQcIUSUB504LM1+Nhvo0jKycWAzzPJ22YwUoWrru/w0+V5sfjPINgkshQ4Ykv+oZOJXk9Kg1ZBUvg==} engines: {node: '>= 16'} @@ -9695,35 +9693,29 @@ snapshots: '@microsoft/tsdoc@0.16.0': {} - '@module-federation/error-codes@0.0.0-feat-shared-treeshake-poc-20260114091859': {} - '@module-federation/error-codes@0.22.0': {} - '@module-federation/runtime-core@0.0.0-feat-shared-treeshake-poc-20260114091859': - dependencies: - '@module-federation/error-codes': 0.0.0-feat-shared-treeshake-poc-20260114091859 - '@module-federation/sdk': 0.0.0-feat-shared-treeshake-poc-20260114091859 + '@module-federation/error-codes@0.24.0': {} '@module-federation/runtime-core@0.22.0': dependencies: '@module-federation/error-codes': 0.22.0 '@module-federation/sdk': 0.22.0 - '@module-federation/runtime-tools@0.0.0-feat-shared-treeshake-poc-20260114091859': + '@module-federation/runtime-core@0.24.0': dependencies: - '@module-federation/runtime': 0.0.0-feat-shared-treeshake-poc-20260114091859 - '@module-federation/webpack-bundler-runtime': 0.0.0-feat-shared-treeshake-poc-20260114091859 + '@module-federation/error-codes': 0.24.0 + '@module-federation/sdk': 0.24.0 '@module-federation/runtime-tools@0.22.0': dependencies: '@module-federation/runtime': 0.22.0 '@module-federation/webpack-bundler-runtime': 0.22.0 - '@module-federation/runtime@0.0.0-feat-shared-treeshake-poc-20260114091859': + '@module-federation/runtime-tools@0.24.0': dependencies: - '@module-federation/error-codes': 0.0.0-feat-shared-treeshake-poc-20260114091859 - '@module-federation/runtime-core': 0.0.0-feat-shared-treeshake-poc-20260114091859 - '@module-federation/sdk': 0.0.0-feat-shared-treeshake-poc-20260114091859 + '@module-federation/runtime': 0.24.0 + '@module-federation/webpack-bundler-runtime': 0.24.0 '@module-federation/runtime@0.22.0': dependencies: @@ -9731,20 +9723,26 @@ snapshots: '@module-federation/runtime-core': 0.22.0 '@module-federation/sdk': 0.22.0 - '@module-federation/sdk@0.0.0-feat-shared-treeshake-poc-20260114091859': {} + '@module-federation/runtime@0.24.0': + dependencies: + '@module-federation/error-codes': 0.24.0 + '@module-federation/runtime-core': 0.24.0 + '@module-federation/sdk': 0.24.0 '@module-federation/sdk@0.22.0': {} - '@module-federation/webpack-bundler-runtime@0.0.0-feat-shared-treeshake-poc-20260114091859': - dependencies: - '@module-federation/runtime': 0.0.0-feat-shared-treeshake-poc-20260114091859 - '@module-federation/sdk': 0.0.0-feat-shared-treeshake-poc-20260114091859 + '@module-federation/sdk@0.24.0': {} '@module-federation/webpack-bundler-runtime@0.22.0': dependencies: '@module-federation/runtime': 0.22.0 '@module-federation/sdk': 0.22.0 + '@module-federation/webpack-bundler-runtime@0.24.0': + dependencies: + '@module-federation/runtime': 0.24.0 + '@module-federation/sdk': 0.24.0 + '@napi-rs/cli@3.0.4(@emnapi/runtime@1.5.0)(@types/node@20.19.30)(emnapi@1.8.1(node-addon-api@7.1.1))': dependencies: '@inquirer/prompts': 7.8.6(@types/node@20.19.30) @@ -10211,9 +10209,9 @@ snapshots: core-js: 3.47.0 jiti: 2.6.1 - '@rsbuild/core@2.0.0-beta.0(@module-federation/runtime-tools@0.22.0)(core-js@3.47.0)': + '@rsbuild/core@2.0.0-beta.0(@module-federation/runtime-tools@0.24.0)(core-js@3.47.0)': dependencies: - '@rspack/core': 2.0.0-alpha.1(@module-federation/runtime-tools@0.22.0)(@swc/helpers@0.5.18) + '@rspack/core': 2.0.0-alpha.1(@module-federation/runtime-tools@0.24.0)(@swc/helpers@0.5.18) '@rspack/lite-tapable': 1.1.0 '@swc/helpers': 0.5.18 jiti: 2.6.1 @@ -10222,7 +10220,7 @@ snapshots: transitivePeerDependencies: - '@module-federation/runtime-tools' - '@rsbuild/plugin-node-polyfill@1.4.3(@rsbuild/core@2.0.0-beta.0(@module-federation/runtime-tools@0.22.0)(core-js@3.47.0))': + '@rsbuild/plugin-node-polyfill@1.4.3(@rsbuild/core@2.0.0-beta.0(@module-federation/runtime-tools@0.24.0)(core-js@3.47.0))': dependencies: assert: 2.1.0 browserify-zlib: 0.2.0 @@ -10248,19 +10246,19 @@ snapshots: util: 0.12.5 vm-browserify: 1.1.2 optionalDependencies: - '@rsbuild/core': 2.0.0-beta.0(@module-federation/runtime-tools@0.22.0)(core-js@3.47.0) + '@rsbuild/core': 2.0.0-beta.0(@module-federation/runtime-tools@0.24.0)(core-js@3.47.0) - '@rsbuild/plugin-react@1.4.5(@rsbuild/core@2.0.0-beta.0(@module-federation/runtime-tools@0.22.0)(core-js@3.47.0))': + '@rsbuild/plugin-react@1.4.5(@rsbuild/core@2.0.0-beta.0(@module-federation/runtime-tools@0.24.0)(core-js@3.47.0))': dependencies: - '@rsbuild/core': 2.0.0-beta.0(@module-federation/runtime-tools@0.22.0)(core-js@3.47.0) + '@rsbuild/core': 2.0.0-beta.0(@module-federation/runtime-tools@0.24.0)(core-js@3.47.0) '@rspack/plugin-react-refresh': 1.6.0(react-refresh@0.18.0) react-refresh: 0.18.0 transitivePeerDependencies: - webpack-hot-middleware - '@rsbuild/plugin-sass@1.5.0(@rsbuild/core@2.0.0-beta.0(@module-federation/runtime-tools@0.22.0)(core-js@3.47.0))': + '@rsbuild/plugin-sass@1.5.0(@rsbuild/core@2.0.0-beta.0(@module-federation/runtime-tools@0.24.0)(core-js@3.47.0))': dependencies: - '@rsbuild/core': 2.0.0-beta.0(@module-federation/runtime-tools@0.22.0)(core-js@3.47.0) + '@rsbuild/core': 2.0.0-beta.0(@module-federation/runtime-tools@0.24.0)(core-js@3.47.0) deepmerge: 4.3.1 loader-utils: 2.0.4 postcss: 8.5.6 @@ -10402,12 +10400,12 @@ snapshots: optionalDependencies: '@swc/helpers': 0.5.18 - '@rspack/core@2.0.0-alpha.1(@module-federation/runtime-tools@0.22.0)(@swc/helpers@0.5.18)': + '@rspack/core@2.0.0-alpha.1(@module-federation/runtime-tools@0.24.0)(@swc/helpers@0.5.18)': dependencies: '@rspack/binding': 2.0.0-alpha.1 '@rspack/lite-tapable': 1.1.0 optionalDependencies: - '@module-federation/runtime-tools': 0.22.0 + '@module-federation/runtime-tools': 0.24.0 '@swc/helpers': 0.5.18 '@rspack/dev-server@1.2.1(@rspack/core@packages+rspack)(webpack@5.102.1)': @@ -10461,13 +10459,13 @@ snapshots: html-entities: 2.6.0 react-refresh: 0.18.0 - '@rspress/core@2.0.1(@module-federation/runtime-tools@0.22.0)(@types/react@19.2.10)(core-js@3.47.0)': + '@rspress/core@2.0.1(@module-federation/runtime-tools@0.24.0)(@types/react@19.2.10)(core-js@3.47.0)': dependencies: '@mdx-js/mdx': 3.1.1 '@mdx-js/react': 3.1.1(@types/react@19.2.10)(react@19.2.4) - '@rsbuild/core': 2.0.0-beta.0(@module-federation/runtime-tools@0.22.0)(core-js@3.47.0) - '@rsbuild/plugin-react': 1.4.5(@rsbuild/core@2.0.0-beta.0(@module-federation/runtime-tools@0.22.0)(core-js@3.47.0)) - '@rspress/shared': 2.0.1(@module-federation/runtime-tools@0.22.0)(core-js@3.47.0) + '@rsbuild/core': 2.0.0-beta.0(@module-federation/runtime-tools@0.24.0)(core-js@3.47.0) + '@rsbuild/plugin-react': 1.4.5(@rsbuild/core@2.0.0-beta.0(@module-federation/runtime-tools@0.24.0)(core-js@3.47.0)) + '@rspress/shared': 2.0.1(@module-federation/runtime-tools@0.24.0)(core-js@3.47.0) '@shikijs/rehype': 3.21.0 '@types/unist': 3.0.3 '@unhead/react': 2.1.2(react@19.2.4) @@ -10512,33 +10510,33 @@ snapshots: - supports-color - webpack-hot-middleware - '@rspress/plugin-algolia@2.0.1(@rspress/core@2.0.1(@module-federation/runtime-tools@0.22.0)(@types/react@19.2.10)(core-js@3.47.0))(@types/react@19.2.10)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(search-insights@2.17.3)': + '@rspress/plugin-algolia@2.0.1(@rspress/core@2.0.1(@module-federation/runtime-tools@0.24.0)(@types/react@19.2.10)(core-js@3.47.0))(@types/react@19.2.10)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(search-insights@2.17.3)': dependencies: '@docsearch/css': 4.5.3 '@docsearch/react': 4.5.3(@types/react@19.2.10)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(search-insights@2.17.3) - '@rspress/core': 2.0.1(@module-federation/runtime-tools@0.22.0)(@types/react@19.2.10)(core-js@3.47.0) + '@rspress/core': 2.0.1(@module-federation/runtime-tools@0.24.0)(@types/react@19.2.10)(core-js@3.47.0) transitivePeerDependencies: - '@types/react' - react - react-dom - search-insights - '@rspress/plugin-client-redirects@2.0.1(@rspress/core@2.0.1(@module-federation/runtime-tools@0.22.0)(@types/react@19.2.10)(core-js@3.47.0))': + '@rspress/plugin-client-redirects@2.0.1(@rspress/core@2.0.1(@module-federation/runtime-tools@0.24.0)(@types/react@19.2.10)(core-js@3.47.0))': dependencies: - '@rspress/core': 2.0.1(@module-federation/runtime-tools@0.22.0)(@types/react@19.2.10)(core-js@3.47.0) + '@rspress/core': 2.0.1(@module-federation/runtime-tools@0.24.0)(@types/react@19.2.10)(core-js@3.47.0) - '@rspress/plugin-rss@2.0.1(@rspress/core@2.0.1(@module-federation/runtime-tools@0.22.0)(@types/react@19.2.10)(core-js@3.47.0))': + '@rspress/plugin-rss@2.0.1(@rspress/core@2.0.1(@module-federation/runtime-tools@0.24.0)(@types/react@19.2.10)(core-js@3.47.0))': dependencies: - '@rspress/core': 2.0.1(@module-federation/runtime-tools@0.22.0)(@types/react@19.2.10)(core-js@3.47.0) + '@rspress/core': 2.0.1(@module-federation/runtime-tools@0.24.0)(@types/react@19.2.10)(core-js@3.47.0) feed: 4.2.2 - '@rspress/plugin-sitemap@2.0.1(@rspress/core@2.0.1(@module-federation/runtime-tools@0.22.0)(@types/react@19.2.10)(core-js@3.47.0))': + '@rspress/plugin-sitemap@2.0.1(@rspress/core@2.0.1(@module-federation/runtime-tools@0.24.0)(@types/react@19.2.10)(core-js@3.47.0))': dependencies: - '@rspress/core': 2.0.1(@module-federation/runtime-tools@0.22.0)(@types/react@19.2.10)(core-js@3.47.0) + '@rspress/core': 2.0.1(@module-federation/runtime-tools@0.24.0)(@types/react@19.2.10)(core-js@3.47.0) - '@rspress/shared@2.0.1(@module-federation/runtime-tools@0.22.0)(core-js@3.47.0)': + '@rspress/shared@2.0.1(@module-federation/runtime-tools@0.24.0)(core-js@3.47.0)': dependencies: - '@rsbuild/core': 2.0.0-beta.0(@module-federation/runtime-tools@0.22.0)(core-js@3.47.0) + '@rsbuild/core': 2.0.0-beta.0(@module-federation/runtime-tools@0.24.0)(core-js@3.47.0) '@shikijs/rehype': 3.21.0 gray-matter: 4.0.3 lodash-es: 4.17.23 @@ -15290,13 +15288,13 @@ snapshots: '@microsoft/api-extractor': 7.55.2(@types/node@20.19.30) typescript: 5.9.3 - rsbuild-plugin-google-analytics@1.0.5(@rsbuild/core@2.0.0-beta.0(@module-federation/runtime-tools@0.22.0)(core-js@3.47.0)): + rsbuild-plugin-google-analytics@1.0.5(@rsbuild/core@2.0.0-beta.0(@module-federation/runtime-tools@0.24.0)(core-js@3.47.0)): optionalDependencies: - '@rsbuild/core': 2.0.0-beta.0(@module-federation/runtime-tools@0.22.0)(core-js@3.47.0) + '@rsbuild/core': 2.0.0-beta.0(@module-federation/runtime-tools@0.24.0)(core-js@3.47.0) - rsbuild-plugin-open-graph@1.1.2(@rsbuild/core@2.0.0-beta.0(@module-federation/runtime-tools@0.22.0)(core-js@3.47.0)): + rsbuild-plugin-open-graph@1.1.2(@rsbuild/core@2.0.0-beta.0(@module-federation/runtime-tools@0.24.0)(core-js@3.47.0)): optionalDependencies: - '@rsbuild/core': 2.0.0-beta.0(@module-federation/runtime-tools@0.22.0)(core-js@3.47.0) + '@rsbuild/core': 2.0.0-beta.0(@module-federation/runtime-tools@0.24.0)(core-js@3.47.0) rspack-vue-loader@17.4.5(vue@3.5.27(typescript@5.9.3))(webpack@5.102.1): dependencies: @@ -15306,9 +15304,9 @@ snapshots: optionalDependencies: vue: 3.5.27(typescript@5.9.3) - rspress-plugin-font-open-sans@1.0.3(@rspress/core@2.0.1(@module-federation/runtime-tools@0.22.0)(@types/react@19.2.10)(core-js@3.47.0)): + rspress-plugin-font-open-sans@1.0.3(@rspress/core@2.0.1(@module-federation/runtime-tools@0.24.0)(@types/react@19.2.10)(core-js@3.47.0)): dependencies: - '@rspress/core': 2.0.1(@module-federation/runtime-tools@0.22.0)(@types/react@19.2.10)(core-js@3.47.0) + '@rspress/core': 2.0.1(@module-federation/runtime-tools@0.24.0)(@types/react@19.2.10)(core-js@3.47.0) run-applescript@7.1.0: {} diff --git a/tests/e2e/package.json b/tests/e2e/package.json index ccb73c7a42d5..ffa5b7eb6178 100644 --- a/tests/e2e/package.json +++ b/tests/e2e/package.json @@ -16,7 +16,7 @@ "@rspack/browser": "workspace:*", "@rspack/dev-server": "~1.2.1", "@rspack/plugin-react-refresh": "^1.6.0", - "@module-federation/runtime-tools": "0.0.0-feat-shared-treeshake-poc-20260114091859", + "@module-federation/runtime-tools": "0.24.0", "@swc/helpers": "0.5.18", "@types/fs-extra": "11.0.4", "babel-loader": "^10.0.0", diff --git a/tests/rspack-test/package.json b/tests/rspack-test/package.json index d0519f730fd2..68a0d77a7e73 100644 --- a/tests/rspack-test/package.json +++ b/tests/rspack-test/package.json @@ -15,7 +15,7 @@ "devDependencies": { "@babel/core": "^7.28.6", "@babel/preset-react": "^7.28.5", - "@module-federation/runtime-tools": "0.0.0-feat-shared-treeshake-poc-20260114091859", + "@module-federation/runtime-tools": "0.24.0", "@rspack/binding-testing": "workspace:*", "@rspack/cli": "workspace:*", "@rspack/core": "workspace:*", diff --git a/website/docs/en/plugins/webpack/module-federation-plugin.mdx b/website/docs/en/plugins/webpack/module-federation-plugin.mdx index 6f0efa590541..35b0a908316e 100644 --- a/website/docs/en/plugins/webpack/module-federation-plugin.mdx +++ b/website/docs/en/plugins/webpack/module-federation-plugin.mdx @@ -162,10 +162,15 @@ The SharedConfig can include the following sub-options: - singleton: Ensure that shared modules are only loaded once between different versions, following the singleton pattern. This is necessary for libraries designed to run as singletons, such as React, as it can prevent various issues caused by instantiating multiple library instances. - strictVersion: Used to strengthen `requiredVersion`. If set to `true`, the shared module must match the version specified in requiredVersion exactly, otherwise an error will be reported and the module will not be loaded. If set to `false`, it can tolerate imprecise matching. - version: Explicitly set the version of the shared module. By default, the version in `package.json` will be used. +- treeShaking: Configure the treeshaking behavior of shared dependencies. By enabling treeshaking for shared dependencies, the size of shared dependencies can be reduced. Only effective when using Rspack as the build tool. + - usedExports: Manually **add** export members used by shared dependencies. + - mode: Configure the loading strategy for treeshaking. + - `runtime-infer`: Infer based on the consumer's `usedExports`. If the provider's `usedExports` match the consumer's `usedExports`, the provider's `shared` will be used; otherwise, the consumer's own `shared` will be used. If neither condition is met, the full version is used. + - `server-calc`: Decide whether to load shared dependencies based on the snapshot sent by the server. ### manifest - + - Type: ```ts @@ -190,6 +195,73 @@ When enabled, the plugin emits both `mf-manifest.json` and `mf-stats.json` (you - `fileName`: Manifest file name. When set, the stats file automatically appends a `-stats` suffix (for example, `fileName: 'mf.json'` produces `mf.json` and `mf-stats.json`). All files are emitted into the directory defined by `filePath` (if provided). - `disableAssetsAnalyze`: Disables asset analysis. When `true`, the manifest omits the `shared` and `exposes` fields, and the `remotes` entries will not include asset information. +### injectTreeShakingUsedExports + + + +Whether to inject the exports used by shared into the bundler runtime. + +- Type: `boolean` +- Required: No +- Default: `undefined` + +This option is used to control whether to inject the actual used export information of shared modules into the bundler runtime for more precise dependency management and optimization. + +If you are using mode as 'server-calc', it is recommended to set this option to `false`. + +### treeShakingDir + +Directory for outputting tree shaking shared fallback resources. + +- Type: `string` +- Required: No +- Default: `undefined` + +When shared dependency tree shaking is enabled, Module Federation splits unused shared module exports. This option specifies the output directory for these fallback resources. + +### treeShakingSharedExcludePlugins + +Configure plugin names to exclude during the shared dependency tree shaking/fallback build process. + +- Type: `string[]` +- Required: No +- Default: `['HtmlWebpackPlugin','HtmlRspackPlugin']` + +Allows users to specify a set of plugin names that will be ignored or not involved in processing during the shared dependency tree shaking/fallback build process. + +### treeShakingSharedPlugins + +Allows users to explicitly specify which plugins should participate in the second treeshaking process for shared modules. + +- Type: `string[]` +- Required: No +- Default: `undefined` + +If `shared.treeShaking.mode` is set to 'server-calc', then in the deployment service, the shared dependencies that need tree shaking will be rebuilt. At this time, only shared dependencies are built, and the original project's build configuration will not be loaded. +If your project has special build configurations, such as setting externals, you can integrate these build configurations into an NPM Package, and then fill in the name and version of this plugin in `treeShakingSharedPlugins`, so that it can participate in the treeshaking process of shared modules in the second treeshaking process. + +For example, a plugin `my-build-plugin` is provided, which sets `externals`: + +```ts title='my-build-plugin' +class MyBuildPlugin { + apply(compiler) { + compiler.options.externals = { + react: 'React', + }; + } +} +export default MyBuildPlugin; +``` + +Publish this plugin version as `0.0.2`, then you only need to fill in the plugin name and version in `treeShakingSharedPlugins`: + +```ts title='module-federation.config.ts' +export default { + // ... + treeShakingSharedPlugins: ['my-build-plugin@0.0.2'], +}; +``` + ## FAQ - Found non-downgraded syntax in the build output? diff --git a/website/docs/zh/plugins/webpack/module-federation-plugin.mdx b/website/docs/zh/plugins/webpack/module-federation-plugin.mdx index e142e78cb811..e2b35d6d68e6 100644 --- a/website/docs/zh/plugins/webpack/module-federation-plugin.mdx +++ b/website/docs/zh/plugins/webpack/module-federation-plugin.mdx @@ -146,6 +146,10 @@ export default { singleton?: boolean; strictVersion?: boolean; version?: false | string; + treeShaking?: { + mode: 'runtime-infer' | 'server-calc'; + usedExports?: string[]; + }; } ``` @@ -162,10 +166,15 @@ export default { - singleton:确保共享模块在不同版本间只会被加载一次,遵守单例模式。这对于一些设计为单例运行的库(如 React)是很有必要的,因为这样可以避免由于实例化了多个库实例而导致的各种问题。 - strictVersion:用来强化 `requiredVersion`。如果设置为 `true`,那么必须精确地匹配 `requiredVersion` 中规定的版本,否则共享模块会报错并且不会加载该模块。如果设置为 `false`,那么可以容忍不精确的匹配。 - version:显式地设置共享模块的版本。默认会使用 `package.json` 中的版本。 +- treeShaking:配置 shared 依赖的 treeshaking 行为。通过开启 shared 依赖的 treeshaking,可以减少共享依赖的体积。 + - usedExports:手动**添加**共享依赖被使用的导出成员。 + - mode:配置 treeshaking 的加载策略。 + - `runtime-infer`: 根据消费方的 `usedExports` 进行推断,如果提供方的 `usedExports` 符合当前消费方的 `usedExports`,那么就会使用提供方的 `shared`,否则会使用消费方自身的 `shared`,如果都不满足,就使用全量的。 + - `server-calc`: 根据服务端下发的 snapshot 来决定是否加载共享依赖。 ### manifest - + - 类型: ```ts @@ -188,6 +197,73 @@ export default { - fileName:manifest 文件名称,如果设置了 `fileName`,对应的 stats 文件名会自动附加 `-stats` 后缀(例如 `fileName: 'mf.json'` 时会同时生成 `mf.json` 与 `mf-stats.json`)。所有文件都会写入 `filePath`(若配置)指定的子目录。 - disableAssetsAnalyze:禁用产物分析,如果设置为 true ,那么 manifest 中将不会有 shared 、exposes 字段,且 remotes 中也不会有 assets 。 +### injectTreeShakingUsedExports + + + +是否将 shared 使用的 exports 注入到 bundler runtime 中。 + +- 类型:`boolean` +- 是否必填:否 +- 默认值:`undefined` + +此选项用于控制是否将共享模块中实际使用的导出信息注入到打包器的运行时中,以便进行更精确的依赖管理和优化。 + +如果你使用的是 mode 为 'server-calc',那么推荐将此选项设置为 `false`。 + +### treeShakingDir + +用于输出 tree shaking 共享 fallback 资源的目录。 + +- 类型:`string` +- 是否必填:否 +- 默认值:`undefined` + +当启用共享依赖 tree shaking 功能时,Module Federation 会将未使用的共享模块导出拆分出来。该选项指定了这些 fallback 资源的输出目录。 + +### treeShakingSharedExcludePlugins + +配置在构建共享依赖 tree shaking/fallback 过程中需要排除的插件名称。 + +- 类型:`string[]` +- 是否必填:否 +- 默认值:`['HtmlWebpackPlugin','HtmlRspackPlugin']` + +允许用户指定一组插件名称,这些插件在构建共享依赖 tree shaking/fallback 过程 时将被忽略或不参与处理。 + +### treeShakingSharedPlugins + +允许用户显式指定哪些插件应该参与 shared 模块的第二次 treeshaking 过程。 + +- 类型:`string[]` +- 是否必填:否 +- 默认值:`undefined` + +如果设置了 `shared.treeShaking.mode` 为 'server-calc',那么在部署服务中,会重新构建需要 tree shaking 的共享依赖,此时仅构建共享依赖,不会加载原项目的构建配置。 +如果你的项目有特殊的构建配置,例如设置了 externals ,那么你可以把这些构建配置集成到一个 NPM Package ,然后在 `treeShakingSharedPlugins` 中填写此插件的名称和版本,这样就可以在第二次 treeshaking 过程中参与 shared 模块的 treeshaking 过程。 + +例如提供了一个插件 `my-build-plugin`,它会设置 `externals`: + +```ts title='my-build-plugin' +class MyBuildPlugin { + apply(compiler) { + compiler.options.externals = { + react: 'React', + }; + } +} +export default MyBuildPlugin; +``` + +将此插件发布的版本为 `0.0.2` ,那么此时只需要在 `treeShakingSharedPlugins` 中填写插件的名称和版本即可: + +```ts title='module-federation.config.ts' +export default { + // ... + treeShakingSharedPlugins: ['my-build-plugin@0.0.2'], +}; +``` + ## 常见问题 - 构建产物中存在未降级语法? From 9fbc69ca8b13fdeb9ea344355695785d5ec027e4 Mon Sep 17 00:00:00 2001 From: "zhanghang.heal" Date: Tue, 3 Feb 2026 16:27:14 +0800 Subject: [PATCH 79/87] chore: fix cargo clippy --- .../cache/persistent/build_dependencies/mod.rs | 18 +++++++++++++++--- .../esm/esm_import_specifier_dependency.rs | 2 +- .../src/plugin/flag_dependency_usage_plugin.rs | 16 +++++----------- .../src/container/container_entry_module.rs | 14 +++++--------- .../container/container_exposed_dependency.rs | 2 +- .../src/sharing/collect_shared_entry_plugin.rs | 9 +++------ .../shared_used_exports_optimizer_plugin.rs | 5 +---- ...ed_used_exports_optimizer_runtime_module.rs | 4 +--- .../benches/groups/build_chunk_graph.rs | 2 +- 9 files changed, 33 insertions(+), 39 deletions(-) diff --git a/crates/rspack_core/src/cache/persistent/build_dependencies/mod.rs b/crates/rspack_core/src/cache/persistent/build_dependencies/mod.rs index a2ce6c190209..249aea05b419 100644 --- a/crates/rspack_core/src/cache/persistent/build_dependencies/mod.rs +++ b/crates/rspack_core/src/cache/persistent/build_dependencies/mod.rs @@ -165,15 +165,27 @@ mod test { SnapshotOptions::default(), fs.clone(), storage.clone(), - codec, + codec.clone(), )); - let mut build_deps = BuildDeps::new(&options, fs.clone(), snapshot.clone(), storage.clone()); + let mut build_deps = BuildDeps::new( + &options, + fs.clone(), + snapshot.clone(), + storage.clone(), + codec.clone(), + ); let warnings = build_deps.add(vec![].into_iter()).await; assert_eq!(warnings.len(), 1); let data = storage.load(scope).await.expect("should load success"); assert_eq!(data.len(), 9); - let mut build_deps = BuildDeps::new(&options, fs.clone(), snapshot.clone(), storage.clone()); + let mut build_deps = BuildDeps::new( + &options, + fs.clone(), + snapshot.clone(), + storage.clone(), + codec, + ); fs.write("/b.js".into(), r#"require("./c")"#.as_bytes()) .await .unwrap(); diff --git a/crates/rspack_plugin_javascript/src/dependency/esm/esm_import_specifier_dependency.rs b/crates/rspack_plugin_javascript/src/dependency/esm/esm_import_specifier_dependency.rs index dc562d2f0c1f..90a8246bb619 100644 --- a/crates/rspack_plugin_javascript/src/dependency/esm/esm_import_specifier_dependency.rs +++ b/crates/rspack_plugin_javascript/src/dependency/esm/esm_import_specifier_dependency.rs @@ -121,7 +121,7 @@ impl ESMImportSpecifierDependency { && id == "default" { match exports_type { - Some(ExportsType::DefaultOnly) | Some(ExportsType::DefaultWithNamed) => { + Some(ExportsType::DefaultOnly | ExportsType::DefaultWithNamed) => { if ids.len() == 1 { return self.get_referenced_exports_in_destructuring(None); } diff --git a/crates/rspack_plugin_javascript/src/plugin/flag_dependency_usage_plugin.rs b/crates/rspack_plugin_javascript/src/plugin/flag_dependency_usage_plugin.rs index d61376878dc1..1ee3eb59c61f 100644 --- a/crates/rspack_plugin_javascript/src/plugin/flag_dependency_usage_plugin.rs +++ b/crates/rspack_plugin_javascript/src/plugin/flag_dependency_usage_plugin.rs @@ -298,17 +298,11 @@ impl<'a> FlagDependencyUsagePluginProxy<'a> { ) .await; - match referenced_exports_result { - Some(mut referenced_exports) => { - if let Some(new_referenced_exports) = - merge_referenced_exports(old_referenced_exports, referenced_exports) - { - map.insert(module_id, new_referenced_exports); - } - } - None => { - continue; - } + if let Some(mut referenced_exports) = referenced_exports_result + && let Some(new_referenced_exports) = + merge_referenced_exports(old_referenced_exports, referenced_exports) + { + map.insert(module_id, new_referenced_exports); } } diff --git a/crates/rspack_plugin_mf/src/container/container_entry_module.rs b/crates/rspack_plugin_mf/src/container/container_entry_module.rs index d069e8abe09d..d7dbaa763e9a 100644 --- a/crates/rspack_plugin_mf/src/container/container_entry_module.rs +++ b/crates/rspack_plugin_mf/src/container/container_entry_module.rs @@ -262,13 +262,11 @@ impl Module for ContainerEntryModule { if let Some(dependency) = dependency .as_any() .downcast_ref::() + && *dependency.dependency_type() == DependencyType::ShareContainerFallback { - if *dependency.dependency_type() == DependencyType::ShareContainerFallback { - let request: &str = dependency.user_request(); - let module_expr = - runtime_template.module_raw(compilation, dependency_id, request, false); - factory = runtime_template.returning_function(&module_expr, ""); - } + let request: &str = dependency.user_request(); + let module_expr = runtime_template.module_raw(compilation, dependency_id, request, false); + factory = runtime_template.returning_function(&module_expr, ""); } } @@ -303,9 +301,7 @@ impl Module for ContainerEntryModule { {federation_global}.installInitialConsumes = {install_initial_consumes_fn}; return {federation_global}.installInitialConsumes(); - "#, - federation_global = federation_global, - install_initial_consumes_fn = install_initial_consumes_fn + "# ); let init_share_container_fn = runtime_template.basic_function("mfInstance, bundlerRuntime", &init_body); diff --git a/crates/rspack_plugin_mf/src/container/container_exposed_dependency.rs b/crates/rspack_plugin_mf/src/container/container_exposed_dependency.rs index 789d76ed39d3..f903355c5882 100644 --- a/crates/rspack_plugin_mf/src/container/container_exposed_dependency.rs +++ b/crates/rspack_plugin_mf/src/container/container_exposed_dependency.rs @@ -29,7 +29,7 @@ impl ContainerExposedDependency { } pub fn new_shared_fallback(request: String) -> Self { - let resource_identifier = format!("share-container-fallback:{}", request).into(); + let resource_identifier = format!("share-container-fallback:{request}").into(); Self { id: DependencyId::new(), request, diff --git a/crates/rspack_plugin_mf/src/sharing/collect_shared_entry_plugin.rs b/crates/rspack_plugin_mf/src/sharing/collect_shared_entry_plugin.rs index 25d0ad11ee6b..9aa2493b5c59 100644 --- a/crates/rspack_plugin_mf/src/sharing/collect_shared_entry_plugin.rs +++ b/crates/rspack_plugin_mf/src/sharing/collect_shared_entry_plugin.rs @@ -103,7 +103,7 @@ async fn process_assets(&self, compilation: &mut Compilation) -> Result<()> { let mut ordered_requests: FxHashMap> = FxHashMap::default(); let mut share_scopes: FxHashMap = FxHashMap::default(); - for (_id, module) in module_graph.modules().into_iter() { + for (_id, module) in module_graph.modules() { let module_type = module.module_type(); if !matches!(module_type, rspack_core::ModuleType::ConsumeShared) { continue; @@ -167,7 +167,7 @@ async fn process_assets(&self, compilation: &mut Compilation) -> Result<()> { let version = self .infer_version(&resource) .await - .unwrap_or_else(|| "".to_string()); + .unwrap_or_else(String::new); let pair = [resource, version]; if !reqs.iter().any(|p| p[0] == pair[0] && p[1] == pair[1]) { reqs.push(pair); @@ -185,10 +185,7 @@ async fn process_assets(&self, compilation: &mut Compilation) -> Result<()> { // Build asset content let mut shared: FxHashMap<&str, CollectSharedEntryAssetItem<'_>> = FxHashMap::default(); for (share_key, requests) in ordered_requests.iter() { - let scope = share_scopes - .get(share_key) - .map(|s| s.as_str()) - .unwrap_or(""); + let scope = share_scopes.get(share_key).map_or("", |s| s.as_str()); shared.insert( share_key.as_str(), CollectSharedEntryAssetItem { diff --git a/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_plugin.rs b/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_plugin.rs index fa2f3d1b07e0..2b34bbb8e748 100644 --- a/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_plugin.rs +++ b/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_plugin.rs @@ -166,10 +166,7 @@ async fn optimize_dependencies( } let share_key_part = parts[1]; let share_key_end = if let Some(stripped) = share_key_part.strip_prefix('@') { - stripped - .find('@') - .map(|i| i + 1) - .unwrap_or(share_key_part.len()) + stripped.find('@').map_or(share_key_part.len(), |i| i + 1) } else { share_key_part.find('@').unwrap_or(share_key_part.len()) }; diff --git a/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_runtime_module.rs b/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_runtime_module.rs index 70a9f4b1044e..3ccbb5064b9d 100644 --- a/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_runtime_module.rs +++ b/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_runtime_module.rs @@ -70,9 +70,7 @@ impl RuntimeModule for SharedUsedExportsOptimizerRuntimeModule { r#" if(!{federation_global}){{return;}} {federation_global}.usedExports = {used_exports_json}; -"#, - federation_global = federation_global, - used_exports_json = used_exports_json +"# )) } } diff --git a/xtask/benchmark/benches/groups/build_chunk_graph.rs b/xtask/benchmark/benches/groups/build_chunk_graph.rs index 47f56368f3cf..4dc3db744646 100644 --- a/xtask/benchmark/benches/groups/build_chunk_graph.rs +++ b/xtask/benchmark/benches/groups/build_chunk_graph.rs @@ -5,7 +5,7 @@ use criterion::criterion_group; use rspack::builder::Builder as _; use rspack_benchmark::Criterion; use rspack_core::{ - Compilation, Compiler, Experiments, Optimization, build_chunk_graph, + Compilation, Compiler, Optimization, build_chunk_graph, build_module_graph::build_module_graph_pass, fast_set, incremental::{Incremental, IncrementalOptions}, From 7ef330acff015bdc055ba9bfd2358cabc2213308 Mon Sep 17 00:00:00 2001 From: "zhanghang.heal" Date: Tue, 3 Feb 2026 22:09:22 +0800 Subject: [PATCH 80/87] chore: bump --- packages/rspack/package.json | 2 +- pnpm-lock.yaml | 92 ++++++++++++++++++++++++++++++---- tests/e2e/package.json | 2 +- tests/rspack-test/package.json | 2 +- 4 files changed, 84 insertions(+), 14 deletions(-) diff --git a/packages/rspack/package.json b/packages/rspack/package.json index 18cfff926374..0a29408141e2 100644 --- a/packages/rspack/package.json +++ b/packages/rspack/package.json @@ -70,7 +70,7 @@ "@rspack/lite-tapable": "1.1.0" }, "peerDependencies": { - "@module-federation/runtime-tools": "0.24.0", + "@module-federation/runtime-tools": "0.0.0-fix-loop-load-20260203135642", "@swc/helpers": ">=0.5.1" }, "peerDependenciesMeta": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 08cf81641636..d4ada1dace1b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -363,8 +363,8 @@ importers: packages/rspack: dependencies: '@module-federation/runtime-tools': - specifier: 0.24.0 - version: 0.24.0 + specifier: 0.0.0-fix-loop-load-20260203135642 + version: 0.0.0-fix-loop-load-20260203135642 '@rspack/binding': specifier: workspace:* version: link:../../crates/node_binding @@ -383,7 +383,7 @@ importers: version: 1.0.7 '@rsbuild/plugin-node-polyfill': specifier: ^1.4.3 - version: 1.4.3(@rsbuild/core@2.0.0-beta.0(@module-federation/runtime-tools@0.24.0)(core-js@3.47.0)) + version: 1.4.3(@rsbuild/core@2.0.0-beta.0(@module-federation/runtime-tools@0.0.0-fix-loop-load-20260203135642)(core-js@3.47.0)) '@rslib/core': specifier: 0.19.3 version: 0.19.3(@microsoft/api-extractor@7.55.2(@types/node@20.19.30))(typescript@5.9.3) @@ -661,8 +661,8 @@ importers: specifier: ^7.28.5 version: 7.28.5(@babel/core@7.28.6) '@module-federation/runtime-tools': - specifier: 0.24.0 - version: 0.24.0 + specifier: 0.0.0-fix-loop-load-20260203135642 + version: 0.0.0-fix-loop-load-20260203135642 '@playwright/test': specifier: 1.57.0 version: 1.57.0 @@ -736,8 +736,8 @@ importers: specifier: ^7.28.5 version: 7.28.5(@babel/core@7.28.6) '@module-federation/runtime-tools': - specifier: 0.24.0 - version: 0.24.0 + specifier: 0.0.0-fix-loop-load-20260203135642 + version: 0.0.0-fix-loop-load-20260203135642 '@rspack/binding-testing': specifier: workspace:* version: link:../../crates/rspack_binding_builder_testing @@ -2398,36 +2398,54 @@ packages: '@microsoft/tsdoc@0.16.0': resolution: {integrity: sha512-xgAyonlVVS+q7Vc7qLW0UrJU7rSFcETRWsqdXZtjzRU8dF+6CkozTK4V4y1LwOX7j8r/vHphjDeMeGI4tNGeGA==} + '@module-federation/error-codes@0.0.0-fix-loop-load-20260203135642': + resolution: {integrity: sha512-hyGxZ/7MNl4zx4YpdjfUHsioIpe8kVYT5HBHf6AhPOnkghrjRSnl2VEXKX51rNeMFEckgGiZfnkAJxIPa+Bd7A==} + '@module-federation/error-codes@0.22.0': resolution: {integrity: sha512-xF9SjnEy7vTdx+xekjPCV5cIHOGCkdn3pIxo9vU7gEZMIw0SvAEdsy6Uh17xaCpm8V0FWvR0SZoK9Ik6jGOaug==} '@module-federation/error-codes@0.24.0': resolution: {integrity: sha512-T6rRYTHOZtFyni9ffZjfj5YbUDpQ7TAhP9TW0o2PVLk2ss3nmqWe6ZtN4o9PVt5wFOdktlE5p8+P+t1pAuKXPw==} + '@module-federation/runtime-core@0.0.0-fix-loop-load-20260203135642': + resolution: {integrity: sha512-CqJHB4xW/ZlfYYeGbRO8t9hFnPHOjEGG67qrODS72lMx5lWm1aFlao32ZWr8VGUiU+/f7iDzILKXpdMPBGWkDw==} + '@module-federation/runtime-core@0.22.0': resolution: {integrity: sha512-GR1TcD6/s7zqItfhC87zAp30PqzvceoeDGYTgF3Vx2TXvsfDrhP6Qw9T4vudDQL3uJRne6t7CzdT29YyVxlgIA==} '@module-federation/runtime-core@0.24.0': resolution: {integrity: sha512-f5kQZRfw00qK/KjyLuxbgtbYMPTMl7Dt4egRCgctSjVJZHibtL8BRLUr1Clf+Zr19Uhan2s90fo1Xs6rqgzvng==} + '@module-federation/runtime-tools@0.0.0-fix-loop-load-20260203135642': + resolution: {integrity: sha512-0DcSPhKaaBp9dROvSqtEhJw+28F65oA6E3kLCPgcKWyFeM7wE6Sz20QV/PszsAq7Y1VRWzK5B2EpE5D6bbixTQ==} + '@module-federation/runtime-tools@0.22.0': resolution: {integrity: sha512-4ScUJ/aUfEernb+4PbLdhM/c60VHl698Gn1gY21m9vyC1Ucn69fPCA1y2EwcCB7IItseRMoNhdcWQnzt/OPCNA==} '@module-federation/runtime-tools@0.24.0': resolution: {integrity: sha512-3kffMSJBqV9M4HJ6a2+I8P/03PdeTD3mBLZ71czzmYtDpYPe7GGjpiSlJebW+dUYrlMeqWG4tKM20xWNfaj4QQ==} + '@module-federation/runtime@0.0.0-fix-loop-load-20260203135642': + resolution: {integrity: sha512-fh6kQmwSAiW/G4jMIjKZ/hIHJ/2RuK9yJmYRdPq3yGyH9tUU9p4TG+ZaY2BXreXTRHEqmeWUbpA149jDurXpIg==} + '@module-federation/runtime@0.22.0': resolution: {integrity: sha512-38g5iPju2tPC3KHMPxRKmy4k4onNp6ypFPS1eKGsNLUkXgHsPMBFqAjDw96iEcjri91BrahG4XcdyKi97xZzlA==} '@module-federation/runtime@0.24.0': resolution: {integrity: sha512-fZYLS3S0CwTP9SYiFmchPM1JZPqbR9GpiI4egSWsPrub53znMBMVtf4DAKfcpQFaaKTjsUZs1RxXmCyt30Uqzg==} + '@module-federation/sdk@0.0.0-fix-loop-load-20260203135642': + resolution: {integrity: sha512-wUzh3cMd4raAsIon3zWvtG1egpY4s+iQrc95ykQ6Let54SagqH7KWTCGpPOdOskBjqpE5Ska6BPwzpUImOgPRw==} + '@module-federation/sdk@0.22.0': resolution: {integrity: sha512-x4aFNBKn2KVQRuNVC5A7SnrSCSqyfIWmm1DvubjbO9iKFe7ith5niw8dqSFBekYBg2Fwy+eMg4sEFNVvCAdo6g==} '@module-federation/sdk@0.24.0': resolution: {integrity: sha512-3AxOPr3uKxLcT2Ek2ne3+5cUDrQ/0Ncoz3t2hgFqmHcZ+6sTPcEmS7Sr0T04yRCM/Dyv3TrJR8EebevRtILc2A==} + '@module-federation/webpack-bundler-runtime@0.0.0-fix-loop-load-20260203135642': + resolution: {integrity: sha512-SnrQcdJkl/L27MEcDuaq42l6dC1sobvtSHEE9qMjE6CMUhhQE5O8ZQqoQRR9nw1RiiO+5NqFBPlyRicVh/YJqQ==} + '@module-federation/webpack-bundler-runtime@0.22.0': resolution: {integrity: sha512-aM8gCqXu+/4wBmJtVeMeeMN5guw3chf+2i6HajKtQv7SJfxV/f4IyNQJUeUQu9HfiAZHjqtMV5Lvq/Lvh8LdyA==} @@ -9693,9 +9711,17 @@ snapshots: '@microsoft/tsdoc@0.16.0': {} + '@module-federation/error-codes@0.0.0-fix-loop-load-20260203135642': {} + '@module-federation/error-codes@0.22.0': {} - '@module-federation/error-codes@0.24.0': {} + '@module-federation/error-codes@0.24.0': + optional: true + + '@module-federation/runtime-core@0.0.0-fix-loop-load-20260203135642': + dependencies: + '@module-federation/error-codes': 0.0.0-fix-loop-load-20260203135642 + '@module-federation/sdk': 0.0.0-fix-loop-load-20260203135642 '@module-federation/runtime-core@0.22.0': dependencies: @@ -9706,6 +9732,12 @@ snapshots: dependencies: '@module-federation/error-codes': 0.24.0 '@module-federation/sdk': 0.24.0 + optional: true + + '@module-federation/runtime-tools@0.0.0-fix-loop-load-20260203135642': + dependencies: + '@module-federation/runtime': 0.0.0-fix-loop-load-20260203135642 + '@module-federation/webpack-bundler-runtime': 0.0.0-fix-loop-load-20260203135642 '@module-federation/runtime-tools@0.22.0': dependencies: @@ -9716,6 +9748,13 @@ snapshots: dependencies: '@module-federation/runtime': 0.24.0 '@module-federation/webpack-bundler-runtime': 0.24.0 + optional: true + + '@module-federation/runtime@0.0.0-fix-loop-load-20260203135642': + dependencies: + '@module-federation/error-codes': 0.0.0-fix-loop-load-20260203135642 + '@module-federation/runtime-core': 0.0.0-fix-loop-load-20260203135642 + '@module-federation/sdk': 0.0.0-fix-loop-load-20260203135642 '@module-federation/runtime@0.22.0': dependencies: @@ -9728,10 +9767,19 @@ snapshots: '@module-federation/error-codes': 0.24.0 '@module-federation/runtime-core': 0.24.0 '@module-federation/sdk': 0.24.0 + optional: true + + '@module-federation/sdk@0.0.0-fix-loop-load-20260203135642': {} '@module-federation/sdk@0.22.0': {} - '@module-federation/sdk@0.24.0': {} + '@module-federation/sdk@0.24.0': + optional: true + + '@module-federation/webpack-bundler-runtime@0.0.0-fix-loop-load-20260203135642': + dependencies: + '@module-federation/runtime': 0.0.0-fix-loop-load-20260203135642 + '@module-federation/sdk': 0.0.0-fix-loop-load-20260203135642 '@module-federation/webpack-bundler-runtime@0.22.0': dependencies: @@ -9742,6 +9790,7 @@ snapshots: dependencies: '@module-federation/runtime': 0.24.0 '@module-federation/sdk': 0.24.0 + optional: true '@napi-rs/cli@3.0.4(@emnapi/runtime@1.5.0)(@types/node@20.19.30)(emnapi@1.8.1(node-addon-api@7.1.1))': dependencies: @@ -10209,6 +10258,18 @@ snapshots: core-js: 3.47.0 jiti: 2.6.1 + '@rsbuild/core@2.0.0-beta.0(@module-federation/runtime-tools@0.0.0-fix-loop-load-20260203135642)(core-js@3.47.0)': + dependencies: + '@rspack/core': 2.0.0-alpha.1(@module-federation/runtime-tools@0.0.0-fix-loop-load-20260203135642)(@swc/helpers@0.5.18) + '@rspack/lite-tapable': 1.1.0 + '@swc/helpers': 0.5.18 + jiti: 2.6.1 + optionalDependencies: + core-js: 3.47.0 + transitivePeerDependencies: + - '@module-federation/runtime-tools' + optional: true + '@rsbuild/core@2.0.0-beta.0(@module-federation/runtime-tools@0.24.0)(core-js@3.47.0)': dependencies: '@rspack/core': 2.0.0-alpha.1(@module-federation/runtime-tools@0.24.0)(@swc/helpers@0.5.18) @@ -10220,7 +10281,7 @@ snapshots: transitivePeerDependencies: - '@module-federation/runtime-tools' - '@rsbuild/plugin-node-polyfill@1.4.3(@rsbuild/core@2.0.0-beta.0(@module-federation/runtime-tools@0.24.0)(core-js@3.47.0))': + '@rsbuild/plugin-node-polyfill@1.4.3(@rsbuild/core@2.0.0-beta.0(@module-federation/runtime-tools@0.0.0-fix-loop-load-20260203135642)(core-js@3.47.0))': dependencies: assert: 2.1.0 browserify-zlib: 0.2.0 @@ -10246,7 +10307,7 @@ snapshots: util: 0.12.5 vm-browserify: 1.1.2 optionalDependencies: - '@rsbuild/core': 2.0.0-beta.0(@module-federation/runtime-tools@0.24.0)(core-js@3.47.0) + '@rsbuild/core': 2.0.0-beta.0(@module-federation/runtime-tools@0.0.0-fix-loop-load-20260203135642)(core-js@3.47.0) '@rsbuild/plugin-react@1.4.5(@rsbuild/core@2.0.0-beta.0(@module-federation/runtime-tools@0.24.0)(core-js@3.47.0))': dependencies: @@ -10400,6 +10461,15 @@ snapshots: optionalDependencies: '@swc/helpers': 0.5.18 + '@rspack/core@2.0.0-alpha.1(@module-federation/runtime-tools@0.0.0-fix-loop-load-20260203135642)(@swc/helpers@0.5.18)': + dependencies: + '@rspack/binding': 2.0.0-alpha.1 + '@rspack/lite-tapable': 1.1.0 + optionalDependencies: + '@module-federation/runtime-tools': 0.0.0-fix-loop-load-20260203135642 + '@swc/helpers': 0.5.18 + optional: true + '@rspack/core@2.0.0-alpha.1(@module-federation/runtime-tools@0.24.0)(@swc/helpers@0.5.18)': dependencies: '@rspack/binding': 2.0.0-alpha.1 diff --git a/tests/e2e/package.json b/tests/e2e/package.json index ffa5b7eb6178..10a199d19e1d 100644 --- a/tests/e2e/package.json +++ b/tests/e2e/package.json @@ -16,7 +16,7 @@ "@rspack/browser": "workspace:*", "@rspack/dev-server": "~1.2.1", "@rspack/plugin-react-refresh": "^1.6.0", - "@module-federation/runtime-tools": "0.24.0", + "@module-federation/runtime-tools": "0.0.0-fix-loop-load-20260203135642", "@swc/helpers": "0.5.18", "@types/fs-extra": "11.0.4", "babel-loader": "^10.0.0", diff --git a/tests/rspack-test/package.json b/tests/rspack-test/package.json index 68a0d77a7e73..39eab11e2761 100644 --- a/tests/rspack-test/package.json +++ b/tests/rspack-test/package.json @@ -15,7 +15,7 @@ "devDependencies": { "@babel/core": "^7.28.6", "@babel/preset-react": "^7.28.5", - "@module-federation/runtime-tools": "0.24.0", + "@module-federation/runtime-tools": "0.0.0-fix-loop-load-20260203135642", "@rspack/binding-testing": "workspace:*", "@rspack/cli": "workspace:*", "@rspack/core": "workspace:*", From 44fe169a1cd4e3b9a9a573cb6f1fc5b497260431 Mon Sep 17 00:00:00 2001 From: "zhanghang.heal" Date: Wed, 4 Feb 2026 14:33:16 +0800 Subject: [PATCH 81/87] workflow: revert ci --- .github/actions/codspeed/action.sh | 120 +++++++++++++++++++++ .github/workflows/reusable-build-bench.yml | 2 +- 2 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 .github/actions/codspeed/action.sh diff --git a/.github/actions/codspeed/action.sh b/.github/actions/codspeed/action.sh new file mode 100644 index 000000000000..45cfc961bf8c --- /dev/null +++ b/.github/actions/codspeed/action.sh @@ -0,0 +1,120 @@ +name: 'CodSpeed Performance Analysis' +description: 'Continuous benchmarking and performance checks' +branding: + color: orange + icon: activity + +author: 'Arthur Pastel' +inputs: + run: + description: 'The command to run the benchmarks' + required: true + + mode: + description: | + The mode to run the benchmarks in. The following modes are available: + - `simulation`: Run the benchmarks with CPU simulation measurements. + - `walltime`: Run the benchmarks with walltime measurement. + - `memory`: Run the benchmarks with allocation measurements. + - `instrumentation`: (Deprecated) Legacy name for `simulation`. Please use `simulation` instead. + + We strongly recommend starting with the `simulation` mode. + + Using the `walltime` mode on traditional VMs/Hosted Runners might lead to inconsistent data. For the best results, we recommend using CodSpeed Hosted Macro Runners, which are fine-tuned for performance measurement consistency. + Check out the [Walltime Instrument Documentation](https://docs.codspeed.io/instruments/walltime/) for more details. + required: true + + token: + description: | + CodSpeed upload token. Only required for private repositories. + required: false + + working-directory: + description: | + The directory where the `run` command will be executed. + Warning: if you use defaults.working-directory, you must still set this parameter. + required: false + + upload-url: + description: 'The upload endpoint (for on-premise deployments)' + required: false + + runner-version: + description: "The version of the runner to use. Use 'latest' to automatically fetch the latest release version from GitHub, or specify a version like '3.5.0' or 'v3.5.0'." + required: false + + instruments: + description: | + Comma separated list of instruments to enable. The following instruments are available: + - `mongodb`: MongoDB instrumentation, requires the MongoDB instrument to be enabled for the organization in CodSpeed + required: false + + mongo-uri-env-name: + description: | + The name of the environment variable containing the MongoDB URI. Requires the `mongodb` instrument to be activated in `instruments`. + If the instrumentation is enabled and this value is not set, the user will need to dynamically provide the MongoDB URI to the CodSpeed runner. + required: false + + cache-instruments: + description: | + Enable caching of instrument installations (like valgrind or perf) to speed up subsequent workflow runs. Set to 'false' to disable caching. + required: false + default: 'true' + + instruments-cache-dir: + description: | + The directory to use for caching installations of instruments (like valgrind or perf). Defaults to `$HOME/.cache/codspeed-action`. + required: false + default: '~/.cache/codspeed-action' + + allow-empty: + description: | + Allow the action to complete successfully even if no benchmarks were found or run. Set to 'true' to enable this behavior. + required: false + default: 'false' + +runs: + using: 'composite' + steps: + - shell: bash + run: | + # Validate required inputs + # (custom message for smoother v4 migration) + if [ -z "${{ inputs.mode }}" ]; then + echo "::error title=Missing required input 'mode'::The 'mode' input is required as of CodSpeed Action v4. Please explicitly set 'mode' to 'simulation' or 'walltime'. Before, this variable was automatically set to instrumentation on every runner except for CodSpeed macro runners where it was set to walltime by default. See https://codspeed.io/docs/instruments for details." + exit 1 + fi + + # We can use official runner if it supports config valgrind flags in the future: https://github.com/CodSpeedHQ/runner/pull/92 + cargo install --git https://github.com/CPunisher/runner.git --rev 9c1ca5aa4742b8524843c0ac3e417c6ecb91b1bd codspeed-runner + + # Get the runner arguments + RUNNER_ARGS="" + if [ -n "${{ inputs.token }}" ]; then + RUNNER_ARGS="$RUNNER_ARGS --token ${{ inputs.token }}" + fi + if [ -n "${{ inputs.working-directory }}" ]; then + RUNNER_ARGS="$RUNNER_ARGS --working-directory=${{ inputs.working-directory }}" + fi + if [ -n "${{ inputs.upload-url }}" ]; then + RUNNER_ARGS="$RUNNER_ARGS --upload-url=${{ inputs.upload-url }}" + fi + if [ -n "${{ inputs.mode }}" ]; then + RUNNER_ARGS="$RUNNER_ARGS --mode=${{ inputs.mode }}" + fi + if [ -n "${{ inputs.instruments }}" ]; then + RUNNER_ARGS="$RUNNER_ARGS --instruments=${{ inputs.instruments }}" + fi + if [ -n "${{ inputs.mongo-uri-env-name }}" ]; then + RUNNER_ARGS="$RUNNER_ARGS --mongo-uri-env-name=${{ inputs.mongo-uri-env-name }}" + fi + if [ "${{ inputs.cache-instruments }}" = "true" ] && [ -n "${{ inputs.instruments-cache-dir }}" ]; then + RUNNER_ARGS="$RUNNER_ARGS --setup-cache-dir=${{ inputs.instruments-cache-dir }}" + fi + if [ "${{ inputs.allow-empty }}" = "true" ]; then + RUNNER_ARGS="$RUNNER_ARGS --allow-empty" + fi + + # Run the benchmarks + # Enable fair sched to make benchmark more stable, see: https://github.com/CodSpeedHQ/runner/pull/91 + env VALGRIND_FLAGS='--fair-sched=yes' codspeed run $RUNNER_ARGS -- '${{ inputs.run }}' \ No newline at end of file diff --git a/.github/workflows/reusable-build-bench.yml b/.github/workflows/reusable-build-bench.yml index ab82b54560db..10328166697d 100644 --- a/.github/workflows/reusable-build-bench.yml +++ b/.github/workflows/reusable-build-bench.yml @@ -77,7 +77,7 @@ jobs: run: pnpm run build:js - name: Run benchmark - uses: CodSpeedHQ/action@0700edb451d0e9f2426f99bd6977027e550fb2a6 # https://github.com/CodSpeedHQ/action/releases/tag/v4.7.0 + uses: ./.github/actions/codspeed timeout-minutes: 30 env: RAYON_NUM_THREADS: 1 From eee0673eeb09deb0a7463df61c29cc7255d5abc3 Mon Sep 17 00:00:00 2001 From: "zhanghang.heal" Date: Wed, 4 Feb 2026 14:40:14 +0800 Subject: [PATCH 82/87] ci: add CodSpeed performance analysis action Add GitHub action for continuous benchmarking with CodSpeed. The action supports multiple measurement modes and instruments, including MongoDB instrumentation and caching for faster runs. Includes validation for required inputs and custom runner installation. --- .github/actions/codspeed/{action.sh => action.yaml} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename .github/actions/codspeed/{action.sh => action.yaml} (99%) diff --git a/.github/actions/codspeed/action.sh b/.github/actions/codspeed/action.yaml similarity index 99% rename from .github/actions/codspeed/action.sh rename to .github/actions/codspeed/action.yaml index 45cfc961bf8c..943010e364be 100644 --- a/.github/actions/codspeed/action.sh +++ b/.github/actions/codspeed/action.yaml @@ -117,4 +117,4 @@ runs: # Run the benchmarks # Enable fair sched to make benchmark more stable, see: https://github.com/CodSpeedHQ/runner/pull/91 - env VALGRIND_FLAGS='--fair-sched=yes' codspeed run $RUNNER_ARGS -- '${{ inputs.run }}' \ No newline at end of file + env VALGRIND_FLAGS='--fair-sched=yes' codspeed run $RUNNER_ARGS -- '${{ inputs.run }}' From 247bd993fdf297a7a792a4f82efee27720fb2bf3 Mon Sep 17 00:00:00 2001 From: "zhanghang.heal" Date: Wed, 4 Feb 2026 14:49:33 +0800 Subject: [PATCH 83/87] chore: revert cacahe implementation --- .../persistent/build_dependencies/mod.rs | 20 +++---------------- .../rspack_core/src/cache/persistent/mod.rs | 1 - 2 files changed, 3 insertions(+), 18 deletions(-) diff --git a/crates/rspack_core/src/cache/persistent/build_dependencies/mod.rs b/crates/rspack_core/src/cache/persistent/build_dependencies/mod.rs index 249aea05b419..00bc16f3283e 100644 --- a/crates/rspack_core/src/cache/persistent/build_dependencies/mod.rs +++ b/crates/rspack_core/src/cache/persistent/build_dependencies/mod.rs @@ -12,7 +12,6 @@ use super::{ snapshot::{Snapshot, SnapshotScope}, storage::Storage, }; -use crate::cache::persistent::CacheCodec; pub const SCOPE: &str = "build_dependencies"; @@ -41,7 +40,6 @@ impl BuildDeps { fs: Arc, snapshot: Arc, storage: Arc, - _codec: Arc, ) -> Self { Self { added: Default::default(), @@ -165,27 +163,15 @@ mod test { SnapshotOptions::default(), fs.clone(), storage.clone(), - codec.clone(), + codec, )); - let mut build_deps = BuildDeps::new( - &options, - fs.clone(), - snapshot.clone(), - storage.clone(), - codec.clone(), - ); + let mut build_deps = BuildDeps::new(&options, fs.clone(), snapshot.clone(), storage.clone()); let warnings = build_deps.add(vec![].into_iter()).await; assert_eq!(warnings.len(), 1); let data = storage.load(scope).await.expect("should load success"); assert_eq!(data.len(), 9); - let mut build_deps = BuildDeps::new( - &options, - fs.clone(), - snapshot.clone(), - storage.clone(), - codec, - ); + let mut build_deps = BuildDeps::new(&options, fs.clone(), snapshot.clone(), storage.clone()); fs.write("/b.js".into(), r#"require("./c")"#.as_bytes()) .await .unwrap(); diff --git a/crates/rspack_core/src/cache/persistent/mod.rs b/crates/rspack_core/src/cache/persistent/mod.rs index 2640f76daceb..da1e4951b4c4 100644 --- a/crates/rspack_core/src/cache/persistent/mod.rs +++ b/crates/rspack_core/src/cache/persistent/mod.rs @@ -101,7 +101,6 @@ impl PersistentCache { input_filesystem, snapshot.clone(), storage.clone(), - codec.clone(), ), snapshot, make_occasion: MakeOccasion::new(storage.clone(), codec.clone()), From d62d2a5c9de0748a41d04a43ecaa06c30fd8d932 Mon Sep 17 00:00:00 2001 From: "zhanghang.heal" Date: Wed, 4 Feb 2026 17:02:31 +0800 Subject: [PATCH 84/87] chore: use get_referenced_exports --- .../esm/esm_import_specifier_dependency.rs | 68 ++++++++----------- .../plugin/flag_dependency_usage_plugin.rs | 1 - .../shared_used_exports_optimizer_plugin.rs | 9 +-- 3 files changed, 34 insertions(+), 44 deletions(-) diff --git a/crates/rspack_plugin_javascript/src/dependency/esm/esm_import_specifier_dependency.rs b/crates/rspack_plugin_javascript/src/dependency/esm/esm_import_specifier_dependency.rs index 90a8246bb619..0db0ee2b9653 100644 --- a/crates/rspack_plugin_javascript/src/dependency/esm/esm_import_specifier_dependency.rs +++ b/crates/rspack_plugin_javascript/src/dependency/esm/esm_import_specifier_dependency.rs @@ -106,44 +106,7 @@ impl ESMImportSpecifierDependency { .map_or_else(|| self.ids.as_slice(), |meta| meta.ids.as_slice()) } - pub fn get_esm_import_specifier_referenced_exports( - &self, - module_graph: &ModuleGraph, - exports_type: Option, - ) -> Vec { - let mut ids = self.get_ids(module_graph); - if ids.is_empty() { - return self.get_referenced_exports_in_destructuring(None); - } - - let mut namespace_object_as_context = self.namespace_object_as_context; - if let Some(id) = ids.first() - && id == "default" - { - match exports_type { - Some(ExportsType::DefaultOnly | ExportsType::DefaultWithNamed) => { - if ids.len() == 1 { - return self.get_referenced_exports_in_destructuring(None); - } - ids = &ids[1..]; - namespace_object_as_context = true; - } - Some(ExportsType::Dynamic) => { - return create_exports_object_referenced(); - } - _ => {} - } - } - - if self.call && !self.direct_import && (namespace_object_as_context || ids.len() > 1) { - if ids.len() == 1 { - return create_exports_object_referenced(); - } - // remove last one - ids = &ids[..ids.len() - 1]; - } - self.get_referenced_exports_in_destructuring(Some(ids)) - } + // Removed get_esm_import_specifier_referenced_exports pub fn get_referenced_exports_in_destructuring( &self, @@ -295,7 +258,34 @@ impl Dependency for ESMImportSpecifierDependency { None }; - self.get_esm_import_specifier_referenced_exports(module_graph, exports_type) + let mut ids = ids; + let mut namespace_object_as_context = self.namespace_object_as_context; + if let Some(id) = ids.first() + && id == "default" + { + match exports_type { + Some(ExportsType::DefaultOnly | ExportsType::DefaultWithNamed) => { + if ids.len() == 1 { + return self.get_referenced_exports_in_destructuring(None); + } + ids = &ids[1..]; + namespace_object_as_context = true; + } + Some(ExportsType::Dynamic) => { + return create_exports_object_referenced(); + } + _ => {} + } + } + + if self.call && !self.direct_import && (namespace_object_as_context || ids.len() > 1) { + if ids.len() == 1 { + return create_exports_object_referenced(); + } + // remove last one + ids = &ids[..ids.len() - 1]; + } + self.get_referenced_exports_in_destructuring(Some(ids)) } fn could_affect_referencing_module(&self) -> rspack_core::AffectType { diff --git a/crates/rspack_plugin_javascript/src/plugin/flag_dependency_usage_plugin.rs b/crates/rspack_plugin_javascript/src/plugin/flag_dependency_usage_plugin.rs index 1ee3eb59c61f..f44f73457998 100644 --- a/crates/rspack_plugin_javascript/src/plugin/flag_dependency_usage_plugin.rs +++ b/crates/rspack_plugin_javascript/src/plugin/flag_dependency_usage_plugin.rs @@ -283,7 +283,6 @@ impl<'a> FlagDependencyUsagePluginProxy<'a> { runtime, ); - // 直接使用 await 调用异步钩子 self .compilation .plugin_driver diff --git a/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_plugin.rs b/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_plugin.rs index 2b34bbb8e748..76b55f75f16e 100644 --- a/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_plugin.rs +++ b/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_plugin.rs @@ -3,8 +3,8 @@ use std::sync::{Arc, RwLock}; use rspack_core::{ AsyncDependenciesBlockIdentifier, ChunkUkey, Compilation, CompilationAdditionalTreeRuntimeRequirements, CompilationDependencyReferencedExports, - CompilationOptimizeDependencies, CompilationProcessAssets, DependenciesBlock, DependencyId, - DependencyType, ExportsType, ExtendedReferencedExport, Module, ModuleGraph, ModuleIdentifier, + CompilationOptimizeDependencies, CompilationProcessAssets, DependenciesBlock, Dependency, + DependencyId, DependencyType, ExtendedReferencedExport, Module, ModuleGraph, ModuleIdentifier, Plugin, RuntimeGlobals, RuntimeModule, RuntimeModuleExt, RuntimeSpec, SideEffectsOptimizeArtifact, build_module_graph::BuildModuleGraphArtifact, @@ -442,9 +442,10 @@ async fn dependency_referenced_exports( { final_exports = esm_dep.get_referenced_exports_in_destructuring(Some(ids)); } else { - final_exports = esm_dep.get_esm_import_specifier_referenced_exports( + final_exports = esm_dep.get_referenced_exports( module_graph, - Some(ExportsType::DefaultWithNamed), + &compilation.module_graph_cache_artifact, + _runtime, ); } } From 0aa547b29bc24744a774a6979da1e7249cbc9019 Mon Sep 17 00:00:00 2001 From: "zhanghang.heal" Date: Wed, 4 Feb 2026 17:54:50 +0800 Subject: [PATCH 85/87] chore: revert esm depnedency change --- .../src/dependency/esm/esm_import_specifier_dependency.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/rspack_plugin_javascript/src/dependency/esm/esm_import_specifier_dependency.rs b/crates/rspack_plugin_javascript/src/dependency/esm/esm_import_specifier_dependency.rs index 0db0ee2b9653..515dc8ef2460 100644 --- a/crates/rspack_plugin_javascript/src/dependency/esm/esm_import_specifier_dependency.rs +++ b/crates/rspack_plugin_javascript/src/dependency/esm/esm_import_specifier_dependency.rs @@ -106,8 +106,6 @@ impl ESMImportSpecifierDependency { .map_or_else(|| self.ids.as_slice(), |meta| meta.ids.as_slice()) } - // Removed get_esm_import_specifier_referenced_exports - pub fn get_referenced_exports_in_destructuring( &self, ids: Option<&[Atom]>, From 26185ceb5e79716beaef2d3e00a44ac970da3561 Mon Sep 17 00:00:00 2001 From: "zhanghang.heal" Date: Wed, 4 Feb 2026 19:53:27 +0800 Subject: [PATCH 86/87] chore: revert esm_import_specifier_dependency change --- .../esm/esm_import_specifier_dependency.rs | 27 ++++++------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/crates/rspack_plugin_javascript/src/dependency/esm/esm_import_specifier_dependency.rs b/crates/rspack_plugin_javascript/src/dependency/esm/esm_import_specifier_dependency.rs index 515dc8ef2460..cf5ee05a2890 100644 --- a/crates/rspack_plugin_javascript/src/dependency/esm/esm_import_specifier_dependency.rs +++ b/crates/rspack_plugin_javascript/src/dependency/esm/esm_import_specifier_dependency.rs @@ -235,41 +235,30 @@ impl Dependency for ESMImportSpecifierDependency { module_graph_cache: &ModuleGraphCacheArtifact, _runtime: Option<&RuntimeSpec>, ) -> Vec { - let ids = self.get_ids(module_graph); + let mut ids = self.get_ids(module_graph); + // namespace import if ids.is_empty() { return self.get_referenced_exports_in_destructuring(None); } - let exports_type = if let Some(id) = ids.first() + let mut namespace_object_as_context = self.namespace_object_as_context; + if let Some(id) = ids.first() && id == "default" { let parent_module = module_graph .get_parent_module(&self.id) .expect("should have parent module"); - Some(get_exports_type( - module_graph, - module_graph_cache, - &self.id, - parent_module, - )) - } else { - None - }; - - let mut ids = ids; - let mut namespace_object_as_context = self.namespace_object_as_context; - if let Some(id) = ids.first() - && id == "default" - { + let exports_type = + get_exports_type(module_graph, module_graph_cache, &self.id, parent_module); match exports_type { - Some(ExportsType::DefaultOnly | ExportsType::DefaultWithNamed) => { + ExportsType::DefaultOnly | ExportsType::DefaultWithNamed => { if ids.len() == 1 { return self.get_referenced_exports_in_destructuring(None); } ids = &ids[1..]; namespace_object_as_context = true; } - Some(ExportsType::Dynamic) => { + ExportsType::Dynamic => { return create_exports_object_referenced(); } _ => {} From b33c235b5ca193979210261cd78cdfad9ee4ddc0 Mon Sep 17 00:00:00 2001 From: "zhanghang.heal" Date: Thu, 5 Feb 2026 11:40:29 +0800 Subject: [PATCH 87/87] refactor(mf): simplify runtime module implementations --- .../src/sharing/shared_container_plugin.rs | 2 +- .../shared_container_runtime_module.rs | 25 +++++-------------- .../shared_used_exports_optimizer_plugin.rs | 19 ++++++++------ ...d_used_exports_optimizer_runtime_module.rs | 25 +++++++------------ 4 files changed, 27 insertions(+), 44 deletions(-) diff --git a/crates/rspack_plugin_mf/src/sharing/shared_container_plugin.rs b/crates/rspack_plugin_mf/src/sharing/shared_container_plugin.rs index d7e86d3a88cd..87cf4cead02f 100644 --- a/crates/rspack_plugin_mf/src/sharing/shared_container_plugin.rs +++ b/crates/rspack_plugin_mf/src/sharing/shared_container_plugin.rs @@ -88,7 +88,7 @@ async fn additional_tree_runtime_requirements( if let Some(name) = chunk.name() && name == self.options.name { - runtime_modules.push(ShareContainerRuntimeModule::new().boxed()); + runtime_modules.push(ShareContainerRuntimeModule::new(&compilation.runtime_template).boxed()); } Ok(()) } diff --git a/crates/rspack_plugin_mf/src/sharing/shared_container_runtime_module.rs b/crates/rspack_plugin_mf/src/sharing/shared_container_runtime_module.rs index 09c88b12441d..cce7571b2209 100644 --- a/crates/rspack_plugin_mf/src/sharing/shared_container_runtime_module.rs +++ b/crates/rspack_plugin_mf/src/sharing/shared_container_runtime_module.rs @@ -1,28 +1,19 @@ -use rspack_collections::Identifier; -use rspack_core::{ChunkUkey, Compilation, RuntimeModule, RuntimeModuleStage, impl_runtime_module}; +use rspack_core::{ + Compilation, RuntimeModule, RuntimeModuleStage, RuntimeTemplate, impl_runtime_module, +}; #[impl_runtime_module] #[derive(Debug)] -pub struct ShareContainerRuntimeModule { - id: Identifier, - chunk: Option, -} +pub struct ShareContainerRuntimeModule {} impl ShareContainerRuntimeModule { - pub fn new() -> Self { - Self::with_default( - Identifier::from("webpack/runtime/share_container_federation"), - None, - ) + pub fn new(runtime_template: &RuntimeTemplate) -> Self { + Self::with_name(runtime_template, "share_container_federation") } } #[async_trait::async_trait] impl RuntimeModule for ShareContainerRuntimeModule { - fn name(&self) -> Identifier { - self.id - } - async fn generate(&self, _compilation: &Compilation) -> rspack_error::Result { Ok( "__webpack_require__.federation = { instance: undefined,bundlerRuntime: undefined };" @@ -30,10 +21,6 @@ impl RuntimeModule for ShareContainerRuntimeModule { ) } - fn attach(&mut self, chunk: ChunkUkey) { - self.chunk = Some(chunk); - } - fn stage(&self) -> RuntimeModuleStage { RuntimeModuleStage::Attach } diff --git a/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_plugin.rs b/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_plugin.rs index 76b55f75f16e..189c94549937 100644 --- a/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_plugin.rs +++ b/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_plugin.rs @@ -353,7 +353,7 @@ async fn process_assets(&self, compilation: &mut Compilation) -> Result<()> { )] async fn additional_tree_runtime_requirements( &self, - _compilation: &Compilation, + compilation: &Compilation, _chunk_ukey: &ChunkUkey, runtime_requirements: &mut RuntimeGlobals, runtime_modules: &mut Vec>, @@ -364,13 +364,16 @@ async fn additional_tree_runtime_requirements( runtime_requirements.insert(RuntimeGlobals::RUNTIME_ID); runtime_modules.push( - SharedUsedExportsOptimizerRuntimeModule::new(Arc::new( - self - .shared_referenced_exports - .read() - .expect("lock poisoned") - .clone(), - )) + SharedUsedExportsOptimizerRuntimeModule::new( + &compilation.runtime_template, + Arc::new( + self + .shared_referenced_exports + .read() + .expect("lock poisoned") + .clone(), + ), + ) .boxed(), ); diff --git a/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_runtime_module.rs b/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_runtime_module.rs index 3ccbb5064b9d..a0bc98447c09 100644 --- a/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_runtime_module.rs +++ b/crates/rspack_plugin_mf/src/sharing/shared_used_exports_optimizer_runtime_module.rs @@ -1,9 +1,9 @@ use std::{collections::BTreeMap, sync::Arc}; use async_trait::async_trait; -use rspack_collections::Identifier; use rspack_core::{ - ChunkUkey, Compilation, RuntimeGlobals, RuntimeModule, RuntimeModuleStage, impl_runtime_module, + Compilation, RuntimeGlobals, RuntimeModule, RuntimeModuleStage, RuntimeTemplate, + impl_runtime_module, }; use rspack_error::{Result, error}; use rustc_hash::{FxHashMap, FxHashSet}; @@ -11,17 +11,18 @@ use rustc_hash::{FxHashMap, FxHashSet}; #[impl_runtime_module] #[derive(Debug)] pub struct SharedUsedExportsOptimizerRuntimeModule { - id: Identifier, - chunk: Option, // Keep type consistent with plugin: FxHashMap> shared_used_exports: Arc>>, } impl SharedUsedExportsOptimizerRuntimeModule { - pub fn new(shared_used_exports: Arc>>) -> Self { - Self::with_default( - Identifier::from("module_federation/shared_used_exports"), - None, + pub fn new( + runtime_template: &RuntimeTemplate, + shared_used_exports: Arc>>, + ) -> Self { + Self::with_name( + runtime_template, + "module_federation/shared_used_exports", shared_used_exports, ) } @@ -29,14 +30,6 @@ impl SharedUsedExportsOptimizerRuntimeModule { #[async_trait] impl RuntimeModule for SharedUsedExportsOptimizerRuntimeModule { - fn name(&self) -> Identifier { - self.id - } - - fn attach(&mut self, chunk: ChunkUkey) { - self.chunk = Some(chunk); - } - fn stage(&self) -> RuntimeModuleStage { RuntimeModuleStage::Attach }