Understanding sideEffects: false in package.json

The "sideEffects": false property in package.json is a configuration flag that tells modern JavaScript bundlers, such as Webpack, Rollup, and Vite, that a package contains no code that modifies external state upon import. By declaring this flag, you allow the bundler’s tree-shaking engine to safely remove unused imports entirely from the final production bundle. This article explains what side effects are in JavaScript, how the flag enables aggressive tree shaking, how to configure it correctly, and how it drastically reduces bundle sizes.

What is a Side Effect in JavaScript?

A “side effect” occurs when an imported module executes code that affects the global scope or modifies behavior outside of its own exported functions. Even if an application never directly calls an export from that module, running the module itself changes the environment.

Common examples of side effects include: * Modifying global objects (e.g., window.myCustomProperty = true) * Attaching event listeners to window or document * Importing CSS or SCSS stylesheets (e.g., import './styles.css') * Executing polyfills (e.g., import 'core-js') * Executing top-level logic or self-invoking functions immediately upon import

Why Bundlers Need the sideEffects Flag

JavaScript bundlers perform “tree shaking” (dead code elimination) to discard unused exports. However, static analysis tools cannot always determine if evaluating an unused module will trigger necessary side effects.

Without the sideEffects flag: 1. You import a utility: import { formatDate } from 'large-utility-library'; 2. The library has 50 other utility files that are not imported. 3. The bundler must inspect every file to ensure none of them execute global code upon being loaded. If it cannot guarantee safety, it bundles the unused code, leading to bloated builds.

Setting "sideEffects": false explicitly guarantees to the bundler: “If a file’s exports are not consumed, it is 100% safe to drop the entire file and avoid compiling it.”

How to Configure sideEffects

You can define sideEffects in your project’s package.json using either a boolean value or an array of file patterns.

1. Pure Libraries (No Side Effects)

If your library consists entirely of pure functions and components with no global mutations or direct CSS imports, set the value to false:

{
  "name": "my-pure-library",
  "version": "1.0.0",
  "sideEffects": false
}

2. Libraries with Specific Side Effects

If your project is mostly pure but includes certain files that must always run—such as CSS files or polyfills—provide an array of relative paths or glob patterns:

{
  "name": "my-ui-library",
  "version": "1.0.0",
  "sideEffects": [
    "*.css",
    "*.scss",
    "./src/polyfills.js",
    "./src/global-init.js"
  ]
}

In this scenario, any imported CSS files and the polyfill script will execute as intended, while all other unused JavaScript modules will be eliminated during the build process.

How sideEffects: false Optimizes Build Sizes

  1. Eliminates Whole Modules, Not Just Statements: Standard tree shaking removes unused functions inside an imported file. The sideEffects: false flag allows bundlers to skip parsing, bundling, and executing entire unreferenced files.
  2. Accelerates Build Times: Because the bundler can safely ignore unreferenced dependency files, it spends less time analyzing Abstract Syntax Trees (ASTs) during minification.
  3. Drastically Reduces Output for Component and Utility Libraries: In large libraries (like UI component libraries or large utility toolkits), a consumer might only use one component. With sideEffects: false, only that specific component and its direct dependencies make it into the final bundle, often reducing library footprint by 80% to 90%.

Best Practices