Barrel files (index.ts/index.js aggregating module exports) introduce structural ambiguity that directly conflicts with Webpack’s dependency graph construction. When Tree-Shaking & Bundle Optimization is applied to libraries or applications relying on wildcard aggregations, the parser encounters static analysis limitations that prevent accurate dead-code elimination. This guide isolates the exact failure modes and provides deterministic configuration overrides to restore pruning.

Static Analysis Bottleneck in Webpack’s Parser

Webpack’s dependency graph builder relies on static AST traversal to map consumed exports. The export * from './module' syntax generates implicit namespace objects that bypass static export tracking. Because Webpack’s Acorn parser cannot statically determine which specific re-exports are consumed downstream, it defaults to a conservative resolution strategy. The compiler falls back to dynamic require resolution, retaining all referenced modules in the final bundle regardless of actual usage. Diagnostic Flag: optimization.providedExports: false (implicit fallback)

sideEffects Flag Misconfiguration & False Positives

Declaring "sideEffects": false in package.json assumes modules contain no global state mutations or side-effect execution. Barrel files violate this assumption because re-export evaluation order requires Webpack to execute the intermediate index file. Consequently, Webpack assumes barrel files have side effects due to re-export evaluation order. The package.json sideEffects array must explicitly exclude index files or use granular glob patterns (e.g., ["./src/**/*.css", "!./src/index.ts"]). When misconfigured, ModuleConcatenationPlugin skips barrel-wrapped modules, preventing scope hoisting and fragmenting module execution. Diagnostic Flag: ModuleConcatenationPlugin bailout: Module has side effects

Namespace Object Inflation & Dead Code Retention

Aggregation files force Webpack to generate namespace getters for all exports to maintain CommonJS/ESM interoperability. Unused exports remain in the chunk due to getter invocation overhead and circular reference guards injected during compilation. Tree-shaking stops at the barrel boundary, preventing deep pruning into the underlying implementation files. This results in significant bundle bloat from generated wrappers that are never garbage-collected. Diagnostic Flag: __webpack_require__.r() and __webpack_require__.d() overhead

Targeted Resolution: Explicit Re-exports & Config Overrides

Restoring deterministic pruning requires eliminating implicit aggregation boundaries. Replace export * with explicit named exports to restore static analysis and allow the parser to trace exact consumption paths. Use resolve.alias to bypass barrel entry points and point directly to source modules during bundling. Enable optimization.sideEffects: true with granular package.json rules for library distribution to guarantee safe elimination. When transitioning from wildcard re-exports to explicit module boundaries for library distribution, consult Eliminating Barrel File Anti-Patterns for architectural migration patterns. Configuration Override: resolve.alias: { '@lib/components': '@lib/components/src' }

Step-by-Step Fix

  1. Audit and replace wildcard re-exports in barrel files
grep -r "export \*" src/ && sed -i 's/export \* from/export { NamedExport } from/g' src/index.ts
  1. Enforce strict side-effect declarations in package.json
"sideEffects": false
  1. Configure Webpack optimization flags to force static analysis
optimization: {
  providedExports: true,
  sideEffects: true,
  concatenateModules: true,
  usedExports: true,
}
  1. Bypass legacy barrel entry points via resolve.alias
resolve: {
  alias: {
    'my-lib': 'my-lib/dist/esm/src',
  }
}
  1. Validate tree-shaking with production build analysis
webpack --mode production --json > stats.json && npx webpack-bundle-analyzer stats.json