Rspack supports tree shaking, a terminology widely used within the JavaScript ecosystem defined as the removal of unused code, commonly referred to as "dead code." Dead code arises when certain exports from a module are not used and they lack side effects, allowing such pieces to be safely deleted to reduce the final output size.
Upon setting the mode
to production
, Rspack by default enables a series of optimizations related to tree shaking, including:
Below are examples to illustrate how these configuration options function.
Note that Rspack does not directly remove dead code but labels unused exports as potential "dead code." These labels can then be recognized and processed by subsequent compression tools. As such, if compression features are turned off, no actual code removal will be observable. For enhanced readability, pseudocode might be used to demonstrate the effects of code removal.
Let's understand this mechanism better through an example, assuming src/main.js
as the project's entry point:
In this example, bar
from util.js
is unused. In production
mode, Rspack defaults to enabling the usedExports optimization, detecting which exports are actively used. Unused exports, like bar
, are safely removed. The final output would resemble:
In production
mode, Rspack also typically analyzes modules for the presence of side effects. If all exports from a module are unused and the module is devoid of side effects, then the entire module can be deleted. Let's modify the previous example a bit:
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 may manually indicate whether a module retains side effects through package.json
or module.rules
. For information on how to do so, please consult sideEffects.
Re-exports are common in development. However, a module might pull in numerous other modules while typically only a fraction of those are needed. Rspack optimizes this situation by ensuring that the referring party can access the actual exported modules directly. Consider this example involving re-exports:
Rspack defaults to enable providedExports, which can analyze all exports from a re-exporting module and identify their respective origins.
If src/re-exports.js
contains no side effects, Rspack can convert the import in src/main.js
from src/re-exports.js
directly into imports from src/value.js
, effectively:
This approach benefits by entirely ignoring the src/re-exports.js
module.
With an ability to analyze all re-exports in src/re-exports.js
, it is determined that foo
from src/value.js
is not used and will be removed in the final output.
In some cases, even though exports are accessed, they might not actually be used. For example:
In the scenario above, even though the log
function and the variable bar
depend on foo
, since neither is used, foo
can still be considered dead code and be deleted.
After enabling innerGraph optimization (enabled by default for production
mode), for complex cross-module situations, Rspack maintains the ability to track variable usage, thereby achieving precise code optimization.
In this context, because value
is eventually used, the foo
it depends on is retained.