JavaScript · Question 100
Why do ES modules make tree shaking easier, and why can side effects still prevent dead-code elimination?
Direct answer
ES import/export structure is statically analyzable, so build tools can reason about which exports are referenced; however, unused-looking modules or statements may still have observable side effects, so safely removing them requires side-effect analysis and build configuration rather than merely seeing an unused name.
Static import and export declarations give bundlers a dependency graph they can analyze without executing arbitrary module-loading code. This makes it possible to determine that certain exported bindings are never referenced by the reachable application graph.
But an unused export does not mean every statement that produced it can disappear. Importing a module can execute top-level code: registering something globally, modifying a prototype, initializing telemetry, importing CSS through a toolchain, or performing other observable work. Removing that module could change behavior.
- Prefer modules with explicit exports and limited top-level side effects when you want optimization to be predictable.
- Package metadata that declares side-effect characteristics is a build-tool contract and must be accurate; marking effectful modules as side-effect-free can break applications.
- Tree shaking is a build-time optimization enabled by analyzable module structure, not a runtime feature guaranteed by the JavaScript engine.