Skip to content

refactor: Switch ModuleGraph dependencies to Arc-based storage#13153

Draft
hardfist wants to merge 12 commits intomainfrom
codex/yj/arc-dependency
Draft

refactor: Switch ModuleGraph dependencies to Arc-based storage#13153
hardfist wants to merge 12 commits intomainfrom
codex/yj/arc-dependency

Conversation

@hardfist
Copy link
Contributor

@hardfist hardfist commented Feb 28, 2026

Summary

  • migrate ModuleGraph to store Arc<Dependency> so callers can share references without cloning the whole trait object
  • update binding adapters, repair flows, cache recovery, and concatenated module helpers to work with dyn Dependency and clone where necessary before mutation
  • adapt FactorizeInfo, dependency lookups, and executor paths to operate on Dependency trait refs and to clone via clone_box when mutability requires unique ownership

Testing

  • Not run (not requested)

@github-actions github-actions bot added the team The issue/pr is created by the member of Rspack. label Feb 28, 2026
@hardfist hardfist changed the title Switch ModuleGraph dependencies to Arc-based storage refactor: Switch ModuleGraph dependencies to Arc-based storage Feb 28, 2026
@github-actions
Copy link
Contributor

github-actions bot commented Feb 28, 2026

📝 Benchmark detail: Open

task skipped

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Free Tier Details

You are on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle.

To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: COW check misses weak references causing potential panic
    • Replaced strong_count-based COW guard with Arc::get_mut uniqueness check and updated the panic to reflect exclusivity failure, preventing a panic when only weak refs exist.
Preview (59ca3b1b01)
diff --git a/crates/rspack_binding_api/src/compilation/mod.rs b/crates/rspack_binding_api/src/compilation/mod.rs
--- a/crates/rspack_binding_api/src/compilation/mod.rs
+++ b/crates/rspack_binding_api/src/compilation/mod.rs
@@ -838,7 +838,7 @@
             .into_iter()
             .map(|dependency_id| {
               let dependency = module_graph.dependency_by_id(&dependency_id);
-              if let Some(factorize_info) = FactorizeInfo::get_from(dependency)
+              if let Some(factorize_info) = FactorizeInfo::get_from(dependency.as_ref())
                 && let Some(diagnostic) = factorize_info.diagnostics().first()
               {
                 return Either::A(diagnostic.to_string());
@@ -942,7 +942,7 @@
             .into_iter()
             .map(|dependency_id| {
               let dependency = module_graph.dependency_by_id(&dependency_id);
-              if let Some(factorize_info) = FactorizeInfo::get_from(dependency)
+              if let Some(factorize_info) = FactorizeInfo::get_from(dependency.as_ref())
                 && let Some(diagnostic) = factorize_info.diagnostics().first()
               {
                 return Either::A(diagnostic.to_string());

diff --git a/crates/rspack_core/src/artifacts/build_module_graph_artifact.rs b/crates/rspack_core/src/artifacts/build_module_graph_artifact.rs
--- a/crates/rspack_core/src/artifacts/build_module_graph_artifact.rs
+++ b/crates/rspack_core/src/artifacts/build_module_graph_artifact.rs
@@ -208,7 +208,7 @@
     let dep_diagnostics = self.make_failed_dependencies.iter().flat_map(|dep_id| {
       let dep = mg.dependency_by_id(dep_id);
       let origin_module_identifier = mg.get_parent_module(dep_id);
-      FactorizeInfo::get_from(dep)
+      FactorizeInfo::get_from(dep.as_ref())
         .expect("should have factorize info")
         .diagnostics()
         .iter()

diff --git a/crates/rspack_core/src/cache/persistent/occasion/make/mod.rs b/crates/rspack_core/src/cache/persistent/occasion/make/mod.rs
--- a/crates/rspack_core/src/cache/persistent/occasion/make/mod.rs
+++ b/crates/rspack_core/src/cache/persistent/occasion/make/mod.rs
@@ -97,7 +97,7 @@
     // recovery make_failed_dependencies
     let mut make_failed_dependencies = FxHashSet::default();
     for (dep_id, dep) in mg.dependencies() {
-      if let Some(info) = FactorizeInfo::get_from(dep) {
+      if let Some(info) = FactorizeInfo::get_from(dep.as_ref()) {
         if !info.is_success() {
           make_failed_dependencies.insert(*dep_id);
         }

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
--- a/crates/rspack_core/src/cache/persistent/occasion/make/module_graph.rs
+++ b/crates/rspack_core/src/cache/persistent/occasion/make/module_graph.rs
@@ -3,6 +3,7 @@
   atomic::{AtomicUsize, Ordering},
 };
 
+use dyn_clone::clone_box;
 use rayon::prelude::*;
 use rspack_cacheable::{cacheable, utils::OwnedOrRef};
 use rspack_collections::IdentifierSet;
@@ -71,7 +72,7 @@
         .par_iter()
         .map(|dep_id| {
           (
-            mg.dependency_by_id(dep_id).into(),
+            clone_box(mg.dependency_by_id(dep_id).as_ref()).into(),
             mg.get_parent_block(dep_id).map(Into::into),
           )
         })
@@ -158,7 +159,7 @@
             index_in_block,
           },
         );
-        mg.add_dependency(dep);
+        mg.add_dependency(dep.into());
       }
       for con in node.connections {
         let con = con.into_owned();
@@ -194,7 +195,8 @@
     let dep = TempDependency::default();
     let connection = ModuleGraphConnection::new(*dep.id(), None, mid, false);
     entry_dependencies.insert(*dep.id());
-    mg.add_dependency(Box::new(dep));
+    let dep: BoxDependency = Box::new(dep);
+    mg.add_dependency(dep.into());
     mg.cache_recovery_connection(connection);
   }
 

diff --git a/crates/rspack_core/src/compilation/build_module_graph/graph_updater/repair/add.rs b/crates/rspack_core/src/compilation/build_module_graph/graph_updater/repair/add.rs
--- a/crates/rspack_core/src/compilation/build_module_graph/graph_updater/repair/add.rs
+++ b/crates/rspack_core/src/compilation/build_module_graph/graph_updater/repair/add.rs
@@ -140,7 +140,7 @@
       *dependency.id(),
       module_identifier,
     )?;
-    module_graph.add_dependency(dependency);
+    module_graph.add_dependency(dependency.into());
   }
   Ok(())
 }

diff --git a/crates/rspack_core/src/compilation/build_module_graph/graph_updater/repair/build.rs b/crates/rspack_core/src/compilation/build_module_graph/graph_updater/repair/build.rs
--- a/crates/rspack_core/src/compilation/build_module_graph/graph_updater/repair/build.rs
+++ b/crates/rspack_core/src/compilation/build_module_graph/graph_updater/repair/build.rs
@@ -163,7 +163,7 @@
             index_in_block,
           },
         );
-        module_graph.add_dependency(dependency);
+        module_graph.add_dependency(dependency.into());
       }
       if let Some(current_block) = current_block {
         module.add_block_id(current_block.identifier());

diff --git a/crates/rspack_core/src/compilation/build_module_graph/graph_updater/repair/factorize.rs b/crates/rspack_core/src/compilation/build_module_graph/graph_updater/repair/factorize.rs
--- a/crates/rspack_core/src/compilation/build_module_graph/graph_updater/repair/factorize.rs
+++ b/crates/rspack_core/src/compilation/build_module_graph/graph_updater/repair/factorize.rs
@@ -194,7 +194,7 @@
       tracing::trace!("Module created with failure, but without bailout: {dep:?}");
       // sync dependencies to mg
       for dep in dependencies {
-        module_graph.add_dependency(dep)
+        module_graph.add_dependency(dep.into())
       }
       return Ok(vec![]);
     };
@@ -204,7 +204,7 @@
       tracing::trace!("Module ignored: {dep:?}");
       // sync dependencies to mg
       for dep in dependencies {
-        module_graph.add_dependency(dep)
+        module_graph.add_dependency(dep.into())
       }
       return Ok(vec![]);
     };

diff --git a/crates/rspack_core/src/compilation/build_module_graph/graph_updater/repair/mod.rs b/crates/rspack_core/src/compilation/build_module_graph/graph_updater/repair/mod.rs
--- a/crates/rspack_core/src/compilation/build_module_graph/graph_updater/repair/mod.rs
+++ b/crates/rspack_core/src/compilation/build_module_graph/graph_updater/repair/mod.rs
@@ -5,6 +5,7 @@
 pub mod lazy;
 pub mod process_dependencies;
 
+use dyn_clone::clone_box;
 use rspack_error::Result;
 use rustc_hash::{FxHashMap as HashMap, FxHashSet as HashSet};
 
@@ -47,13 +48,13 @@
           Box::new(factorize::FactorizeTask {
             compiler_id: compilation.compiler_id(),
             compilation_id: compilation.id(),
-            module_factory: compilation.get_dependency_factory(dependency),
+            module_factory: compilation.get_dependency_factory(dependency.as_ref()),
             original_module_identifier: None,
             original_module_source: None,
             issuer: None,
             issuer_layer: None,
             original_module_context: None,
-            dependencies: vec![dependency.clone()],
+            dependencies: vec![clone_box(dependency.as_ref())],
             resolve_options: None,
             options: compilation.options.clone(),
             resolver_factory: compilation.resolver_factory.clone(),

diff --git a/crates/rspack_core/src/compilation/build_module_graph/graph_updater/repair/process_dependencies.rs b/crates/rspack_core/src/compilation/build_module_graph/graph_updater/repair/process_dependencies.rs
--- a/crates/rspack_core/src/compilation/build_module_graph/graph_updater/repair/process_dependencies.rs
+++ b/crates/rspack_core/src/compilation/build_module_graph/graph_updater/repair/process_dependencies.rs
@@ -1,5 +1,6 @@
 use std::borrow::Cow;
 
+use dyn_clone::clone_box;
 use rustc_hash::FxHashMap as HashMap;
 
 use super::{TaskContext, factorize::FactorizeTask};
@@ -66,7 +67,7 @@
         sorted_dependencies
           .entry(resource_identifier)
           .or_insert(vec![])
-          .push(dependency.clone());
+          .push(clone_box(dependency.as_ref()));
       }
     }
 

diff --git a/crates/rspack_core/src/compilation/build_module_graph/module_executor/entry.rs b/crates/rspack_core/src/compilation/build_module_graph/module_executor/entry.rs
--- a/crates/rspack_core/src/compilation/build_module_graph/module_executor/entry.rs
+++ b/crates/rspack_core/src/compilation/build_module_graph/module_executor/entry.rs
@@ -7,7 +7,7 @@
   overwrite::overwrite_tasks,
 };
 use crate::{
-  Context, Dependency, LoaderImportDependency,
+  BoxDependency, Context, LoaderImportDependency,
   utils::task_loop::{Task, TaskResult, TaskType},
 };
 
@@ -44,14 +44,14 @@
     let (dep_id, is_new) = match entries.entry(meta.clone()) {
       Entry::Vacant(v) => {
         // not exist, generate a new dependency
-        let dep = Box::new(LoaderImportDependency::new(
+        let dep: BoxDependency = Box::new(LoaderImportDependency::new(
           meta.request.clone(),
           origin_module_context.unwrap_or_else(|| Context::from("")),
         ));
         let dep_id = *dep.id();
 
         let mg = TaskContext::get_module_graph_mut(&mut origin_context.artifact);
-        mg.add_dependency(dep.clone());
+        mg.add_dependency(dep.clone().into());
 
         res.extend(overwrite_tasks(vec![Box::new(FactorizeTask {
           compiler_id: origin_context.compiler_id,

diff --git a/crates/rspack_core/src/compilation/build_module_graph/module_executor/execute.rs b/crates/rspack_core/src/compilation/build_module_graph/module_executor/execute.rs
--- a/crates/rspack_core/src/compilation/build_module_graph/module_executor/execute.rs
+++ b/crates/rspack_core/src/compilation/build_module_graph/module_executor/execute.rs
@@ -177,7 +177,7 @@
       for dep_id in module.get_dependencies() {
         if !has_error && make_failed_dependencies.contains(dep_id) {
           let dep = mg.dependency_by_id(dep_id);
-          let diagnostics = FactorizeInfo::get_from(dep)
+          let diagnostics = FactorizeInfo::get_from(dep.as_ref())
             .expect("should have factorize info")
             .diagnostics();
           let errors: Vec<_> = diagnostics

diff --git a/crates/rspack_core/src/compilation/mod.rs b/crates/rspack_core/src/compilation/mod.rs
--- a/crates/rspack_core/src/compilation/mod.rs
+++ b/crates/rspack_core/src/compilation/mod.rs
@@ -70,10 +70,10 @@
   ChunkRenderCacheArtifact, ChunkRenderResult, ChunkUkey, CodeGenerateCacheArtifact,
   CodeGenerationJob, CodeGenerationResult, CodeGenerationResults, CompilationLogger,
   CompilationLogging, CompilerOptions, CompilerPlatform, ConcatenationScope,
-  DependenciesDiagnosticsArtifact, DependencyId, DependencyTemplate, DependencyTemplateType,
-  DependencyType, Entry, EntryData, EntryOptions, EntryRuntime, Entrypoint, ExecuteModuleId,
-  ExportsInfoArtifact, ExtendedReferencedExport, Filename, ImportPhase, ImportVarMap,
-  ImportedByDeferModulesArtifact, MemoryGCStorage, ModuleFactory, ModuleGraph,
+  DependenciesDiagnosticsArtifact, Dependency, DependencyId, DependencyTemplate,
+  DependencyTemplateType, DependencyType, Entry, EntryData, EntryOptions, EntryRuntime, Entrypoint,
+  ExecuteModuleId, ExportsInfoArtifact, ExtendedReferencedExport, Filename, ImportPhase,
+  ImportVarMap, ImportedByDeferModulesArtifact, MemoryGCStorage, ModuleFactory, ModuleGraph,
   ModuleGraphCacheArtifact, ModuleIdentifier, ModuleIdsArtifact, ModuleStaticCache, PathData,
   ProcessRuntimeRequirementsCacheArtifact, ResolverFactory, RuntimeGlobals, RuntimeKeyMap,
   RuntimeMode, RuntimeModule, RuntimeSpec, RuntimeSpecMap, RuntimeTemplate, SharedPluginDriver,
@@ -616,7 +616,7 @@
     self
       .build_module_graph_artifact
       .get_module_graph_mut()
-      .add_dependency(entry);
+      .add_dependency(entry.into());
     if let Some(name) = &entry_name {
       if let Some(data) = self.entries.get_mut(name) {
         data.dependencies.push(entry_id);
@@ -684,7 +684,7 @@
       self
         .build_module_graph_artifact
         .get_module_graph_mut()
-        .add_dependency(entry);
+        .add_dependency(entry.into());
       if let Some(name) = options.name.clone() {
         if let Some(data) = self.entries.get_mut(&name) {
           data.include_dependencies.push(entry_id);
@@ -1216,7 +1216,7 @@
       .insert(dependency_type, module_factory);
   }
 
-  pub fn get_dependency_factory(&self, dependency: &BoxDependency) -> Arc<dyn ModuleFactory> {
+  pub fn get_dependency_factory(&self, dependency: &dyn Dependency) -> Arc<dyn ModuleFactory> {
     let dependency_type = dependency.dependency_type();
     self
       .dependency_factories

diff --git a/crates/rspack_core/src/concatenated_module.rs b/crates/rspack_core/src/concatenated_module.rs
--- a/crates/rspack_core/src/concatenated_module.rs
+++ b/crates/rspack_core/src/concatenated_module.rs
@@ -38,24 +38,24 @@
 use swc_node_comments::SwcComments;
 
 use crate::{
-  AsyncDependenciesBlockIdentifier, BoxDependency, BoxDependencyTemplate, BoxModule,
-  BoxModuleDependency, BuildContext, BuildInfo, BuildMeta, BuildMetaDefaultObject,
-  BuildMetaExportsType, BuildResult, ChunkGraph, ChunkInitFragments, ChunkRenderContext,
-  CodeGenerationDataTopLevelDeclarations, CodeGenerationExportsFinalNames,
-  CodeGenerationPublicPathAutoReplace, CodeGenerationResult, Compilation, ConcatenatedModuleIdent,
-  ConcatenationScope, ConditionalInitFragment, ConnectionState, Context, DEFAULT_EXPORT,
-  DEFAULT_EXPORT_ATOM, DependenciesBlock, DependencyId, DependencyType, ExportInfoHashKey,
-  ExportProvided, ExportsArgument, ExportsInfoArtifact, ExportsInfoGetter, ExportsType,
-  FactoryMeta, GetUsedNameParam, ImportedByDeferModulesArtifact, InitFragment, InitFragmentStage,
-  LibIdentOptions, Module, ModuleArgument, ModuleCodeGenerationContext, ModuleGraph,
-  ModuleGraphCacheArtifact, ModuleGraphConnection, ModuleIdentifier, ModuleLayer,
-  ModuleStaticCache, ModuleType, NAMESPACE_OBJECT_EXPORT, ParserOptions, PrefetchExportsInfoMode,
-  Resolve, RuntimeCondition, RuntimeGlobals, RuntimeSpec, SourceType, URLStaticMode, UsageState,
-  UsedName, UsedNameItem, escape_identifier, filter_runtime, find_target, get_runtime_key,
-  impl_source_map_config, merge_runtime_condition, merge_runtime_condition_non_false,
-  module_update_hash, property_access, property_name,
-  render_make_deferred_namespace_mode_from_exports_type, reserved_names::RESERVED_NAMES,
-  subtract_runtime_condition, to_identifier_with_escaped, to_normal_comment,
+  AsyncDependenciesBlockIdentifier, BoxDependencyTemplate, BoxModule, BoxModuleDependency,
+  BuildContext, BuildInfo, BuildMeta, BuildMetaDefaultObject, BuildMetaExportsType, BuildResult,
+  ChunkGraph, ChunkInitFragments, ChunkRenderContext, CodeGenerationDataTopLevelDeclarations,
+  CodeGenerationExportsFinalNames, CodeGenerationPublicPathAutoReplace, CodeGenerationResult,
+  Compilation, ConcatenatedModuleIdent, ConcatenationScope, ConditionalInitFragment,
+  ConnectionState, Context, DEFAULT_EXPORT, DEFAULT_EXPORT_ATOM, DependenciesBlock, Dependency,
+  DependencyId, DependencyType, ExportInfoHashKey, ExportProvided, ExportsArgument,
+  ExportsInfoArtifact, ExportsInfoGetter, ExportsType, FactoryMeta, GetUsedNameParam,
+  ImportedByDeferModulesArtifact, InitFragment, InitFragmentStage, LibIdentOptions, Module,
+  ModuleArgument, ModuleCodeGenerationContext, ModuleGraph, ModuleGraphCacheArtifact,
+  ModuleGraphConnection, ModuleIdentifier, ModuleLayer, ModuleStaticCache, ModuleType,
+  NAMESPACE_OBJECT_EXPORT, ParserOptions, PrefetchExportsInfoMode, Resolve, RuntimeCondition,
+  RuntimeGlobals, RuntimeSpec, SourceType, URLStaticMode, UsageState, UsedName, UsedNameItem,
+  escape_identifier, filter_runtime, find_target, get_runtime_key, impl_source_map_config,
+  merge_runtime_condition, merge_runtime_condition_non_false, module_update_hash, property_access,
+  property_name, render_make_deferred_namespace_mode_from_exports_type,
+  reserved_names::RESERVED_NAMES, subtract_runtime_condition, to_identifier_with_escaped,
+  to_normal_comment,
 };
 
 type ExportsDefinitionArgs = Vec<(String, String)>;
@@ -799,7 +799,7 @@
       for dep_id in module.get_dependencies().iter() {
         let dep = module_graph.dependency_by_id(dep_id);
         let module_id_of_dep = module_graph.module_identifier_by_dependency_id(dep_id);
-        if !is_esm_dep_like(dep) || !modules.contains(&module_id_of_dep) {
+        if !is_esm_dep_like(dep.as_ref()) || !modules.contains(&module_id_of_dep) {
           self.dependencies.push(*dep_id);
         }
       }
@@ -2221,7 +2221,7 @@
       .into_iter()
       .filter_map(|connection| {
         let dep = mg.dependency_by_id(&connection.dependency_id);
-        if !is_esm_dep_like(dep) {
+        if !is_esm_dep_like(dep.as_ref()) {
           return None;
         }
         let ref_module = mg
@@ -3117,7 +3117,7 @@
   }
 }
 
-pub fn is_esm_dep_like(dep: &BoxDependency) -> bool {
+pub fn is_esm_dep_like(dep: &dyn Dependency) -> bool {
   matches!(
     dep.dependency_type(),
     DependencyType::EsmImportSpecifier

diff --git a/crates/rspack_core/src/dependency/dependency_trait.rs b/crates/rspack_core/src/dependency/dependency_trait.rs
--- a/crates/rspack_core/src/dependency/dependency_trait.rs
+++ b/crates/rspack_core/src/dependency/dependency_trait.rs
@@ -1,4 +1,4 @@
-use std::{any::Any, fmt::Debug};
+use std::{any::Any, fmt::Debug, sync::Arc};
 
 use dyn_clone::{DynClone, clone_trait_object};
 use rspack_cacheable::cacheable_dyn;
@@ -149,3 +149,4 @@
 clone_trait_object!(Dependency);
 
 pub type BoxDependency = Box<dyn Dependency>;
+pub type ArcDependency = Arc<dyn Dependency>;

diff --git a/crates/rspack_core/src/dependency/factorize_info.rs b/crates/rspack_core/src/dependency/factorize_info.rs
--- a/crates/rspack_core/src/dependency/factorize_info.rs
+++ b/crates/rspack_core/src/dependency/factorize_info.rs
@@ -2,7 +2,7 @@
 use rspack_error::Diagnostic;
 use rspack_paths::ArcPathSet;
 
-use super::{BoxDependency, DependencyId};
+use super::{Dependency, DependencyId};
 
 #[cacheable]
 #[derive(Debug, Clone, Default)]
@@ -31,7 +31,7 @@
     }
   }
 
-  pub fn get_from(dep: &BoxDependency) -> Option<&FactorizeInfo> {
+  pub fn get_from(dep: &dyn Dependency) -> Option<&FactorizeInfo> {
     if let Some(d) = dep.as_context_dependency() {
       Some(d.factorize_info())
     } else if let Some(d) = dep.as_module_dependency() {
@@ -41,7 +41,7 @@
     }
   }
 
-  pub fn revoke(dep: &mut BoxDependency) -> Option<FactorizeInfo> {
+  pub fn revoke(dep: &mut dyn Dependency) -> Option<FactorizeInfo> {
     if let Some(d) = dep.as_context_dependency_mut() {
       Some(std::mem::take(d.factorize_info_mut()))
     } else if let Some(d) = dep.as_module_dependency_mut() {

diff --git a/crates/rspack_core/src/incremental/mutations.rs b/crates/rspack_core/src/incremental/mutations.rs
--- a/crates/rspack_core/src/incremental/mutations.rs
+++ b/crates/rspack_core/src/incremental/mutations.rs
@@ -6,7 +6,7 @@
 use rspack_collections::{IdentifierSet, UkeySet};
 
 use crate::{
-  AffectType, BoxDependency, ChunkUkey, Compilation, DependencyId, ModuleGraph, ModuleIdentifier,
+  AffectType, ChunkUkey, Compilation, Dependency, DependencyId, ModuleGraph, ModuleIdentifier,
 };
 
 #[derive(Debug, Default)]
@@ -254,7 +254,7 @@
   built_modules: IdentifierSet,
   built_dependencies: UkeySet<DependencyId>,
 ) -> IdentifierSet {
-  fn reduce_affect_type<'a>(dependencies: impl Iterator<Item = &'a BoxDependency>) -> AffectType {
+  fn reduce_affect_type<'a>(dependencies: impl Iterator<Item = &'a dyn Dependency>) -> AffectType {
     let mut affected = AffectType::False;
     for dependency in dependencies {
       match dependency.could_affect_referencing_module() {
@@ -285,7 +285,7 @@
             match reduce_affect_type(
               connections
                 .iter()
-                .map(|c| module_graph.dependency_by_id(&c.dependency_id)),
+                .map(|c| module_graph.dependency_by_id(&c.dependency_id).as_ref()),
             ) {
               AffectType::False => None,
               AffectType::True => Some(AffectedModuleKind::Direct(referencing_module)),

diff --git a/crates/rspack_core/src/module_graph/internal.rs b/crates/rspack_core/src/module_graph/internal.rs
--- a/crates/rspack_core/src/module_graph/internal.rs
+++ b/crates/rspack_core/src/module_graph/internal.rs
@@ -4,7 +4,7 @@
 ///
 /// This module provides restricted access to potentially unsafe ModuleGraph operations
 /// that should only be used in specific contexts where items may legitimately not exist.
-use crate::{BoxDependency, DependencyId, ModuleGraph, ModuleGraphModule, ModuleIdentifier};
+use crate::{ArcDependency, DependencyId, ModuleGraph, ModuleGraphModule, ModuleIdentifier};
 
 /// Try to get a dependency by ID, returning None if not found.
 ///
@@ -30,7 +30,7 @@
 pub fn try_dependency_by_id<'a>(
   module_graph: &'a ModuleGraph,
   dependency_id: &DependencyId,
-) -> Option<&'a BoxDependency> {
+) -> Option<&'a ArcDependency> {
   module_graph.inner.dependencies.get(dependency_id)
 }
 

diff --git a/crates/rspack_core/src/module_graph/mod.rs b/crates/rspack_core/src/module_graph/mod.rs
--- a/crates/rspack_core/src/module_graph/mod.rs
+++ b/crates/rspack_core/src/module_graph/mod.rs
@@ -1,6 +1,9 @@
 pub mod internal;
 pub mod rollback;
 
+use std::sync::Arc;
+
+use dyn_clone::clone_box;
 use internal::try_get_module_graph_module_mut_by_identifier;
 use rayon::prelude::*;
 use rspack_error::Result;
@@ -9,19 +12,16 @@
 use swc_core::ecma::atoms::Atom;
 
 use crate::{
-  AsyncDependenciesBlock, AsyncDependenciesBlockIdentifier, AsyncModulesArtifact, Compilation,
-  DependenciesBlock, Dependency, ExportInfo, ExportName, ImportedByDeferModulesArtifact,
-  ModuleGraphCacheArtifact, RuntimeSpec, UsedNameItem,
+  ArcDependency, AsyncDependenciesBlock, AsyncDependenciesBlockIdentifier, AsyncModulesArtifact,
+  Compilation, DependenciesBlock, Dependency, ExportInfo, ExportName,
+  ImportedByDeferModulesArtifact, ModuleGraphCacheArtifact, RuntimeSpec, UsedNameItem,
 };
 mod module;
 pub use module::*;
 mod connection;
 pub use connection::*;
 
-use crate::{
-  BoxDependency, BoxModule, DependencyCondition, DependencyId, ExportsInfoArtifact,
-  ModuleIdentifier,
-};
+use crate::{BoxModule, DependencyCondition, DependencyId, ExportsInfoArtifact, ModuleIdentifier};
 
 // TODO Here request can be used Atom
 pub type ImportVarMap = HashMap<(Option<ModuleIdentifier>, bool), String /* import_var */>;
@@ -59,7 +59,7 @@
   pub(crate) modules: rollback::RollbackMap<ModuleIdentifier, BoxModule>,
 
   /// Dependencies indexed by `DependencyId`.
-  dependencies: HashMap<DependencyId, BoxDependency>,
+  dependencies: HashMap<DependencyId, ArcDependency>,
   /// AsyncDependenciesBlocks indexed by `AsyncDependenciesBlockIdentifier`.
   blocks: HashMap<AsyncDependenciesBlockIdentifier, Box<AsyncDependenciesBlock>>,
 
@@ -366,7 +366,7 @@
     &mut self,
     old_module: &ModuleIdentifier,
     new_module: &ModuleIdentifier,
-    filter_connection: impl Fn(&ModuleGraphConnection, &Box<dyn Dependency>) -> bool,
+    filter_connection: impl Fn(&ModuleGraphConnection, &dyn Dependency) -> bool,
   ) {
     if old_module == new_module {
       return;
@@ -384,7 +384,7 @@
         .connection_by_dependency_id(&dep_id)
         .expect("should have connection");
       let dependency = self.dependency_by_id(&dep_id);
-      if filter_connection(connection, dependency) {
+      if filter_connection(connection, dependency.as_ref()) {
         let connection = self
           .connection_by_dependency_id_mut(&dep_id)
           .expect("should have connection");
@@ -415,7 +415,7 @@
         .connection_by_dependency_id(&dep_id)
         .expect("should have connection");
       let dependency = self.dependency_by_id(&dep_id);
-      if filter_connection(connection, dependency) {
+      if filter_connection(connection, dependency.as_ref()) {
         let connection = self
           .connection_by_dependency_id_mut(&dep_id)
           .expect("should have connection");
@@ -441,7 +441,7 @@
     new_module: &ModuleIdentifier,
     filter_connection: F,
   ) where
-    F: Fn(&ModuleGraphConnection, &BoxDependency) -> bool,
+    F: Fn(&ModuleGraphConnection, &dyn Dependency) -> bool,
   {
     if old_module == new_module {
       return;
@@ -460,7 +460,7 @@
         .connection_by_dependency_id(&dep_id)
         .expect("should have connection");
       let dep = self.dependency_by_id(&dep_id);
-      if filter_connection(connection, dep) {
+      if filter_connection(connection, dep.as_ref()) {
         let con = self
           .connection_by_dependency_id_mut(&dep_id)
           .expect("should have connection");
@@ -556,11 +556,11 @@
     &self.inner.blocks
   }
 
-  pub fn dependencies(&self) -> impl Iterator<Item = (&DependencyId, &BoxDependency)> {
+  pub fn dependencies(&self) -> impl Iterator<Item = (&DependencyId, &ArcDependency)> {
     self.inner.dependencies.iter()
   }
 
-  pub fn add_dependency(&mut self, dependency: BoxDependency) {
+  pub fn add_dependency(&mut self, dependency: ArcDependency) {
     self.inner.dependencies.insert(*dependency.id(), dependency);
   }
 
@@ -579,7 +579,7 @@
   ///
   /// **Only the binding layer (`rspack_binding_api`) should use `internal::try_dependency_by_id()`**
   /// for graceful handling of missing dependencies in external APIs.
-  pub fn dependency_by_id(&self, dependency_id: &DependencyId) -> &BoxDependency {
+  pub fn dependency_by_id(&self, dependency_id: &DependencyId) -> &ArcDependency {
     self
       .inner
       .dependencies
@@ -592,12 +592,19 @@
   /// **PREFERRED METHOD**: Use this for ALL internal Rust code when you need to
   /// modify dependencies. Dependencies should always be accessible in internal
   /// operations, so this method enforces that invariant with a clear panic message.
-  pub fn dependency_by_id_mut(&mut self, dependency_id: &DependencyId) -> &mut BoxDependency {
-    self
+  pub fn dependency_by_id_mut(&mut self, dependency_id: &DependencyId) -> &mut dyn Dependency {
+    let dep = self
       .inner
       .dependencies
       .get_mut(dependency_id)
-      .unwrap_or_else(|| panic!("Dependency with ID {dependency_id:?} not found"))
+      .unwrap_or_else(|| panic!("Dependency with ID {dependency_id:?} not found"));
+    // Ensure unique mutable access; account for both strong and weak refs.
+    if Arc::get_mut(dep).is_none() {
+      *dep = Arc::from(clone_box(dep.as_ref()));
+    }
+    Arc::get_mut(dep).unwrap_or_else(|| {
+      panic!("Cannot obtain unique mutable access for dependency with ID {dependency_id:?}")
+    })
   }
 
   /// Uniquely identify a module by its dependency

diff --git a/crates/rspack_plugin_dynamic_entry/src/lib.rs b/crates/rspack_plugin_dynamic_entry/src/lib.rs
--- a/crates/rspack_plugin_dynamic_entry/src/lib.rs
+++ b/crates/rspack_plugin_dynamic_entry/src/lib.rs
@@ -78,7 +78,10 @@
             .entry(entry.into())
             .or_default()
             .insert(options.clone(), *dependency_id);
-          dependency.clone()
+          let dependency = dependency
+            .downcast_ref::<EntryDependency>()
+            .expect("dependency should be EntryDependency in DynamicEntryPlugin");
+          Box::new(dependency.clone())
         } else {
           let dependency: BoxDependency = Box::new(EntryDependency::new(
             entry.clone(),

diff --git a/crates/rspack_plugin_esm_library/src/plugin.rs b/crates/rspack_plugin_esm_library/src/plugin.rs
--- a/crates/rspack_plugin_esm_library/src/plugin.rs
+++ b/crates/rspack_plugin_esm_library/src/plugin.rs
@@ -120,7 +120,7 @@
         .get_incoming_connections(module_identifier)
         .map(|conn| module_graph.dependency_by_id(&conn.dependency_id))
         .any(|dep| {
-          !is_esm_dep_like(dep)
+          !is_esm_dep_like(dep.as_ref())
             && !matches!(
               dep.dependency_type(),
               DependencyType::Entry | DependencyType::DynamicImport
@@ -389,7 +389,7 @@
       .get_incoming_connections(module_identifier)
       .map(|conn| module_graph.dependency_by_id(&conn.dependency_id))
       .any(|dep| {
-        !is_esm_dep_like(dep)
+        !is_esm_dep_like(dep.as_ref())
           && !matches!(
             dep.dependency_type(),
             DependencyType::Entry | DependencyType::DynamicImport

diff --git a/crates/rspack_plugin_javascript/src/plugin/module_concatenation_plugin.rs b/crates/rspack_plugin_javascript/src/plugin/module_concatenation_plugin.rs
--- a/crates/rspack_plugin_javascript/src/plugin/module_concatenation_plugin.rs
+++ b/crates/rspack_plugin_javascript/src/plugin/module_concatenation_plugin.rs
@@ -6,7 +6,7 @@
   Identifiable, IdentifierDashMap, IdentifierIndexSet, IdentifierMap, IdentifierSet,
 };
 use rspack_core::{
-  BoxDependency, BoxModule, Compilation, CompilationOptimizeChunkModules, DependencyId,
+  BoxModule, Compilation, CompilationOptimizeChunkModules, Dependency, DependencyId,
   DependencyType, ExportProvided, ExportsInfoArtifact, ExtendedReferencedExport, GetTargetResult,
   ImportedByDeferModulesArtifact, LibIdentOptions, Logger, ModuleGraph, ModuleGraphCacheArtifact,
   ModuleGraphConnection, ModuleGraphModule, ModuleIdentifier, Plugin, PrefetchExportsInfoMode,
@@ -473,7 +473,7 @@
       for (origin_module, connections) in incoming_connections_from_modules.iter() {
         let has_non_esm_connections = connections.iter().any(|connection| {
           let dep = module_graph.dependency_by_id(&connection.dependency_id);
-          !is_esm_dep_like(dep)
+          !is_esm_dep_like(dep.as_ref())
         });
 
         if has_non_esm_connections {
@@ -1104,7 +1104,7 @@
           .iter()
           .filter_map(|d| {
             let dep = module_graph.dependency_by_id(d);
-            if !is_esm_dep_like(dep) {
+            if !is_esm_dep_like(dep.as_ref()) {
               return None;
             }
             let con = module_graph.connection_by_dependency_id(d)?;
@@ -1570,7 +1570,7 @@
   filter_connection: F,
 ) -> Vec<DependencyId>
 where
-  F: Fn(&ModuleIdentifier, &ModuleGraphConnection, &BoxDependency) -> bool,
+  F: Fn(&ModuleIdentifier, &ModuleGraphConnection, &dyn Dependency) -> bool,
 {
   let mg = compilation.get_module_graph();
   let mut res = vec![];
@@ -1590,7 +1590,7 @@
         .connection_by_dependency_id(dep_id)
         .expect("should have connection");
       let dep = mg.dependency_by_id(dep_id);
-      if filter_connection(m, connection, dep) {
+      if filter_connection(m, connection, dep.as_ref()) {
         res.push(*dep_id);
       }
     }
@@ -1604,7 +1604,7 @@
   filter_connection: F,
 ) -> (Vec<DependencyId>, Vec<DependencyId>)
 where
-  F: Fn(&ModuleIdentifier, &ModuleGraphConnection, &BoxDependency) -> bool,
+  F: Fn(&ModuleIdentifier, &ModuleGraphConnection, &dyn Dependency) -> bool,
 {
   let mg = compilation.get_module_graph();
   let mut outgoings = vec![];
@@ -1619,7 +1619,7 @@
       .expect("should have connection");
 
     let dep = mg.dependency_by_id(dep_id);
-    if filter_connection(root_module_id, connection, dep) {
+    if filter_connection(root_module_id, connection, dep.as_ref()) {
       outgoings.push(*dep_id);
     }
   }
@@ -1635,7 +1635,7 @@
       .connection_by_dependency_id(dep_id)
       .expect("should have connection");
     let dependency = mg.dependency_by_id(dep_id);
-    if filter_connection(root_module_id, connection, dependency) {
+    if filter_connection(root_module_id, connection, dependency.as_ref()) {
       incomings.push(*dep_id);
     }
   }

diff --git a/crates/rspack_plugin_library/src/modern_module_library_plugin.rs b/crates/rspack_plugin_library/src/modern_module_library_plugin.rs
--- a/crates/rspack_plugin_library/src/modern_module_library_plugin.rs
+++ b/crates/rspack_plugin_library/src/modern_module_library_plugin.rs
@@ -237,7 +237,7 @@
       // remove connection
       mg.revoke_dependency(dep_id, false);
       // overwrite dependency
-      mg.add_dependency(dep);
+      mg.add_dependency(dep.into());
     }
 
     for connection in &external_connections {

@hardfist hardfist force-pushed the codex/yj/arc-dependency branch from 59ca3b1 to 2055ec3 Compare February 28, 2026 08:28
@github-actions
Copy link
Contributor

github-actions bot commented Feb 28, 2026

📝 Benchmark detail: Open

Name Base (2026-02-28 10ed485) Current Change
10000_big_production-mode_disable-minimize + exec 13.9 s ± 327 ms 14 s ± 220 ms +0.54 %
10000_development-mode + exec 1.05 s ± 8 ms 1.08 s ± 22 ms +2.77 %
10000_development-mode_hmr + stats 197 ms ± 5.3 ms 197 ms ± 4 ms +0.13 %
10000_development-mode_noop-loader + exec 2.13 s ± 64 ms 2.15 s ± 113 ms +1.05 %
10000_production-mode + exec 1.15 s ± 40 ms 1.17 s ± 33 ms +1.39 %
10000_production-mode_persistent-cold + exec 1.34 s ± 50 ms 1.36 s ± 22 ms +1.45 %
10000_production-mode_persistent-hot + exec 971 ms ± 31 ms 981 ms ± 23 ms +1.07 %
10000_production-mode_source-map + exec 1.32 s ± 18 ms 1.35 s ± 38 ms +2.52 %
arco-pro_development-mode + exec 1.32 s ± 86 ms 1.34 s ± 106 ms +0.91 %
arco-pro_development-mode_hmr + stats 39 ms ± 1.2 ms 43 ms ± 2.8 ms +9.68 %
arco-pro_production-mode + exec 2.37 s ± 110 ms 2.4 s ± 76 ms +1.08 %
arco-pro_production-mode_generate-package-json-webpack-plugin + exec 2.41 s ± 90 ms 2.47 s ± 96 ms +2.63 %
arco-pro_production-mode_persistent-cold + exec 2.47 s ± 69 ms 2.49 s ± 52 ms +0.77 %
arco-pro_production-mode_persistent-hot + exec 1.4 s ± 37 ms 1.41 s ± 27 ms +0.89 %
arco-pro_production-mode_source-map + exec 2.89 s ± 72 ms 2.95 s ± 94 ms +2.01 %
arco-pro_production-mode_traverse-chunk-modules + exec 2.42 s ± 133 ms 2.42 s ± 76 ms +0.27 %
bundled-threejs_development-mode + exec 194 ms ± 7 ms 196 ms ± 3.1 ms +1.24 %
bundled-threejs_production-mode + exec 227 ms ± 3.3 ms 229 ms ± 2.4 ms +1.06 %
large-dyn-imports_development-mode + exec 1.31 s ± 49 ms 1.33 s ± 52 ms +1.57 %
large-dyn-imports_production-mode + exec 1.4 s ± 21 ms 1.42 s ± 45 ms +1.56 %
threejs_development-mode_10x + exec 862 ms ± 9.6 ms 853 ms ± 18 ms -1.07 %
threejs_development-mode_10x_hmr + stats 136 ms ± 1.5 ms 139 ms ± 7.2 ms +2.19 %
threejs_production-mode_10x + exec 2.96 s ± 29 ms 2.97 s ± 42 ms +0.20 %
threejs_production-mode_10x_persistent-cold + exec 3.09 s ± 26 ms 3.12 s ± 37 ms +1.02 %
threejs_production-mode_10x_persistent-hot + exec 2.48 s ± 32 ms 2.49 s ± 40 ms +0.38 %
threejs_production-mode_10x_source-map + exec 3.7 s ± 45 ms 3.72 s ± 53 ms +0.44 %
10000_big_production-mode_disable-minimize + rss memory 2242 MiB ± 163 MiB 2216 MiB ± 76.9 MiB -1.14 %
10000_development-mode + rss memory 672 MiB ± 31.5 MiB 682 MiB ± 33.6 MiB +1.50 %
10000_development-mode_hmr + rss memory 854 MiB ± 22.6 MiB 863 MiB ± 30.8 MiB +0.99 %
10000_development-mode_noop-loader + rss memory 982 MiB ± 35.5 MiB 964 MiB ± 36.1 MiB -1.80 %
10000_production-mode + rss memory 558 MiB ± 16.2 MiB 554 MiB ± 15.9 MiB -0.85 %
10000_production-mode_persistent-cold + rss memory 780 MiB ± 36.8 MiB 778 MiB ± 11.1 MiB -0.26 %
10000_production-mode_persistent-hot + rss memory 767 MiB ± 19.7 MiB 773 MiB ± 14 MiB +0.75 %
10000_production-mode_source-map + rss memory 620 MiB ± 22.6 MiB 635 MiB ± 58.7 MiB +2.42 %
arco-pro_development-mode + rss memory 544 MiB ± 33.1 MiB 536 MiB ± 37.7 MiB -1.51 %
arco-pro_development-mode_hmr + rss memory 484 MiB ± 15.5 MiB 487 MiB ± 10.9 MiB +0.72 %
arco-pro_production-mode + rss memory 609 MiB ± 36 MiB 618 MiB ± 40.1 MiB +1.40 %
arco-pro_production-mode_generate-package-json-webpack-plugin + rss memory 629 MiB ± 48.1 MiB 604 MiB ± 28.9 MiB -3.88 %
arco-pro_production-mode_persistent-cold + rss memory 681 MiB ± 40.8 MiB 669 MiB ± 28.7 MiB -1.76 %
arco-pro_production-mode_persistent-hot + rss memory 433 MiB ± 60.6 MiB 439 MiB ± 77.4 MiB +1.38 %
arco-pro_production-mode_source-map + rss memory 697 MiB ± 50.4 MiB 721 MiB ± 79.4 MiB +3.49 %
arco-pro_production-mode_traverse-chunk-modules + rss memory 604 MiB ± 63.6 MiB 605 MiB ± 42 MiB +0.05 %
bundled-threejs_development-mode + rss memory 173 MiB ± 4.89 MiB 169 MiB ± 2.08 MiB -2.26 %
bundled-threejs_production-mode + rss memory 199 MiB ± 10.4 MiB 194 MiB ± 25.4 MiB -2.61 %
large-dyn-imports_development-mode + rss memory 694 MiB ± 15.5 MiB 685 MiB ± 7.68 MiB -1.24 %
large-dyn-imports_production-mode + rss memory 495 MiB ± 6.7 MiB 496 MiB ± 10.2 MiB +0.12 %
threejs_development-mode_10x + rss memory 535 MiB ± 25.4 MiB 539 MiB ± 14.1 MiB +0.80 %
threejs_development-mode_10x_hmr + rss memory 652 MiB ± 22 MiB 650 MiB ± 9.86 MiB -0.42 %
threejs_production-mode_10x + rss memory 651 MiB ± 18.2 MiB 649 MiB ± 14.2 MiB -0.33 %
threejs_production-mode_10x_persistent-cold + rss memory 794 MiB ± 7.68 MiB 772 MiB ± 16.4 MiB -2.68 %
threejs_production-mode_10x_persistent-hot + rss memory 642 MiB ± 15.9 MiB 634 MiB ± 11.7 MiB -1.23 %
threejs_production-mode_10x_source-map + rss memory 724 MiB ± 61.9 MiB 668 MiB ± 126 MiB -7.82 %

@github-actions
Copy link
Contributor

github-actions bot commented Feb 28, 2026

📦 Binary Size-limit

Comparing 568eb2b to fix: when there are 2+ dep targets in the same chunk, create facade chunks for all of them (#13154) by Fy

🎉 Size decreased by 29.75KB from 48.89MB to 48.86MB (⬇️0.06%)

@codspeed-hq
Copy link

codspeed-hq bot commented Feb 28, 2026

Merging this PR will not alter performance

✅ 16 untouched benchmarks
⏩ 3 skipped benchmarks1


Comparing codex/yj/arc-dependency (568eb2b) with main (7da4bdc)

Open in CodSpeed

Footnotes

  1. 3 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@github-actions
Copy link
Contributor

github-actions bot commented Feb 28, 2026

📝 Benchmark detail: Open

task failure

@hardfist
Copy link
Contributor Author

@cursoragent review

@cursor
Copy link

cursor bot commented Feb 28, 2026

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: COW check misses weak references causing potential panic
    • Replaced strong_count-based COW guard with Arc::get_mut uniqueness check and updated the panic to reflect exclusivity failure, preventing a panic when only weak refs exist.

Create PR

Preview (c3d149a863)
diff --git a/crates/rspack_binding_api/src/compilation/mod.rs b/crates/rspack_binding_api/src/compilation/mod.rs
--- a/crates/rspack_binding_api/src/compilation/mod.rs
+++ b/crates/rspack_binding_api/src/compilation/mod.rs
@@ -838,7 +838,7 @@
             .into_iter()
             .map(|dependency_id| {
               let dependency = module_graph.dependency_by_id(&dependency_id);
-              if let Some(factorize_info) = FactorizeInfo::get_from(dependency)
+              if let Some(factorize_info) = FactorizeInfo::get_from(dependency.as_ref())
                 && let Some(diagnostic) = factorize_info.diagnostics().first()
               {
                 return Either::A(diagnostic.to_string());
@@ -942,7 +942,7 @@
             .into_iter()
             .map(|dependency_id| {
               let dependency = module_graph.dependency_by_id(&dependency_id);
-              if let Some(factorize_info) = FactorizeInfo::get_from(dependency)
+              if let Some(factorize_info) = FactorizeInfo::get_from(dependency.as_ref())
                 && let Some(diagnostic) = factorize_info.diagnostics().first()
               {
                 return Either::A(diagnostic.to_string());

diff --git a/crates/rspack_core/src/artifacts/build_module_graph_artifact.rs b/crates/rspack_core/src/artifacts/build_module_graph_artifact.rs
--- a/crates/rspack_core/src/artifacts/build_module_graph_artifact.rs
+++ b/crates/rspack_core/src/artifacts/build_module_graph_artifact.rs
@@ -208,7 +208,7 @@
     let dep_diagnostics = self.make_failed_dependencies.iter().flat_map(|dep_id| {
       let dep = mg.dependency_by_id(dep_id);
       let origin_module_identifier = mg.get_parent_module(dep_id);
-      FactorizeInfo::get_from(dep)
+      FactorizeInfo::get_from(dep.as_ref())
         .expect("should have factorize info")
         .diagnostics()
         .iter()

diff --git a/crates/rspack_core/src/cache/persistent/occasion/make/mod.rs b/crates/rspack_core/src/cache/persistent/occasion/make/mod.rs
--- a/crates/rspack_core/src/cache/persistent/occasion/make/mod.rs
+++ b/crates/rspack_core/src/cache/persistent/occasion/make/mod.rs
@@ -97,7 +97,7 @@
     // recovery make_failed_dependencies
     let mut make_failed_dependencies = FxHashSet::default();
     for (dep_id, dep) in mg.dependencies() {
-      if let Some(info) = FactorizeInfo::get_from(dep) {
+      if let Some(info) = FactorizeInfo::get_from(dep.as_ref()) {
         if !info.is_success() {
           make_failed_dependencies.insert(*dep_id);
         }

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
--- a/crates/rspack_core/src/cache/persistent/occasion/make/module_graph.rs
+++ b/crates/rspack_core/src/cache/persistent/occasion/make/module_graph.rs
@@ -3,6 +3,7 @@
   atomic::{AtomicUsize, Ordering},
 };
 
+use dyn_clone::clone_box;
 use rayon::prelude::*;
 use rspack_cacheable::{cacheable, utils::OwnedOrRef};
 use rspack_collections::IdentifierSet;
@@ -71,7 +72,7 @@
         .par_iter()
         .map(|dep_id| {
           (
-            mg.dependency_by_id(dep_id).into(),
+            clone_box(mg.dependency_by_id(dep_id).as_ref()).into(),
             mg.get_parent_block(dep_id).map(Into::into),
           )
         })
@@ -158,7 +159,7 @@
             index_in_block,
           },
         );
-        mg.add_dependency(dep);
+        mg.add_dependency(dep.into());
       }
       for con in node.connections {
         let con = con.into_owned();
@@ -194,7 +195,8 @@
     let dep = TempDependency::default();
     let connection = ModuleGraphConnection::new(*dep.id(), None, mid, false);
     entry_dependencies.insert(*dep.id());
-    mg.add_dependency(Box::new(dep));
+    let dep: BoxDependency = Box::new(dep);
+    mg.add_dependency(dep.into());
     mg.cache_recovery_connection(connection);
   }
 

diff --git a/crates/rspack_core/src/compilation/build_module_graph/graph_updater/repair/add.rs b/crates/rspack_core/src/compilation/build_module_graph/graph_updater/repair/add.rs
--- a/crates/rspack_core/src/compilation/build_module_graph/graph_updater/repair/add.rs
+++ b/crates/rspack_core/src/compilation/build_module_graph/graph_updater/repair/add.rs
@@ -2,7 +2,7 @@
 
 use super::{TaskContext, build::BuildTask, lazy::process_unlazy_dependencies};
 use crate::{
-  BoxDependency, BoxModule, ModuleIdentifier,
+  ArcDependency, BoxModule, ModuleIdentifier,
   compilation::build_module_graph::ForwardedIdSet,
   module_graph::{ModuleGraph, ModuleGraphModule},
   utils::task_loop::{Task, TaskResult, TaskType},
@@ -13,7 +13,7 @@
   pub original_module_identifier: Option<ModuleIdentifier>,
   pub module: BoxModule,
   pub module_graph_module: Box<ModuleGraphModule>,
-  pub dependencies: Vec<BoxDependency>,
+  pub dependencies: Vec<ArcDependency>,
   pub from_unlazy: bool,
 }
 
@@ -131,7 +131,7 @@
 fn set_resolved_module(
   module_graph: &mut ModuleGraph,
   original_module_identifier: Option<ModuleIdentifier>,
-  dependencies: Vec<BoxDependency>,
+  dependencies: Vec<ArcDependency>,
   module_identifier: ModuleIdentifier,
 ) -> Result<()> {
   for dependency in dependencies {

diff --git a/crates/rspack_core/src/compilation/build_module_graph/graph_updater/repair/build.rs b/crates/rspack_core/src/compilation/build_module_graph/graph_updater/repair/build.rs
--- a/crates/rspack_core/src/compilation/build_module_graph/graph_updater/repair/build.rs
+++ b/crates/rspack_core/src/compilation/build_module_graph/graph_updater/repair/build.rs
@@ -163,7 +163,7 @@
             index_in_block,
           },
         );
-        module_graph.add_dependency(dependency);
+        module_graph.add_dependency(dependency.into());
       }
       if let Some(current_block) = current_block {
         module.add_block_id(current_block.identifier());

diff --git a/crates/rspack_core/src/compilation/build_module_graph/graph_updater/repair/factorize.rs b/crates/rspack_core/src/compilation/build_module_graph/graph_updater/repair/factorize.rs
--- a/crates/rspack_core/src/compilation/build_module_graph/graph_updater/repair/factorize.rs
+++ b/crates/rspack_core/src/compilation/build_module_graph/graph_updater/repair/factorize.rs
@@ -5,7 +5,7 @@
 
 use super::{TaskContext, add::AddTask};
 use crate::{
-  BoxDependency, CompilationId, CompilerId, CompilerOptions, Context, FactorizeInfo, ModuleFactory,
+  ArcDependency, CompilationId, CompilerId, CompilerOptions, Context, FactorizeInfo, ModuleFactory,
   ModuleFactoryCreateData, ModuleFactoryResult, ModuleIdentifier, ModuleLayer, Resolve,
   ResolverFactory,
   module_graph::ModuleGraphModule,
@@ -25,7 +25,7 @@
   pub original_module_context: Option<Box<Context>>,
   pub issuer: Option<Box<str>>,
   pub issuer_layer: Option<ModuleLayer>,
-  pub dependencies: Vec<BoxDependency>,
+  pub dependencies: Vec<ArcDependency>,
   pub resolve_options: Option<Arc<Resolve>>,
   pub options: Arc<CompilerOptions>,
   pub resolver_factory: Arc<ResolverFactory>,
@@ -38,7 +38,7 @@
     TaskType::Background
   }
   async fn background_run(mut self: Box<Self>) -> TaskResult<TaskContext> {
-    let dependency = &self.dependencies[0];
+    let dependency = self.dependencies[0].as_ref();
 
     let context = if let Some(context) = dependency.get_context()
       && !context.is_empty()
@@ -59,10 +59,12 @@
       .cloned();
 
     let request = self.dependencies[0]
+      .as_ref()
       .as_module_dependency()
       .map(|d| d.request().to_string())
       .or_else(|| {
         self.dependencies[0]
+          .as_ref()
           .as_context_dependency()
           .map(|d| d.request().to_string())
       })
@@ -136,7 +138,7 @@
   pub original_module_identifier: Option<ModuleIdentifier>,
   /// Result will be available if [crate::ModuleFactory::create] returns `Ok`.
   pub factory_result: Option<ModuleFactoryResult>,
-  pub dependencies: Vec<BoxDependency>,
+  pub dependencies: Vec<ArcDependency>,
   pub factorize_info: FactorizeInfo,
   pub from_unlazy: bool,
 }
@@ -177,15 +179,14 @@
       // so add all dependencies here.
       artifact.affected_dependencies.mark_as_add(dep.id());
 
-      let dep_factorize_info = if let Some(d) = dep.as_context_dependency_mut() {
-        d.factorize_info_mut()
-      } else if let Some(d) = dep.as_module_dependency_mut() {
-        d.factorize_info_mut()
+      let dep_mut = if let Some(dep) = Arc::get_mut(dep) {
+        dep
       } else {
+        unreachable!("factorize dependencies should be uniquely owned")
+      };
+      if FactorizeInfo::set(dep_mut, std::mem::take(&mut factorize_info)).is_none() {
         unreachable!("only module dependency and context dependency can factorize")
-      };
-      // write factorize_info to dependencies[0] and set success factorize_info to others
-      *dep_factorize_info = std::mem::take(&mut factorize_info);
+      }
     }
 
     let module_graph = artifact.get_module_graph_mut();
@@ -194,7 +195,7 @@
       tracing::trace!("Module created with failure, but without bailout: {dep:?}");
       // sync dependencies to mg
       for dep in dependencies {
-        module_graph.add_dependency(dep)
+        module_graph.add_dependency(dep.into())
       }
       return Ok(vec![]);
     };
@@ -204,7 +205,7 @@
       tracing::trace!("Module ignored: {dep:?}");
       // sync dependencies to mg
       for dep in dependencies {
-        module_graph.add_dependency(dep)
+        module_graph.add_dependency(dep.into())
       }
       return Ok(vec![]);
     };

diff --git a/crates/rspack_core/src/compilation/build_module_graph/graph_updater/repair/lazy.rs b/crates/rspack_core/src/compilation/build_module_graph/graph_updater/repair/lazy.rs
--- a/crates/rspack_core/src/compilation/build_module_graph/graph_updater/repair/lazy.rs
+++ b/crates/rspack_core/src/compilation/build_module_graph/graph_updater/repair/lazy.rs
@@ -18,7 +18,7 @@
   let dependencies_to_process: Vec<DependencyId> = lazy_dependencies
     .requested_lazy_dependencies(&forwarded_ids)
     .into_iter()
-    .filter(|dep| module_graph.dependency_by_id_mut(dep).unset_lazy())
+    .filter(|dep| module_graph.dependency_by_id(dep).unset_lazy())
     .collect();
 
   if dependencies_to_process.is_empty() {

diff --git a/crates/rspack_core/src/compilation/build_module_graph/graph_updater/repair/mod.rs b/crates/rspack_core/src/compilation/build_module_graph/graph_updater/repair/mod.rs
--- a/crates/rspack_core/src/compilation/build_module_graph/graph_updater/repair/mod.rs
+++ b/crates/rspack_core/src/compilation/build_module_graph/graph_updater/repair/mod.rs
@@ -47,7 +47,7 @@
           Box::new(factorize::FactorizeTask {
             compiler_id: compilation.compiler_id(),
             compilation_id: compilation.id(),
-            module_factory: compilation.get_dependency_factory(dependency),
+            module_factory: compilation.get_dependency_factory(dependency.as_ref()),
             original_module_identifier: None,
             original_module_source: None,
             issuer: None,

diff --git a/crates/rspack_core/src/compilation/build_module_graph/graph_updater/repair/process_dependencies.rs b/crates/rspack_core/src/compilation/build_module_graph/graph_updater/repair/process_dependencies.rs
--- a/crates/rspack_core/src/compilation/build_module_graph/graph_updater/repair/process_dependencies.rs
+++ b/crates/rspack_core/src/compilation/build_module_graph/graph_updater/repair/process_dependencies.rs
@@ -4,7 +4,7 @@
 
 use super::{TaskContext, factorize::FactorizeTask};
 use crate::{
-  ContextDependency, DependencyId, Module, ModuleIdentifier,
+  ArcDependency, ContextDependency, DependencyId, Module, ModuleIdentifier,
   utils::task_loop::{Task, TaskResult, TaskType},
 };
 
@@ -27,7 +27,7 @@
       dependencies,
       from_unlazy,
     } = *self;
-    let mut sorted_dependencies = HashMap::default();
+    let mut sorted_dependencies: HashMap<_, Vec<ArcDependency>> = HashMap::default();
 
     // First mark all dependencies as added
     for dependency_id in &dependencies {
@@ -80,7 +80,7 @@
         .module_by_identifier(&original_module_identifier)
         .and_then(|m| m.as_normal_module())
         .and_then(|m| m.source().cloned());
-      let dependency = &dependencies[0];
+      let dependency = dependencies[0].as_ref();
       let dependency_type = dependency.dependency_type();
       // TODO move module_factory calculate to dependency factories
       let module_factory = context

diff --git a/crates/rspack_core/src/compilation/build_module_graph/lazy_barrel_artifact.rs b/crates/rspack_core/src/compilation/build_module_graph/lazy_barrel_artifact.rs
--- a/crates/rspack_core/src/compilation/build_module_graph/lazy_barrel_artifact.rs
+++ b/crates/rspack_core/src/compilation/build_module_graph/lazy_barrel_artifact.rs
@@ -6,7 +6,7 @@
 use rspack_util::atom::Atom;
 use rustc_hash::{FxHashMap, FxHashSet};
 
-use crate::{BoxDependency, DependencyId, ModuleIdentifier};
+use crate::{ArcDependency, BoxDependency, DependencyId, ModuleIdentifier};
 
 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
 pub enum ForwardId {
@@ -26,7 +26,7 @@
     Self::IdSet(FxHashSet::default())
   }
 
-  pub fn from_dependencies(dependencies: &[BoxDependency]) -> Self {
+  pub fn from_dependencies(dependencies: &[ArcDependency]) -> Self {
     let mut set = FxHashSet::default();
     for dep in dependencies {
       match dep.forward_id() {

diff --git a/crates/rspack_core/src/compilation/build_module_graph/module_executor/entry.rs b/crates/rspack_core/src/compilation/build_module_graph/module_executor/entry.rs
--- a/crates/rspack_core/src/compilation/build_module_graph/module_executor/entry.rs
+++ b/crates/rspack_core/src/compilation/build_module_graph/module_executor/entry.rs
@@ -7,7 +7,7 @@
   overwrite::overwrite_tasks,
 };
 use crate::{
-  Context, Dependency, LoaderImportDependency,
+  ArcDependency, BoxDependency, Context, LoaderImportDependency,
   utils::task_loop::{Task, TaskResult, TaskType},
 };
 
@@ -44,14 +44,15 @@
     let (dep_id, is_new) = match entries.entry(meta.clone()) {
       Entry::Vacant(v) => {
         // not exist, generate a new dependency
-        let dep = Box::new(LoaderImportDependency::new(
+        let dep: BoxDependency = Box::new(LoaderImportDependency::new(
           meta.request.clone(),
           origin_module_context.unwrap_or_else(|| Context::from("")),
         ));
+        let dep_arc: ArcDependency = dep.clone().into();
         let dep_id = *dep.id();
 
         let mg = TaskContext::get_module_graph_mut(&mut origin_context.artifact);
-        mg.add_dependency(dep.clone());
+        mg.add_dependency(dep.clone().into());
 
         res.extend(overwrite_tasks(vec![Box::new(FactorizeTask {
           compiler_id: origin_context.compiler_id,
@@ -71,7 +72,7 @@
           issuer: None,
           issuer_layer: meta.layer.clone(),
           original_module_context: None,
-          dependencies: vec![dep],
+          dependencies: vec![dep_arc],
           resolve_options: None,
           options: origin_context.compiler_options.clone(),
           resolver_factory: origin_context.resolver_factory.clone(),

diff --git a/crates/rspack_core/src/compilation/build_module_graph/module_executor/execute.rs b/crates/rspack_core/src/compilation/build_module_graph/module_executor/execute.rs
--- a/crates/rspack_core/src/compilation/build_module_graph/module_executor/execute.rs
+++ b/crates/rspack_core/src/compilation/build_module_graph/module_executor/execute.rs
@@ -177,7 +177,7 @@
       for dep_id in module.get_dependencies() {
         if !has_error && make_failed_dependencies.contains(dep_id) {
           let dep = mg.dependency_by_id(dep_id);
-          let diagnostics = FactorizeInfo::get_from(dep)
+          let diagnostics = FactorizeInfo::get_from(dep.as_ref())
             .expect("should have factorize info")
             .diagnostics();
           let errors: Vec<_> = diagnostics

diff --git a/crates/rspack_core/src/compilation/mod.rs b/crates/rspack_core/src/compilation/mod.rs
--- a/crates/rspack_core/src/compilation/mod.rs
+++ b/crates/rspack_core/src/compilation/mod.rs
@@ -70,10 +70,10 @@
   ChunkRenderCacheArtifact, ChunkRenderResult, ChunkUkey, CodeGenerateCacheArtifact,
   CodeGenerationJob, CodeGenerationResult, CodeGenerationResults, CompilationLogger,
   CompilationLogging, CompilerOptions, CompilerPlatform, ConcatenationScope,
-  DependenciesDiagnosticsArtifact, DependencyId, DependencyTemplate, DependencyTemplateType,
-  DependencyType, Entry, EntryData, EntryOptions, EntryRuntime, Entrypoint, ExecuteModuleId,
-  ExportsInfoArtifact, ExtendedReferencedExport, Filename, ImportPhase, ImportVarMap,
-  ImportedByDeferModulesArtifact, MemoryGCStorage, ModuleFactory, ModuleGraph,
+  DependenciesDiagnosticsArtifact, Dependency, DependencyId, DependencyTemplate,
+  DependencyTemplateType, DependencyType, Entry, EntryData, EntryOptions, EntryRuntime, Entrypoint,
+  ExecuteModuleId, ExportsInfoArtifact, ExtendedReferencedExport, Filename, ImportPhase,
+  ImportVarMap, ImportedByDeferModulesArtifact, MemoryGCStorage, ModuleFactory, ModuleGraph,
   ModuleGraphCacheArtifact, ModuleIdentifier, ModuleIdsArtifact, ModuleStaticCache, PathData,
   ProcessRuntimeRequirementsCacheArtifact, ResolverFactory, RuntimeGlobals, RuntimeKeyMap,
   RuntimeMode, RuntimeModule, RuntimeSpec, RuntimeSpecMap, RuntimeTemplate, SharedPluginDriver,
@@ -616,7 +616,7 @@
     self
       .build_module_graph_artifact
       .get_module_graph_mut()
-      .add_dependency(entry);
+      .add_dependency(entry.into());
     if let Some(name) = &entry_name {
       if let Some(data) = self.entries.get_mut(name) {
         data.dependencies.push(entry_id);
@@ -684,7 +684,7 @@
       self
         .build_module_graph_artifact
         .get_module_graph_mut()
-        .add_dependency(entry);
+        .add_dependency(entry.into());
       if let Some(name) = options.name.clone() {
         if let Some(data) = self.entries.get_mut(&name) {
           data.include_dependencies.push(entry_id);
@@ -1216,7 +1216,7 @@
       .insert(dependency_type, module_factory);
   }
 
-  pub fn get_dependency_factory(&self, dependency: &BoxDependency) -> Arc<dyn ModuleFactory> {
+  pub fn get_dependency_factory(&self, dependency: &dyn Dependency) -> Arc<dyn ModuleFactory> {
     let dependency_type = dependency.dependency_type();
     self
       .dependency_factories

diff --git a/crates/rspack_core/src/concatenated_module.rs b/crates/rspack_core/src/concatenated_module.rs
--- a/crates/rspack_core/src/concatenated_module.rs
+++ b/crates/rspack_core/src/concatenated_module.rs
@@ -38,24 +38,24 @@
 use swc_node_comments::SwcComments;
 
 use crate::{
-  AsyncDependenciesBlockIdentifier, BoxDependency, BoxDependencyTemplate, BoxModule,
-  BoxModuleDependency, BuildContext, BuildInfo, BuildMeta, BuildMetaDefaultObject,
-  BuildMetaExportsType, BuildResult, ChunkGraph, ChunkInitFragments, ChunkRenderContext,
-  CodeGenerationDataTopLevelDeclarations, CodeGenerationExportsFinalNames,
-  CodeGenerationPublicPathAutoReplace, CodeGenerationResult, Compilation, ConcatenatedModuleIdent,
-  ConcatenationScope, ConditionalInitFragment, ConnectionState, Context, DEFAULT_EXPORT,
-  DEFAULT_EXPORT_ATOM, DependenciesBlock, DependencyId, DependencyType, ExportInfoHashKey,
-  ExportProvided, ExportsArgument, ExportsInfoArtifact, ExportsInfoGetter, ExportsType,
-  FactoryMeta, GetUsedNameParam, ImportedByDeferModulesArtifact, InitFragment, InitFragmentStage,
-  LibIdentOptions, Module, ModuleArgument, ModuleCodeGenerationContext, ModuleGraph,
-  ModuleGraphCacheArtifact, ModuleGraphConnection, ModuleIdentifier, ModuleLayer,
-  ModuleStaticCache, ModuleType, NAMESPACE_OBJECT_EXPORT, ParserOptions, PrefetchExportsInfoMode,
-  Resolve, RuntimeCondition, RuntimeGlobals, RuntimeSpec, SourceType, URLStaticMode, UsageState,
-  UsedName, UsedNameItem, escape_identifier, filter_runtime, find_target, get_runtime_key,
-  impl_source_map_config, merge_runtime_condition, merge_runtime_condition_non_false,
-  module_update_hash, property_access, property_name,
-  render_make_deferred_namespace_mode_from_exports_type, reserved_names::RESERVED_NAMES,
-  subtract_runtime_condition, to_identifier_with_escaped, to_normal_comment,
+  AsyncDependenciesBlockIdentifier, BoxDependencyTemplate, BoxModule, BoxModuleDependency,
+  BuildContext, BuildInfo, BuildMeta, BuildMetaDefaultObject, BuildMetaExportsType, BuildResult,
+  ChunkGraph, ChunkInitFragments, ChunkRenderContext, CodeGenerationDataTopLevelDeclarations,
+  CodeGenerationExportsFinalNames, CodeGenerationPublicPathAutoReplace, CodeGenerationResult,
+  Compilation, ConcatenatedModuleIdent, ConcatenationScope, ConditionalInitFragment,
+  ConnectionState, Context, DEFAULT_EXPORT, DEFAULT_EXPORT_ATOM, DependenciesBlock, Dependency,
+  DependencyId, DependencyType, ExportInfoHashKey, ExportProvided, ExportsArgument,
+  ExportsInfoArtifact, ExportsInfoGetter, ExportsType, FactoryMeta, GetUsedNameParam,
+  ImportedByDeferModulesArtifact, InitFragment, InitFragmentStage, LibIdentOptions, Module,
+  ModuleArgument, ModuleCodeGenerationContext, ModuleGraph, ModuleGraphCacheArtifact,
+  ModuleGraphConnection, ModuleIdentifier, ModuleLayer, ModuleStaticCache, ModuleType,
+  NAMESPACE_OBJECT_EXPORT, ParserOptions, PrefetchExportsInfoMode, Resolve, RuntimeCondition,
+  RuntimeGlobals, RuntimeSpec, SourceType, URLStaticMode, UsageState, UsedName, UsedNameItem,
+  escape_identifier, filter_runtime, find_target, get_runtime_key, impl_source_map_config,
+  merge_runtime_condition, merge_runtime_condition_non_false, module_update_hash, property_access,
+  property_name, render_make_deferred_namespace_mode_from_exports_type,
+  reserved_names::RESERVED_NAMES, subtract_runtime_condition, to_identifier_with_escaped,
+  to_normal_comment,
 };
 
 type ExportsDefinitionArgs = Vec<(String, String)>;
@@ -799,7 +799,7 @@
       for dep_id in module.get_dependencies().iter() {
         let dep = module_graph.dependency_by_id(dep_id);
         let module_id_of_dep = module_graph.module_identifier_by_dependency_id(dep_id);
-        if !is_esm_dep_like(dep) || !modules.contains(&module_id_of_dep) {
+        if !is_esm_dep_like(dep.as_ref()) || !modules.contains(&module_id_of_dep) {
           self.dependencies.push(*dep_id);
         }
       }
@@ -2221,7 +2221,7 @@
       .into_iter()
       .filter_map(|connection| {
         let dep = mg.dependency_by_id(&connection.dependency_id);
-        if !is_esm_dep_like(dep) {
+        if !is_esm_dep_like(dep.as_ref()) {
           return None;
         }
         let ref_module = mg
@@ -3117,7 +3117,7 @@
   }
 }
 
-pub fn is_esm_dep_like(dep: &BoxDependency) -> bool {
+pub fn is_esm_dep_like(dep: &dyn Dependency) -> bool {
   matches!(
     dep.dependency_type(),
     DependencyType::EsmImportSpecifier

diff --git a/crates/rspack_core/src/context_module_factory.rs b/crates/rspack_core/src/context_module_factory.rs
--- a/crates/rspack_core/src/context_module_factory.rs
+++ b/crates/rspack_core/src/context_module_factory.rs
@@ -13,7 +13,7 @@
 use tracing::instrument;
 
 use crate::{
-  BoxDependency, CompilationId, ContextElementDependency, ContextModule, ContextModuleOptions,
+  ArcDependency, CompilationId, ContextElementDependency, ContextModule, ContextModuleOptions,
   DependencyCategory, DependencyId, DependencyType, ModuleExt, ModuleFactory,
   ModuleFactoryCreateData, ModuleFactoryResult, ResolveArgs, ResolveContextModuleDependencies,
   ResolveInnerOptions, ResolveOptionsWithDependencyType, ResolveResult, Resolver, ResolverFactory,
@@ -33,7 +33,7 @@
   pub context: String,
   pub request: String,
   // assertions
-  pub dependencies: Vec<BoxDependency>,
+  pub dependencies: Vec<ArcDependency>,
   // dependency_type
   // file_dependencies
   // missing_dependencies
@@ -55,7 +55,7 @@
   pub compilation_id: CompilationId,
   pub resource: Utf8PathBuf,
   pub context: String,
-  pub dependencies: Vec<BoxDependency>,
+  pub dependencies: Vec<ArcDependency>,
   // layer
   // resolve_options
   // file_dependencies: HashSet<String>,
@@ -171,7 +171,7 @@
     data: &mut ModuleFactoryCreateData,
   ) -> Result<BeforeResolveResult> {
     let dependency = data.dependencies[0]
-      .as_context_dependency_mut()
+      .as_context_dependency()
       .expect("should be context dependency");
     let dependency_options = dependency.options();
 

diff --git a/crates/rspack_core/src/dependency/context_dependency.rs b/crates/rspack_core/src/dependency/context_dependency.rs
--- a/crates/rspack_core/src/dependency/context_dependency.rs
+++ b/crates/rspack_core/src/dependency/context_dependency.rs
@@ -16,8 +16,17 @@
   fn type_prefix(&self) -> ContextTypePrefix;
 
   fn critical(&self) -> &Option<Diagnostic>;
+  #[doc(hidden)]
   fn critical_mut(&mut self) -> &mut Option<Diagnostic>;
 
+  fn set_critical(&self, diagnostic: Option<Diagnostic>) {
+    // SAFETY: callers must ensure there is no aliasing mutable access.
+    let this = self as *const Self as *mut Self;
+    unsafe {
+      *(*this).critical_mut() = diagnostic;
+    }
+  }
+
   fn factorize_info(&self) -> &FactorizeInfo;
   fn factorize_info_mut(&mut self) -> &mut FactorizeInfo;
 }
@@ -41,3 +50,7 @@
     Some(self)
   }
 }
+
+pub fn clear_context_dependency_critical(dep: &dyn Dependency) -> Option<()> {
+  dep.as_context_dependency().map(|d| d.set_critical(None))
+}

diff --git a/crates/rspack_core/src/dependency/dependency_trait.rs b/crates/rspack_core/src/dependency/dependency_trait.rs
--- a/crates/rspack_core/src/dependency/dependency_trait.rs
+++ b/crates/rspack_core/src/dependency/dependency_trait.rs
@@ -1,4 +1,4 @@
-use std::{any::Any, fmt::Debug};
+use std::{any::Any, fmt::Debug, sync::Arc};
 
 use dyn_clone::{DynClone, clone_trait_object};
 use rspack_cacheable::cacheable_dyn;
@@ -127,7 +127,8 @@
     None
   }
 
-  fn unset_lazy(&mut self) -> bool {
+  #[doc(hidden)]
+  fn unset_lazy(&self) -> bool {
     false
   }
 }
@@ -149,3 +150,4 @@
 clone_trait_object!(Dependency);
 
 pub type BoxDependency = Box<dyn Dependency>;
+pub type ArcDependency = Arc<dyn Dependency>;

diff --git a/crates/rspack_core/src/dependency/factorize_info.rs b/crates/rspack_core/src/dependency/factorize_info.rs
--- a/crates/rspack_core/src/dependency/factorize_info.rs
+++ b/crates/rspack_core/src/dependency/factorize_info.rs
@@ -2,7 +2,7 @@
 use rspack_error::Diagnostic;
 use rspack_paths::ArcPathSet;
 
-use super::{BoxDependency, DependencyId};
+use super::{Dependency, DependencyId};
 
 #[cacheable]
 #[derive(Debug, Clone, Default)]
@@ -31,7 +31,7 @@
     }
   }
 
-  pub fn get_from(dep: &BoxDependency) -> Option<&FactorizeInfo> {
+  pub fn get_from(dep: &dyn Dependency) -> Option<&FactorizeInfo> {
     if let Some(d) = dep.as_context_dependency() {
       Some(d.factorize_info())
     } else if let Some(d) = dep.as_module_dependency() {
@@ -41,7 +41,7 @@
     }
   }
 
-  pub fn revoke(dep: &mut BoxDependency) -> Option<FactorizeInfo> {
+  pub(crate) fn revoke(dep: &mut dyn Dependency) -> Option<FactorizeInfo> {
     if let Some(d) = dep.as_context_dependency_mut() {
       Some(std::mem::take(d.factorize_info_mut()))
     } else if let Some(d) = dep.as_module_dependency_mut() {
@@ -51,6 +51,18 @@
     }
   }
 
+  pub(crate) fn set(dep: &mut dyn Dependency, info: FactorizeInfo) -> Option<()> {
+    if let Some(d) = dep.as_context_dependency_mut() {
+      *d.factorize_info_mut() = info;
+      Some(())
+    } else if let Some(d) = dep.as_module_dependency_mut() {
+      *d.factorize_info_mut() = info;
+      Some(())
+    } else {
+      None
+    }
+  }
+
   pub fn is_success(&self) -> bool {
     self.diagnostics.is_empty()
   }

diff --git a/crates/rspack_core/src/dependency/mod.rs b/crates/rspack_core/src/dependency/mod.rs
--- a/crates/rspack_core/src/dependency/mod.rs
+++ b/crates/rspack_core/src/dependency/mod.rs
@@ -19,7 +19,9 @@
 
 pub use cached_const_dependency::{CachedConstDependency, CachedConstDependencyTemplate};
 pub use const_dependency::{ConstDependency, ConstDependencyTemplate};
-pub use context_dependency::{AsContextDependency, ContextDependency};
+pub use context_dependency::{
+  AsContextDependency, ContextDependency, clear_context_dependency_critical,
+};
 pub use context_element_dependency::ContextElementDependency;
 pub use dependency_category::DependencyCategory;
 pub use dependency_id::*;

diff --git a/crates/rspack_core/src/incremental/mutations.rs b/crates/rspack_core/src/incremental/mutations.rs
--- a/crates/rspack_core/src/incremental/mutations.rs
+++ b/crates/rspack_core/src/incremental/mutations.rs
@@ -6,7 +6,7 @@
 use rspack_collections::{IdentifierSet, UkeySet};
 
 use crate::{
-  AffectType, BoxDependency, ChunkUkey, Compilation, DependencyId, ModuleGraph, ModuleIdentifier,
+  AffectType, ChunkUkey, Compilation, Dependency, DependencyId, ModuleGraph, ModuleIdentifier,
 };
 
 #[derive(Debug, Default)]
@@ -254,7 +254,7 @@
   built_modules: IdentifierSet,
   built_dependencies: UkeySet<DependencyId>,
 ) -> IdentifierSet {
-  fn reduce_affect_type<'a>(dependencies: impl Iterator<Item = &'a BoxDependency>) -> AffectType {
+  fn reduce_affect_type<'a>(dependencies: impl Iterator<Item = &'a dyn Dependency>) -> AffectType {
     let mut affected = AffectType::False;
     for dependency in dependencies {
       match dependency.could_affect_referencing_module() {
@@ -285,7 +285,7 @@
             match reduce_affect_type(
               connections
                 .iter()
-                .map(|c| module_graph.dependency_by_id(&c.dependency_id)),
+                .map(|c| module_graph.dependency_by_id(&c.dependency_id).as_ref()),
             ) {
               AffectType::False => None,
               AffectType::True => Some(AffectedModuleKind::Direct(referencing_module)),

diff --git a/crates/rspack_core/src/module_factory.rs b/crates/rspack_core/src/module_factory.rs
--- a/crates/rspack_core/src/module_factory.rs
+++ b/crates/rspack_core/src/module_factory.rs
@@ -1,11 +1,12 @@
 use std::{fmt::Debug, sync::Arc};
 
+use dyn_clone::clone_box;
 use rspack_error::{Diagnostic, Result};
 use rspack_paths::{ArcPath, ArcPathSet};
 
 use crate::{
-  BoxDependency, BoxModule, CompilationId, CompilerId, CompilerOptions, Context, ModuleIdentifier,
-  ModuleLayer, Resolve, ResolverFactory,
+  ArcDependency, BoxModule, CompilationId, CompilerId, CompilerOptions, Context, Dependency,
+  ModuleIdentifier, ModuleLayer, Resolve, ResolverFactory,
 };
 
 #[derive(Debug, Clone)]
@@ -16,7 +17,7 @@
   pub options: Arc<CompilerOptions>,
   pub request: String,
   pub context: Context,
-  pub dependencies: Vec<BoxDependency>,
+  pub dependencies: Vec<ArcDependency>,
   pub issuer: Option<Box<str>>,
   pub issuer_identifier: Option<ModuleIdentifier>,
   pub issuer_layer: Option<ModuleLayer>,
@@ -29,6 +30,24 @@
 }
 
 impl ModuleFactoryCreateData {
+  pub fn dependency(&self, index: usize) -> &ArcDependency {
+    self
+      .dependencies
+      .get(index)
+      .unwrap_or_else(|| panic!("Dependency at index {index} not found"))
+  }
+
+  pub fn dependency_mut(&mut self, index: usize) -> &mut dyn Dependency {
+    let dep = self
+      .dependencies
+      .get_mut(index)
+      .unwrap_or_else(|| panic!("Dependency at index {index} not found"));
+    if Arc::strong_count(dep) != 1 {
+      *dep = Arc::from(clone_box(dep.as_ref()));
+    }
+    Arc::get_mut(dep).unwrap_or_else(|| panic!("Dependency at index {index} not found"))
+  }
+
   pub fn add_file_dependency<F: Into<ArcPath>>(&mut self, file: F) {
     self.file_dependencies.insert(file.into());
   }

diff --git a/crates/rspack_core/src/module_graph/internal.rs b/crates/rspack_core/src/module_graph/internal.rs
--- a/crates/rspack_core/src/module_graph/internal.rs
+++ b/crates/rspack_core/src/module_graph/internal.rs
@@ -4,7 +4,7 @@
 ///
 /// This module provides restricted access to potentially unsafe ModuleGraph operations
 /// that should only be used in specific contexts where items may legitimately not exist.
-use crate::{BoxDependency, DependencyId, ModuleGraph, ModuleGraphModule, ModuleIdentifier};
+use crate::{ArcDependency, DependencyId, ModuleGraph, ModuleGraphModule, ModuleIdentifier};
 
 /// Try to get a dependency by ID, returning None if not found.
 ///
@@ -30,7 +30,7 @@
 pub fn try_dependency_by_id<'a>(
   module_graph: &'a ModuleGraph,
   dependency_id: &DependencyId,
-) -> Option<&'a BoxDependency> {
+) -> Option<&'a ArcDependency> {
   module_graph.inner.dependencies.get(dependency_id)
 }
 

diff --git a/crates/rspack_core/src/module_graph/mod.rs b/crates/rspack_core/src/module_graph/mod.rs
--- a/crates/rspack_core/src/module_graph/mod.rs
+++ b/crates/rspack_core/src/module_graph/mod.rs
@@ -1,6 +1,9 @@
 pub mod internal;
 pub mod rollback;
 
+use std::sync::Arc;
+
+use dyn_clone::clone_box;
 use internal::try_get_module_graph_module_mut_by_identifier;
 use rayon::prelude::*;
 use rspack_error::Result;
@@ -9,19 +12,16 @@
 use swc_core::ecma::atoms::Atom;
 
 use crate::{
-  AsyncDependenciesBlock, AsyncDependenciesBlockIdentifier, AsyncModulesArtifact, Compilation,
-  DependenciesBlock, Dependency, ExportInfo, ExportName, ImportedByDeferModulesArtifact,
-  ModuleGraphCacheArtifact, RuntimeSpec, UsedNameItem,
+  ArcDependency, AsyncDependenciesBlock, AsyncDependenciesBlockIdentifier, AsyncModulesArtifact,
+  Compilation, DependenciesBlock, Dependency, ExportInfo, ExportName,
+  ImportedByDeferModulesArtifact, ModuleGraphCacheArtifact, RuntimeSpec, UsedNameItem,
 };
 mod module;
 pub use module::*;
 mod connection;
 pub use connection::*;
 
-use crate::{
-  BoxDependency, BoxModule, DependencyCondition, DependencyId, ExportsInfoArtifact,
-  ModuleIdentifier,
-};
+use crate::{BoxModule, DependencyCondition, DependencyId, ExportsInfoArtifact, ModuleIdentifier};
 
 // TODO Here request can be used Atom
 pub type ImportVarMap = HashMap<(Option<ModuleIdentifier>, bool), String /* import_var */>;
@@ -59,7 +59,7 @@
   pub(crate) modules: rollback::RollbackMap<ModuleIdentifier, BoxModule>,
 
   /// Dependencies indexed by `DependencyId`.
-  dependencies: HashMap<DependencyId, BoxDependency>,
+  dependencies: HashMap<DependencyId, ArcDependency>,
   /// AsyncDependenciesBlocks indexed by `AsyncDependenciesBlockIdentifier`.
   blocks: HashMap<AsyncDependenciesBlockIdentifier, Box<AsyncDependenciesBlock>>,
 
@@ -366,7 +366,7 @@
     &mut self,
     old_module: &ModuleIdentifier,
     new_module: &ModuleIdentifier,
-    filter_connection: impl Fn(&ModuleGraphConnection, &Box<dyn Dependency>) -> bool,
+    filter_connection: impl Fn(&ModuleGraphConnection, &dyn Dependency) -> bool,
   ) {
     if old_module == new_module {
       return;
@@ -384,7 +384,7 @@
         .connection_by_dependency_id(&dep_id)
... diff truncated: showing 800 of 1110 lines

Open in Web Open in Cursor 

@hardfist hardfist marked this pull request as draft February 28, 2026 09:36
@github-actions
Copy link
Contributor

github-actions bot commented Feb 28, 2026

📝 Benchmark detail: Open

Name Base (2026-02-28 10ed485) Current Change
10000_big_production-mode_disable-minimize + exec 13.9 s ± 327 ms 14 s ± 163 ms +0.16 %
10000_development-mode + exec 1.05 s ± 8 ms 1.04 s ± 21 ms -0.48 %
10000_development-mode_hmr + stats 197 ms ± 5.3 ms 199 ms ± 5.5 ms +0.91 %
10000_development-mode_noop-loader + exec 2.13 s ± 64 ms 2.09 s ± 65 ms -1.56 %
10000_production-mode + exec 1.15 s ± 40 ms 1.14 s ± 23 ms -0.47 %
10000_production-mode_persistent-cold + exec 1.34 s ± 50 ms 1.3 s ± 40 ms -2.63 %
10000_production-mode_persistent-hot + exec 971 ms ± 31 ms 913 ms ± 34 ms -5.93 %
10000_production-mode_source-map + exec 1.32 s ± 18 ms 1.32 s ± 43 ms +0.23 %
arco-pro_development-mode + exec 1.32 s ± 86 ms 1.34 s ± 82 ms +0.98 %
arco-pro_development-mode_hmr + stats 39 ms ± 1.2 ms 42 ms ± 0.39 ms +5.90 %
arco-pro_production-mode + exec 2.37 s ± 110 ms 2.4 s ± 88 ms +1.34 %
arco-pro_production-mode_generate-package-json-webpack-plugin + exec 2.41 s ± 90 ms 2.46 s ± 75 ms +2.07 %
arco-pro_production-mode_persistent-cold + exec 2.47 s ± 69 ms 2.5 s ± 48 ms +1.21 %
arco-pro_production-mode_persistent-hot + exec 1.4 s ± 37 ms 1.42 s ± 41 ms +1.29 %
arco-pro_production-mode_source-map + exec 2.89 s ± 72 ms 2.92 s ± 86 ms +1.19 %
arco-pro_production-mode_traverse-chunk-modules + exec 2.42 s ± 133 ms 2.46 s ± 39 ms +1.70 %
bundled-threejs_development-mode + exec 194 ms ± 7 ms 192 ms ± 2.9 ms -0.93 %
bundled-threejs_production-mode + exec 227 ms ± 3.3 ms 229 ms ± 2.2 ms +0.97 %
large-dyn-imports_development-mode + exec 1.31 s ± 49 ms 1.3 s ± 28 ms -0.96 %
large-dyn-imports_production-mode + exec 1.4 s ± 21 ms 1.42 s ± 34 ms +1.23 %
threejs_development-mode_10x + exec 862 ms ± 9.6 ms 855 ms ± 18 ms -0.86 %
threejs_development-mode_10x_hmr + stats 136 ms ± 1.5 ms 138 ms ± 3.9 ms +1.29 %
threejs_production-mode_10x + exec 2.96 s ± 29 ms 2.97 s ± 17 ms +0.18 %
threejs_production-mode_10x_persistent-cold + exec 3.09 s ± 26 ms 3.11 s ± 48 ms +0.89 %
threejs_production-mode_10x_persistent-hot + exec 2.48 s ± 32 ms 2.49 s ± 32 ms +0.27 %
threejs_production-mode_10x_source-map + exec 3.7 s ± 45 ms 3.73 s ± 34 ms +0.69 %
10000_big_production-mode_disable-minimize + rss memory 2242 MiB ± 163 MiB 2182 MiB ± 60.2 MiB -2.67 %
10000_development-mode + rss memory 672 MiB ± 31.5 MiB 672 MiB ± 31.8 MiB +0.01 %
10000_development-mode_hmr + rss memory 854 MiB ± 22.6 MiB 850 MiB ± 16.4 MiB -0.46 %
10000_development-mode_noop-loader + rss memory 982 MiB ± 35.5 MiB 974 MiB ± 14.5 MiB -0.86 %
10000_production-mode + rss memory 558 MiB ± 16.2 MiB 556 MiB ± 21.4 MiB -0.50 %
10000_production-mode_persistent-cold + rss memory 780 MiB ± 36.8 MiB 717 MiB ± 19.5 MiB -8.17 %
10000_production-mode_persistent-hot + rss memory 767 MiB ± 19.7 MiB 656 MiB ± 17.1 MiB -14.54 %
10000_production-mode_source-map + rss memory 620 MiB ± 22.6 MiB 625 MiB ± 16.3 MiB +0.83 %
arco-pro_development-mode + rss memory 544 MiB ± 33.1 MiB 529 MiB ± 27.7 MiB -2.87 %
arco-pro_development-mode_hmr + rss memory 484 MiB ± 15.5 MiB 488 MiB ± 14.6 MiB +0.89 %
arco-pro_production-mode + rss memory 609 MiB ± 36 MiB 590 MiB ± 32.5 MiB -3.20 %
arco-pro_production-mode_generate-package-json-webpack-plugin + rss memory 629 MiB ± 48.1 MiB 622 MiB ± 23.6 MiB -1.00 %
arco-pro_production-mode_persistent-cold + rss memory 681 MiB ± 40.8 MiB 657 MiB ± 26.1 MiB -3.50 %
arco-pro_production-mode_persistent-hot + rss memory 433 MiB ± 60.6 MiB 421 MiB ± 80.5 MiB -2.71 %
arco-pro_production-mode_source-map + rss memory 697 MiB ± 50.4 MiB 704 MiB ± 40.8 MiB +1.06 %
arco-pro_production-mode_traverse-chunk-modules + rss memory 604 MiB ± 63.6 MiB 600 MiB ± 56.5 MiB -0.65 %
bundled-threejs_development-mode + rss memory 173 MiB ± 4.89 MiB 171 MiB ± 4.03 MiB -0.82 %
bundled-threejs_production-mode + rss memory 199 MiB ± 10.4 MiB 193 MiB ± 20.9 MiB -3.10 %
large-dyn-imports_development-mode + rss memory 694 MiB ± 15.5 MiB 696 MiB ± 19.9 MiB +0.34 %
large-dyn-imports_production-mode + rss memory 495 MiB ± 6.7 MiB 502 MiB ± 13.7 MiB +1.32 %
threejs_development-mode_10x + rss memory 535 MiB ± 25.4 MiB 525 MiB ± 12.8 MiB -1.95 %
threejs_development-mode_10x_hmr + rss memory 652 MiB ± 22 MiB 648 MiB ± 29.1 MiB -0.60 %
threejs_production-mode_10x + rss memory 651 MiB ± 18.2 MiB 643 MiB ± 11.1 MiB -1.18 %
threejs_production-mode_10x_persistent-cold + rss memory 794 MiB ± 7.68 MiB 767 MiB ± 13.9 MiB -3.37 %
threejs_production-mode_10x_persistent-hot + rss memory 642 MiB ± 15.9 MiB 619 MiB ± 10.5 MiB -3.67 %
threejs_production-mode_10x_source-map + rss memory 724 MiB ± 61.9 MiB 706 MiB ± 139 MiB -2.47 %

@github-actions
Copy link
Contributor

github-actions bot commented Feb 28, 2026

📝 Benchmark detail: Open

Name Base (2026-02-28 10ed485) Current Change
10000_big_production-mode_disable-minimize + exec 13.9 s ± 327 ms 13.9 s ± 149 ms -0.30 %
10000_development-mode + exec 1.05 s ± 8 ms 1.05 s ± 16 ms +0.65 %
10000_development-mode_hmr + stats 197 ms ± 5.3 ms 199 ms ± 7 ms +1.26 %
10000_development-mode_noop-loader + exec 2.13 s ± 64 ms 2.11 s ± 135 ms -0.81 %
10000_production-mode + exec 1.15 s ± 40 ms 1.13 s ± 30 ms -1.29 %
10000_production-mode_persistent-cold + exec 1.34 s ± 50 ms 1.29 s ± 18 ms -3.96 %
10000_production-mode_persistent-hot + exec 971 ms ± 31 ms 904 ms ± 4 ms -6.92 %
10000_production-mode_source-map + exec 1.32 s ± 18 ms 1.33 s ± 47 ms +0.64 %
arco-pro_development-mode + exec 1.32 s ± 86 ms 1.35 s ± 57 ms +2.01 %
arco-pro_development-mode_hmr + stats 39 ms ± 1.2 ms 42 ms ± 0.95 ms +6.91 %
arco-pro_production-mode + exec 2.37 s ± 110 ms 2.39 s ± 45 ms +0.92 %
arco-pro_production-mode_generate-package-json-webpack-plugin + exec 2.41 s ± 90 ms 2.41 s ± 87 ms -0.08 %
arco-pro_production-mode_persistent-cold + exec 2.47 s ± 69 ms 2.46 s ± 63 ms -0.21 %
arco-pro_production-mode_persistent-hot + exec 1.4 s ± 37 ms 1.39 s ± 36 ms -0.69 %
arco-pro_production-mode_source-map + exec 2.89 s ± 72 ms 2.91 s ± 126 ms +0.62 %
arco-pro_production-mode_traverse-chunk-modules + exec 2.42 s ± 133 ms 2.4 s ± 89 ms -0.76 %
bundled-threejs_development-mode + exec 194 ms ± 7 ms 194 ms ± 5.3 ms +0.31 %
bundled-threejs_production-mode + exec 227 ms ± 3.3 ms 229 ms ± 5.1 ms +1.06 %
large-dyn-imports_development-mode + exec 1.31 s ± 49 ms 1.3 s ± 43 ms -0.70 %
large-dyn-imports_production-mode + exec 1.4 s ± 21 ms 1.41 s ± 45 ms +0.50 %
threejs_development-mode_10x + exec 862 ms ± 9.6 ms 856 ms ± 43 ms -0.77 %
threejs_development-mode_10x_hmr + stats 136 ms ± 1.5 ms 136 ms ± 2.1 ms -0.19 %
threejs_production-mode_10x + exec 2.96 s ± 29 ms 2.96 s ± 41 ms -0.30 %
threejs_production-mode_10x_persistent-cold + exec 3.09 s ± 26 ms 3.07 s ± 26 ms -0.51 %
threejs_production-mode_10x_persistent-hot + exec 2.48 s ± 32 ms 2.48 s ± 8.1 ms -0.11 %
threejs_production-mode_10x_source-map + exec 3.7 s ± 45 ms 3.71 s ± 99 ms +0.13 %
10000_big_production-mode_disable-minimize + rss memory 2242 MiB ± 163 MiB 2185 MiB ± 61.3 MiB -2.54 %
10000_development-mode + rss memory 672 MiB ± 31.5 MiB 674 MiB ± 25.8 MiB +0.31 %
10000_development-mode_hmr + rss memory 854 MiB ± 22.6 MiB 846 MiB ± 21.5 MiB -0.91 %
10000_development-mode_noop-loader + rss memory 982 MiB ± 35.5 MiB 976 MiB ± 25.7 MiB -0.67 %
10000_production-mode + rss memory 558 MiB ± 16.2 MiB 550 MiB ± 6.49 MiB -1.55 %
10000_production-mode_persistent-cold + rss memory 780 MiB ± 36.8 MiB 710 MiB ± 5.02 MiB -9.04 %
10000_production-mode_persistent-hot + rss memory 767 MiB ± 19.7 MiB 657 MiB ± 26.9 MiB -14.37 %
10000_production-mode_source-map + rss memory 620 MiB ± 22.6 MiB 627 MiB ± 35.7 MiB +1.17 %
arco-pro_development-mode + rss memory 544 MiB ± 33.1 MiB 529 MiB ± 45.2 MiB -2.82 %
arco-pro_development-mode_hmr + rss memory 484 MiB ± 15.5 MiB 485 MiB ± 8.31 MiB +0.30 %
arco-pro_production-mode + rss memory 609 MiB ± 36 MiB 614 MiB ± 60.3 MiB +0.80 %
arco-pro_production-mode_generate-package-json-webpack-plugin + rss memory 629 MiB ± 48.1 MiB 607 MiB ± 39.4 MiB -3.43 %
arco-pro_production-mode_persistent-cold + rss memory 681 MiB ± 40.8 MiB 662 MiB ± 58.7 MiB -2.73 %
arco-pro_production-mode_persistent-hot + rss memory 433 MiB ± 60.6 MiB 420 MiB ± 60.5 MiB -3.10 %
arco-pro_production-mode_source-map + rss memory 697 MiB ± 50.4 MiB 718 MiB ± 83.6 MiB +3.00 %
arco-pro_production-mode_traverse-chunk-modules + rss memory 604 MiB ± 63.6 MiB 607 MiB ± 29.6 MiB +0.48 %
bundled-threejs_development-mode + rss memory 173 MiB ± 4.89 MiB 172 MiB ± 6.63 MiB -0.31 %
bundled-threejs_production-mode + rss memory 199 MiB ± 10.4 MiB 199 MiB ± 11 MiB -0.17 %
large-dyn-imports_development-mode + rss memory 694 MiB ± 15.5 MiB 693 MiB ± 10.2 MiB -0.11 %
large-dyn-imports_production-mode + rss memory 495 MiB ± 6.7 MiB 501 MiB ± 11.3 MiB +1.20 %
threejs_development-mode_10x + rss memory 535 MiB ± 25.4 MiB 525 MiB ± 31.2 MiB -1.82 %
threejs_development-mode_10x_hmr + rss memory 652 MiB ± 22 MiB 652 MiB ± 27.8 MiB +0.01 %
threejs_production-mode_10x + rss memory 651 MiB ± 18.2 MiB 644 MiB ± 10.6 MiB -1.08 %
threejs_production-mode_10x_persistent-cold + rss memory 794 MiB ± 7.68 MiB 767 MiB ± 4.83 MiB -3.38 %
threejs_production-mode_10x_persistent-hot + rss memory 642 MiB ± 15.9 MiB 615 MiB ± 22.9 MiB -4.27 %
threejs_production-mode_10x_source-map + rss memory 724 MiB ± 61.9 MiB 693 MiB ± 118 MiB -4.33 %

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release: refactor team The issue/pr is created by the member of Rspack.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant