Guide to sideEffects in package.json
This article provides an overview of the sideEffects
property in package.json, explaining what side effects are
in JavaScript and how modern bundlers use this flag to optimize
tree-shaking. You will learn how configuring this property properly
helps bundlers like Webpack, Rollup, and Vite eliminate unused code
safely and reduce your final bundle size.
What Are Side Effects in JavaScript?
A JavaScript file has a “side effect” if executing its code performs an action that affects the global scope or external state, beyond just exporting functions, objects, or variables. Examples of side effects include:
- Modifying global objects or prototypes (such as polyfills like
core-js). - Attaching event listeners to
windowordocument. - Executing immediate logic on import, such as logging or initializing analytics.
- Importing global CSS or SCSS stylesheets (e.g.,
import './styles.css').
If an imported file contains no side effects and its exports are not consumed, it can safely be removed from the final production build without altering the application’s behavior.
Why Bundlers Need the
sideEffects Flag
Static code analysis can determine which named exports are imported and used. However, static analysis cannot always guarantee that an unreferenced module is safe to delete.
By default, JavaScript bundlers must assume that any imported file might contain code with side effects. For example:
import { Button } from 'my-ui-library';If my-ui-library contains multiple components, a bundler
might hesitate to remove unused components like Modal or
Tooltip if it cannot prove their execution does not modify
the global state.
The sideEffects field in package.json acts
as an explicit signal from package authors to the bundler, confirming
whether files in the package are free from side effects.
How to Configure
sideEffects
The sideEffects property is configured in the root of a
library’s package.json file. It accepts two primary
formats: a boolean or an array of file paths.
1. Setting
sideEffects to false
If none of the modules in your package perform actions outside their
exports, set the property to false:
{
"name": "my-pure-library",
"version": "1.0.0",
"sideEffects": false
}This tells the bundler that any file in this package can be completely skipped if none of its exports are imported by the consuming application.
2. Specifying Files with Side Effects
If certain files in your package do contain side effects—such as CSS imports, initialization scripts, or polyfills—you can provide an array of file paths or glob patterns:
{
"name": "my-ui-library",
"version": "1.0.0",
"sideEffects": [
"*.css",
"*.scss",
"./src/polyfills.js",
"./src/analytics/init.js"
]
}In this case, the bundler treats only the listed files as having side effects, while treating all other unlisted files as pure.
How Bundlers Process the Property
When a bundler builds an application:
- Graph Construction: The bundler reads the dependency graph from the entry point.
- Flag Evaluation: It checks the
package.jsonof each imported dependency for thesideEffectsproperty. - Pruning (Tree-Shaking):
- If a module has no exported members used and is marked as having no side effects, the bundler removes the entire module from the bundle.
- If a module is marked as having side effects, the bundler includes the module’s code in the output to preserve its runtime behavior, even if no named exports are consumed.
Best Practices
- Always declare the property: For library authors,
adding
"sideEffects": falseis one of the most effective ways to enable optimal tree-shaking for consumers. - Account for CSS: If your component library imports
CSS files directly inside JavaScript components, ensure CSS patterns
(like
*.css) are included in thesideEffectsarray so styles are not accidentally stripped out during the build.