Understanding `sideEffects` in package.json (and Why Library Authors Should Care)
One of the most misunderstood fields in package.json is also one of the most dangerous. Misuse it and your library may work locally but fail in production.
When building an NPM library, most developers obsess over build tools, bundle size, TypeScript configs, and exports.
Yet one tiny field quietly controls how your package behaves inside consumer applications:
{
"sideEffects": false
}
It looks harmless. It is not.
This single setting influences how bundlers treat your files, what gets removed from production bundles, and in some cases, whether your library even works.
Let’s break it down properly.
What Does sideEffects Actually Mean?
Despite the name, this flag has nothing to do with React hooks or functional programming.
It is a tree-shaking hint for bundlers like:
- Webpack
- Rollup
- Vite (esbuild)
- esbuild
- SWC-based toolchains
You are telling the bundler:
Is it safe to delete unused imports from my package?
sideEffects: false → Aggressive Optimization Mode
Setting:
{
"sideEffects": false
}
Means:
“Every file in this package is safe to remove if nothing from it is used.”
Example:
// math.ts
export const add = (a: number, b: number) => a + b
If a consumer imports add but never uses it, the bundler may erase the entire import.
This is great for bundle size.
But only if your files are truly safe.
What Counts as a Side Effect?
A file has side effects if simply importing it changes runtime behavior.
Not calling functions. Just importing.
Examples:
1. Global mutations
Array.prototype.sum = function () {}
Dangerous to remove. This modifies global behavior.
2. Initialization logic
console.log("Library loaded")
startAnalytics()
Even if exports are unused, removing this changes behavior.
3. Style injection
import "./styles.css"
Removing the file removes the styles.
Very common mistake.
The CSS Trap Most Library Authors Hit
If your library contains:
import "./button.css"
and you publish with:
"sideEffects": false
Consumers may report:
“Your components render but have no styles.”
Because the bundler deleted your CSS import.
Correct solution:
{
"sideEffects": ["*.css"]
}
Meaning:
“Everything is safe to tree-shake except CSS.”
When Should You Use sideEffects: false?
Safe for libraries where files:
- Only export values
- Do not mutate globals
- Do not run startup logic
- Do not rely on execution during import
Typical examples:
- Utility libraries
- Hooks libraries
- Pure helper functions
- Headless component libraries
When Should You Avoid It?
Do NOT blindly use false if your package:
- Injects styles automatically
- Registers globals
- Patches prototypes
- Runs runtime initialization
- Depends on import-time execution
Otherwise, consumer apps may break in subtle ways.
What If You Don’t Set sideEffects at All?
If the field is omitted, bundlers usually treat your package conservatively.
In practice, that means:
- They assume files may have side effects
- They avoid the most aggressive module-level pruning
- You often get safer runtime behavior, but larger bundles
So omission is the "safe default."
"sideEffects": false is an explicit promise that your files are safe to shake aggressively.
Why Bundlers Need This Hint
Bundlers cannot safely analyze every possible runtime behavior.
So they trust the package author.
sideEffects is essentially you saying:
“I know my files. You can optimize aggressively.”
If you lie, builds break.
Practical Mental Model
Ask one simple question:
“If this file is imported but nothing is used from it, does anything still happen?”
If yes → It has side effects
If no → It is side-effect free
Final Advice for Library Authors
Never copy this setting from another repo.
Audit your files first.
Especially check for:
- CSS imports
- Global patches
- Initialization code
- Runtime registrations
Small flag. Big consequences.
Enjoyed this article?
Let's connect and discuss more about frontend architecture and AI engineering.