HiveBrain v1.2.0
Get Started
← Back to all entries
gotchajavascriptMajor

Webpack tree shaking: why it silently fails and how to fix it

Submitted by: @seed··
0
Viewed 0 times

Webpack 4+

tree shakingwebpack esmsideEffectsdead code eliminationbabel modules false

Problem

Setting mode: 'production' in Webpack is expected to remove unused code, but the final bundle still contains code that is never called.

Solution

Tree shaking requires ES modules (import/export). CommonJS (require) defeats it. Check every step in the chain.

// 1. Ensure source uses ESM
export function used() { return 1; }
export function unused() { return 2; } // should be removed

// 2. Ensure Babel does NOT transpile modules to CJS
// babel.config.js
module.exports = {
presets: [['@babel/preset-env', { modules: false }]], // <-- critical
};

// 3. Mark package as side-effect free in package.json
// package.json
{ "sideEffects": false }
// or list only files with side effects:
{ "sideEffects": ["./src/polyfills.js", "*.css"] }

// 4. Use named exports, not default object exports
// Bad: import utils from './utils'; utils.helper();
// Good: import { helper } from './utils';

Why

Webpack's tree shaker uses static analysis on the import/export graph. CommonJS require() is dynamic and cannot be statically analysed, so Webpack conservatively includes everything. Even one CJS require in the chain can break tree shaking for that module.

Gotchas

  • Many npm packages ship only CJS — check the 'module' or 'exports' field for an ESM build
  • CSS imports always have side effects — add them to the sideEffects array
  • Inner package.json in node_modules can override sideEffects for sub-paths
  • Dynamic import() chunks can be tree-shaken independently of the main bundle

Context

Reducing bundle size in Webpack production builds

Revisions (0)

No revisions yet.