Tree shaking
Rspack supports tree shaking, a term commonly used in the JavaScript ecosystem for removing unused code, also known as "dead code". Dead code occurs when module exports are unused and have no side effects, allowing them to be safely removed to reduce bundle size.
What is tree shaking
Think of your application as a tree. The source code and libraries you actually use are the green, living leaves. Dead code is like the brown, dead leaves consumed by autumn. To remove the dead leaves, you shake the tree and they fall off.
Rspack doesn't directly remove dead code—it marks unused exports as potential "dead code". Minification tools then recognize and process these markers. If minimize is disabled, you won't see any actual code removal.
Dead code is code that's no longer executed, typically due to refactoring, optimization, or logical errors. It may be a remnant from previous versions or code that never executes under any condition.
Prerequisites
To effectively leverage tree shaking, you need to:
- Set Rspack's mode to
productionto enable tree shaking optimizations.- In production builds,
modedefaults toproduction.
- In production builds,
- Use ES module syntax (
importandexport).- When using compilers like SWC or Babel, ensure they don't transform ES modules to CommonJS.
- For example, in @babel/preset-env, set
modulestofalse.
Configurations
When mode is set to production, Rspack enables several tree shaking optimizations:
- usedExports: Detects which module exports are used, enabling removal of unused exports.
- sideEffects: Analyzes modules for side effects. Modules without side effects can be further optimized through re-exports.
- providedExports: Analyzes all exports and tracks their re-export sources.
- innerGraph: Tracks variable usage to more accurately determine if exports are actually used.
The following examples illustrate how these options work. For clarity, we'll use simplified code to demonstrate code removal.
Let's look at an example with src/main.js as the entry point:
In this example, bar from util.js is unused. In production mode, Rspack enables usedExports by default, which detects which exports are used. Unused exports like bar are removed. The final output looks like this:
Side effects analysis
In production mode, Rspack also analyzes modules for side effects. If all exports from a module are unused and the module has no side effects, the entire module can be removed. Let's modify the previous example:
In this case, none of the exports from util.js are used, and it’s analyzed as having no side effects, permitting the entire deletion of util.js.
You can manually indicate whether a module has side effects via package.json or module.rules. To do this, enable optimization.sideEffects.
In package.json, you can use true or false to indicate whether all modules in the package have side effects.
This package.json indicates that all modules in this package are side-effect-free.
You can also use glob patterns to specify which modules have side effects. Unmatched modules are automatically treated as side-effect-free. If you manually mark side effects, ensure all unmarked modules truly have no side effects.
This package.json indicates that only ./src/main.js and all .css files have side effects, while all other modules are side-effect-free.
Re-export analysis
Re-exports are common in development. However, a module might import many other modules while only needing a few exports. Rspack optimizes this by allowing consumers to access the actual exported modules directly. Consider this re-export example:
Rspack enables providedExports by default, which analyzes all exports from a re-exporting module and identifies their origins.
If src/re-exports.js has no side effects, Rspack can convert the import in src/main.js to import directly from src/value.js:
This allows Rspack to completely skip the src/re-exports.js module.
By analyzing all re-exports in src/re-exports.js, Rspack determines that foo from src/value.js is unused and removes it from the final output.
Variable transmission
Sometimes exports are imported but not actually used. For example:
In this scenario, even though the log function and the bar variable depend on foo, neither is used, so foo is considered dead code and removed.
When innerGraph is enabled (the default in production mode), Rspack can track variable usage across modules to achieve precise code optimization.
Since value is used, the foo it depends on is retained.
Pure annotation
Use the /*#__PURE__*/ annotation to tell Rspack that a function call is side-effect-free (pure). Place it before function calls to mark them as having no side effects.
When an unused variable's initial value is marked as side-effect-free (pure), it's treated as dead code and removed by the minimizer.
- Function arguments aren't marked by the annotation and may need to be marked individually.
- This behavior is enabled when optimization.innerGraph is set to true.
NO_SIDE_EFFECTS annotation
/*#__NO_SIDE_EFFECTS__*/ is a feature that follows the community JavaScript Compiler Hints Spec. Unlike /*#__PURE__*/ which marks call sites, /*#__NO_SIDE_EFFECTS__*/ is used to mark function definitions, declaring that the function has no side effects when called with arguments.
Enabling
This feature is currently experimental and needs to be enabled via following experimental feature configuration, and it depends on optimization.sideEffects (sideEffects is enabled by default in production mode):
Usage
You can place this annotation before function declarations, function expressions, arrow functions, or export statements, check spec for details:
If a function is marked as side-effect-free and its return value is unused, Rspack can safely remove the call. Compared to /*#__PURE__*/, the advantage is that you only need to mark it once at the definition, and all call sites will benefit.
pureFunctions
pureFunctions lets you manually mark top-level exported functions in matched modules as side-effect-free for pure-function-based tree shaking. This is useful for third-party libraries where source code cannot be modified, such as packages in node_modules.
This option is experimental and only takes effect when experiments.pureFunctions is enabled.
Only top-level exported function definitions are supported. For default exports, use default as the exported name.
For business source code where modification is possible, it is recommended to use the /*#__NO_SIDE_EFFECTS__*/ annotation.
Usage
This option is configured in module.rules[i].parser:
Rspack validates each configured name against the matched module. If a configured exported function name cannot be found, Rspack emits a warning.

