Summary
In a production build only (dev + tests are fine), a route chunk that renders a CommonJS dependency throws TypeError: n is not a function at runtime. The error looks like a minified variable collision, but the real cause is a circular chunk import where a CJS module's binding is read before the chunk that defines it has executed.
This is the same failure class as #8803 — but that issue states automatic splitting "produces chunks that don't form cycles." Here it does form a cycle under plain Vite automatic/route-based splitting, with no codeSplitting.groups configured. So this case appears unreported.
Environment
vite@8.0.14 (bundler: rolldown@1.0.3)
recharts@3.8.1 → es-toolkit@1.47.0
- No
output.codeSplitting.groups — default Vite automatic splitting.
Evidence
A sourcemapped build maps the throw to es-toolkit/dist/compat/math/maxBy.js:2, a top-level const require_identity = require("../../function/identity.js").
The emitted (minified) code:
un = W((e => {
var t = ln(), n = n(), r = r(); // <-- n=n() and r=r() are self-referential
function i(e, i){ /* ... */ r.iteratee(i ?? n.identity) }
e.maxBy = i
}))
t = ln() is fine (the module-init function and its result binding got distinct names), but n = n() / r = r() read a binding that is still uninitialized at that point — the cross-chunk factory and the binding it initializes collapsed to the same name. With minify: false it surfaces as a deconfliction failure instead, per #8803.
Chain: Recharts does import maxBy from 'es-toolkit/compat/maxBy'. es-toolkit's ./compat/* export is CJS-only (module.exports = require('../dist/compat/math/maxBy.js').maxBy), so rolldown bundles + wraps the nested-require chain and splits the helper modules (identity, iteratee) into a different chunk than the consumer — forming the cycle.
Workarounds (both confirm the cause)
Question
Should automatic (non-grouped) splitting avoid forming these CJS cycles so neither workaround is needed — or, if strictExecutionOrder is the intended answer, should the docs note it's required for automatic splitting with CJS deps too (not only codeSplitting.groups, as #8803 implies)?
I can put together a minimal Vite 8 + Recharts reproduction if that would help.
Summary
In a production build only (dev + tests are fine), a route chunk that renders a CommonJS dependency throws
TypeError: n is not a functionat runtime. The error looks like a minified variable collision, but the real cause is a circular chunk import where a CJS module's binding is read before the chunk that defines it has executed.This is the same failure class as #8803 — but that issue states automatic splitting "produces chunks that don't form cycles." Here it does form a cycle under plain Vite automatic/route-based splitting, with no
codeSplitting.groupsconfigured. So this case appears unreported.Environment
vite@8.0.14(bundler:rolldown@1.0.3)recharts@3.8.1→es-toolkit@1.47.0output.codeSplitting.groups— default Vite automatic splitting.Evidence
A sourcemapped build maps the throw to
es-toolkit/dist/compat/math/maxBy.js:2, a top-levelconst require_identity = require("../../function/identity.js").The emitted (minified) code:
t = ln()is fine (the module-init function and its result binding got distinct names), butn = n()/r = r()read a binding that is still uninitialized at that point — the cross-chunk factory and the binding it initializes collapsed to the same name. Withminify: falseit surfaces as a deconfliction failure instead, per #8803.Chain: Recharts does
import maxBy from 'es-toolkit/compat/maxBy'. es-toolkit's./compat/*export is CJS-only (module.exports = require('../dist/compat/math/maxBy.js').maxBy), so rolldown bundles + wraps the nested-requirechain and splits the helper modules (identity,iteratee) into a different chunk than the consumer — forming the cycle.Workarounds (both confirm the cause)
output.strictExecutionOrder: true— fixes it (matches Docs: codeSplitting.groups should recommend strictExecutionOrder for CJS-heavy projects #8803's mitigation), at ~2x bundle-size cost.manualChunksgroup co-locating the consumer + its CJS dep in one chunk — fixes it (removes the split that forms the cycle). This is what we shipped.Question
Should automatic (non-grouped) splitting avoid forming these CJS cycles so neither workaround is needed — or, if
strictExecutionOrderis the intended answer, should the docs note it's required for automatic splitting with CJS deps too (not onlycodeSplitting.groups, as #8803 implies)?I can put together a minimal Vite 8 + Recharts reproduction if that would help.