tldr; what is preventing React from being dead-code eliminated in my project? It is not being used, apart in an unused utility in a library I am consuming.
I recently created a little library for retrying failing dynamic imports. I made a non-react-dependant module and another one that just handled the react specifics. This was to ensure a consumer would not pull in React if not using the react utils. I then created an index module that pulled the two in and exported named constants
import _createDynamicImportWithRetry from "./dynamic-import-with-retry";
import _reactLazy from "./react-lazy";
export const reactLazyWithRetry = _reactLazy;
export const createDynamicImportWithRetry = _createDynamicImportWithRetry;
This is the main
field in package.json
.
I assumed from previous reading that when Vite consumes this library it should be able to gather that just importing the named export createDynamicImportWithRetry
would only require pulling in "./dynamic-import-with-retry", not the other import. Unfortunately, that does not seem to be the case: I published a project that shows it not to be the case: the transitive React dependency is being bundled, no matter if it is unused.
I would have assumed that dead-code analysis during bundling for production would have pruned the unused imports of the tree. How can I ensure pruning of dead branches take place?
Reproduction:
mkdir tmp-proj && cd tmp-proj && mkdir src
echo '<script type="module" src="./src/index.js"></script>' > index.html
echo "import * as o from '@fatso83/retry-dynamic-import'
o.reactLazyWithRetry( () => Promise.resolve())" > src/index.js
npm i @fatso83/retry-dynamic-import; npm i vite
npx vite build
vite v4.3.5 building for production...
✓ 13 modules transformed.
dist/index.html 0.08 kB │ gzip: 0.09 kB
dist/assets/index-4e07d3ed.js 9.27 kB │ gzip: 3.89 kB
The 9KB there is the problem. It should be closer to 500 bytes, but it pulls in all of the React production build :/