Enable and Verify Rollup Tree‑Shaking for an ES Module Bundle
Learn how to turn on Rollup’s built‑in tree‑shaking, verify that unused exports are removed, and recover if needed code is dropped.
24 Jul 2025, 18:26 UTC

Desired outcome
Create a Rollup bundle that contains only the exports actually imported by consumer code, reducing the final payload size through built‑in tree‑shaking.
Prerequisites
- Node.js version 14 or newer.
- A project folder with a
package.json(you can runnpm init -yto create one). - Source files written as ES modules (using
importandexportstatements). - Rollup installed as a development dependency:
npm i -D rollup. - Optional: a minification plugin such as
@rollup/plugin-terserif you also want the bundle minified (npm i -D @rollup/plugin-terser).
Procedure
- Add a basic Rollup configuration. Create a file named
rollup.config.jsin the project root with the following content:import { terser } from 'rollup-plugin-terser'; export default { input: 'src/index.js', output: { file: 'dist/bundle.esm.js', format: 'esm', }, treeshake: true, plugins: [terser()], // remove if you do not want minification };Explanation:
inputpoints to the entry ES module.output.fileis where the bundle will be written;format: 'esm'preserves ES module syntax for consumers.treeshake: truetells Rollup to perform static analysis and drop unused exports.- The
terserplugin is optional; it only minifies code and does not affect tree‑shaking.
- Ensure your modules are pure. If a module has no side‑effects, add
"sideEffects": falseto thepackage.jsonat the project root. This lets Rollup safely discard the entire module when none of its exports are used. If you are unsure, keep the default ("sideEffects": true) or list specific files that have side‑effects. - Run the build. From the project root, execute:
npx rollup --configThis command reads
rollup.config.js, performs tree‑shaking, and writes the bundle todist/bundle.esm.js. No special permissions are required beyond normal file read/write access in the project directory.
Expected checks
- Inspect the bundle for dead exports. Open
dist/bundle.esm.jsin a text editor and search for an export you know is not imported anywhere (e.g.,export function unusedHelper() { … }). If tree‑shaking worked, that function definition should not appear in the bundle. - Compare bundle sizes. Build a second version with tree‑shaking disabled to have a baseline:
npx rollup --config --environment TREESHAKE:falseYou can achieve this by adding an environment variable check in the config:
treeshake: process.env.TREESHAKE !== 'false',Then compare the file sizes (e.g.,
ls -lh dist/bundle.esm.js). The treeshaken build should be noticeably smaller. - Consumer‑side verification. In a separate test project, install the bundle as a local dependency (
npm i ../path/to/your/project) and import only the used member:import { usedFeature } from 'your-package/dist/bundle.esm.js'; console.log(usedFeature());Attempt to access the unused export (
import { unusedHelper } …) – the bundle will not contain it, so the import will resolve toundefinedor cause an error, confirming the code was removed.
Recovery options (if needed code is dropped)
- Mark the module as having side‑effects. If Rollup removed code that actually runs at initialization (e.g., a polyfill that patches a global), set
"sideEffects": truefor that specific file inpackage.json:"sideEffects": ["src/polyfill.js"] - Preserve entry signatures. Add
preserveEntrySignatures: 'strict'to the Rollup config. This forces Rollup to keep the original export shape of the entry module, preventing accidental removal of re‑exports that may be relied upon. - Re‑run the build. After adjusting
sideEffectsorpreserveEntrySignatures, runnpx rollup --configagain and verify the bundle now contains the expected code.
Limitations
- Tree‑shaking only works when inputs are genuine ES modules. If you feed Rollup CommonJS files (e.g., via
@rollup/plugin-commonjswithout theesmExportsoption), the static analyser cannot reliably determine which exports are used, and dead code may be retained. - Incorrectly marking a module as side‑effect‑free (
"sideEffects": false) can cause Rollup to drop initialization code that is required at runtime, leading to broken bundles. Always verify that the removed code truly has no observable side‑effects. - The size difference may be modest if most exports are already used; tree‑shaking is most beneficial when large utility libraries expose many functions but only a few are imported.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.