Tree Shaking
In short
Tree shaking is a build optimization that removes code a program never uses from the final bundle, based on which ES module exports are actually imported.
What is tree shaking?
Tree shaking is a technique bundlers use to leave unused code out of the files shipped to users. If you import one function from a utility library that exports a hundred, tree shaking keeps only that function and whatever it depends on. The result is a smaller download and less JavaScript for the browser to parse and run.
It relies on the static structure of ES modules: import and export statements sit at the top level and can't change at runtime, so a bundler can work out which exports are used without running the code. Anything not reachable from the entry point is dropped, and a minifier then removes leftover dead code inside functions. CommonJS modules, which use require(), are dynamic and much harder to shake. Code with side effects, such as a module that changes a global object when it is imported, can't be removed safely, which is why libraries declare "sideEffects": false in package.json to tell bundlers that unused files can be skipped.
The name pictures your code as a tree: shake it, and the dead leaves that nothing is attached to fall off. Tree shaking is on by default in the production builds of modern bundlers. You get the most out of it by importing named functions, as in import { debounce } from "./utils.js", rather than a whole library object, and by preferring libraries published as ES modules.
Tree shaking is often confused with minification and code splitting. Minification shrinks the code that remains, by removing whitespace and shortening names, but doesn't decide which modules to include. Code splitting doesn't remove anything; it divides the code you do use into separate chunks that load on demand. Tree shaking removes whole unused exports, and the three usually work together in a production build.
Key takeaways
- Tree shaking drops exports that are never imported from the final bundle.
- It depends on the static
importandexportsyntax of ES modules. - Side effects can block removal;
"sideEffects": falseinpackage.jsonhelps bundlers. - Import only the named functions you need to get the most benefit.
- Tree shaking removes unused code, minification shrinks the rest, and code splitting divides it into chunks.
Example
// utils.js exports three functions
export function formatDate(d) { return d.toISOString().slice(0, 10); }
export function formatPrice(n) { return "$" + n.toFixed(2); }
export function slugify(s) { return s.toLowerCase().replace(/\s+/g, "-"); }
// main.js imports only one of them
import { formatDate } from "./utils.js";
console.log(formatDate(new Date()));
// After a production build, formatPrice and slugify are gone:
// the bundle contains only formatDate and the code from main.js.Readers ask
Why is tree shaking not working?
Common causes are a library published only as CommonJS, importing a whole library as one object, code transpiled to CommonJS before bundling, or modules with side effects the bundler must keep. A bundle analyzer shows what actually ended up in the output.
Does tree shaking work with CommonJS?
Only partly. Because require() can be called anywhere and with computed names, bundlers can analyze only simple patterns, so ES modules give far more reliable results.
What is the difference between tree shaking and dead code elimination?
Dead code elimination is the general compiler optimization of removing code that can never run or whose result is never used, such as an if (false) branch. Tree shaking applies the same idea at the module level, removing whole exports that nothing imports.
See also
- BundlerWeb Development, p. 3A bundler is a build tool that combines JavaScript modules and their dependencies into a few optimized files that browsers can download and run quickly.
- MinificationWeb Development, p. 30Minification is the process of shrinking code files by removing whitespace, comments and long names without changing behavior, so web pages download faster.
- Code SplittingWeb Development, p. 5Code splitting is a technique that breaks a web app's JavaScript into smaller chunks loaded on demand, so the first page load downloads only the code it needs.
- JavaScriptWeb Development, p. 24JavaScript is the programming language that runs in web browsers to make pages interactive, and it also runs on servers through runtimes like Node.js.
- Core Web VitalsWeb Development, p. 7Core Web Vitals are three metrics that measure a page's real-user experience: loading speed (LCP), responsiveness (INP), and visual stability (CLS).
- ES ModulesWeb Development, p. 15ES modules are JavaScript's built-in module system: each file keeps its own scope and shares code with other files through import and export.
Spotted a mistake or something missing on this page?Suggest an edit