This is a command-line tree-shakability doctor for JavaScript packages. Compared to alternatives, it not only reports whether a package is tree-shakable but also pinpoints the root causes of non-tree-shakability in the JavaScript or TypeScript source.
-
Ensure that your package’s
package.jsonfile specifies"main"or"module". -
If your package is built, enable source-map generation. For TypeScript, this is done via
"sourceMap".
-
If your package is built, run the build step.
-
Run
is-tree-shakablein the package root:npx is-tree-shakable
If the package is tree-shakable,
is-tree-shakableproduces no output and exits with code 0; otherwise, it lists the root causes of non-tree-shakability and exits with code 1.
Tree shaking is a technique used by modern JavaScript builds tools—such as Webpack, Rollup, or Parcel—to remove unused code during bundling, saving space and boosting performance. It’s particularly beneficial for package consumers, who often use only a subset of the exported members. While tree shaking occurs in the consumer’s build pipeline, a package must meet two criteria to enable the removal of its unconsumed code. When this is the case, the package is tree-shakable.
- It must use ES6 modules.
- It must be obviously free of externally observable side effects that occur during module evaluation.
While the adoption of ES6 modules is straightforward, the second requirement presents a significant pitfall. Some logic—like modifying window at the module level—is evidently problematic. However, because the static analysis that powers tree shaking in widely used bundlers is quite simplistic, they err on the side of caution and also treat many verifiably side effect–free constructs as side-effectful. As a result, code that could be safely eliminated is unexpectedly retained.
is-tree-shakable helps avoid this: it pinpoints constructs that block tree shaking, whether they truly have externally observable side effects or merely are treated as such by bundlers. Collectively, these are referred to as possibly side-effectful.
When is-tree-shakable flags a construct as possibly side-effectful, evaluate if it actually has externally observable side effects. If so, move it accordingly. If not, use @__PURE__, which is a standard annotation that bundlers treat as a guarantee of non-side-effectfulness.
-
For call expressions, usage is straightforward:
/* @__PURE__ */ foo();
-
Other constructs—such as property access—may also be reported as possibly side effectful, but
@__PURE__is applicable only to call expressions. To work around this, use an IIFE:/* @__PURE__ */ (() => bar.baz)();
Founded in 2012, Software Mansion is a software agency with experience in building web and mobile apps. We are core React Native contributors and experts in dealing with all kinds of React Native issues. We can help you build your next dream product—hire us.
