Description
Since #8371, the would_create_circular_dependency function in the chunk optimizer blocks significantly more chunk merges than necessary, causing a large increase in output chunk count and bundle size.
Reproduction
The regression can be reproduced with any application that has:
- Multiple entry points (static or dynamic imports)
- Common modules shared between entries that have their own dependencies
Minimal reproduction
// main.js
import './cjs.js';
import './b.js';
// b.js
import('./cjs.js');
import('./b.js');
// cjs.js
module.exports = 42;
With the current algorithm, common chunks with dependencies are blocked from merging into entry chunks due to false positive cycle detection. The existing test case tests/rolldown/issues/8361 demonstrates the real cycle that #8371 was designed to fix.
Quantified impact
On a large application with ~2,200 entry points:
| Metric |
Before #8371 (rc.4) |
After #8371 (rc.5+) |
Regression |
| JS files |
~2,000 |
~3,200 |
+60% |
| JS size |
~58 MB |
~63 MB |
+8% |
Root Cause
The would_create_circular_dependency function does a BFS from source.deps ∪ target.deps with post-merge edge simulation. This causes false positives because:
- Starting BFS from
target.deps means target can trivially "reach itself" through any transitive dependency that also depends on source
- The post-merge edge simulation amplifies this by redirecting any source-dependent chunk back to target
When source has dependencies, the target.deps BFS + simulation is unnecessary — a simple BFS from source.deps is sufficient to detect real cycles.
Fix
PR #9049 splits the algorithm:
Results with fix applied:
| Metric |
Before fix |
After fix |
Improvement |
| JS files |
3,212 |
2,418 |
-25% |
| JS size |
73.13 MB |
63.99 MB |
-12.5% |
All 1,652 integration tests pass, including #8361.
Related
Description
Since #8371, the
would_create_circular_dependencyfunction in the chunk optimizer blocks significantly more chunk merges than necessary, causing a large increase in output chunk count and bundle size.Reproduction
The regression can be reproduced with any application that has:
Minimal reproduction
With the current algorithm, common chunks with dependencies are blocked from merging into entry chunks due to false positive cycle detection. The existing test case
tests/rolldown/issues/8361demonstrates the real cycle that #8371 was designed to fix.Quantified impact
On a large application with ~2,200 entry points:
Root Cause
The
would_create_circular_dependencyfunction does a BFS fromsource.deps ∪ target.depswith post-merge edge simulation. This causes false positives because:target.depsmeans target can trivially "reach itself" through any transitive dependency that also depends on sourceWhen source has dependencies, the
target.depsBFS + simulation is unnecessary — a simple BFS fromsource.depsis sufficient to detect real cycles.Fix
PR #9049 splits the algorithm:
source.deps(no simulation)target.depsBFS + simulation (needed for [Bug]: __commonJSMin is not a function since rc4 #8361)Results with fix applied:
All 1,652 integration tests pass, including #8361.
Related