Optimizing Rollup Bundles: The Power of the sideEffects Flag
Rollup’s sideEffects flag lets you prune unused code, but it must be used carefully. Learn how to set the flag, test bundle size gains, and avoid breaking your app.
28 Jul 2026, 14:18 UTC

What’s the real problem?
When you ship a web app, every kilobyte counts. A common culprit is code that never runs but still ends up in the final bundle because Rollup can’t prove it’s safe to drop. Developers often wonder how to tell Rollup that a module has no side‑effects so it can prune unused exports more aggressively.
Why the sideEffects flag matters
Rollup performs tree‑shaking by statically analyzing ES modules. It looks at the import graph and removes any code that isn’t reachable from the entry point. However, if a module contains code that runs on import (e.g., a polyfill that mutates the global object), Rollup conservatively keeps the entire module even if none of its exported symbols are used.
The sideEffects field in package.json tells Rollup whether a package can be safely considered side‑effect free. Setting "sideEffects": false enables Rollup to drop unused modules entirely, but it also carries a risk: if you’re wrong, essential initialization code can disappear.
How Rollup uses the flag
Rollup’s algorithm works in three stages:
- Dependency graph construction – Build a tree of all imported modules.
- Marking reachable exports – Follow imports to determine which exported values are actually used.
- Pruning – Remove any modules or exports that aren’t reachable and are marked as side‑effect free.
The sideEffects flag is consulted during the pruning step. If a module is marked as having side‑effects, Rollup treats it as if it could mutate global state, so it never removes it, even if none of its exports are used.
A concrete example
Let’s walk through a minimal library that exports three functions, but only one is needed by the application.
// utils.js – a tiny library
export function used() { console.log('used'); }
export function unused() { console.log('unused'); }
export function sideEffect() { window.foo = 'bar'; }
Suppose the application imports only used:
// main.js
import { used } from './utils.js';
used();
Without any side‑effects declaration, Rollup will keep all three functions because sideEffect mutates window. To let Rollup drop unused and sideEffect, add the following to package.json in the utils package:
{
"name": "utils",
"sideEffects": false
}
Now run Rollup:
npx rollup -c --silent
Check the resulting bundle (dist/bundle.js) to confirm that only the used function appears. You can also run:
npx rollup -c --verbose
to see which modules were excluded.
Trade‑offs and limitations
- CommonJS modules – Tree‑shaking doesn’t work with
require()because the imports are dynamic. ThesideEffectsflag only applies to ES modules. - Incorrectly marking a package – If a module actually mutates global state but you set
sideEffects: false, that code will be removed, potentially breaking the app (e.g., a CSS import that injects styles). - Complex mutations – Rollup can’t always detect subtle side‑effects like modifying a global object passed as a function argument. In such cases, rely on the flag or keep the code explicit.
How to verify your bundle size gains
1. Measure the size before and after adding the flag. A simple stat or du -h on dist/bundle.js will show the difference.
2. Inspect the minified output. Look for the absence of the function names you expected to be removed.
3. Use the --verbose flag or a plugin like rollup-plugin-visualizer to confirm that the unused modules are excluded.
Actionable takeaway
When you’re confident a module has no side‑effects, set "sideEffects": false in its package.json. This can shave dozens of kilobytes off your bundle, but always double‑check that you haven’t accidentally removed essential initialization code. For safety, run rollup --verbose after the change and review the excluded modules.
In short: mark side‑effect free, test, and verify. That’s the recipe for leaner Rollup bundles.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.