esbuild icon indicating copy to clipboard operation
esbuild copied to clipboard

[Bug]: tree shaking breaks with dynamic import() in some situation

Open Ayc0 opened this issue 5 months ago • 1 comments

System Info

  System:
    OS: macOS 15.5
    CPU: (10) arm64 Apple M1 Max
    Memory: 2.34 GB / 64.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 24.4.1 - ~/.volta/tools/image/node/24.4.1/bin/node
    pnpm: 10.13.1 - ~/.volta/tools/image/pnpm/10.13.1/bin/pnpm
    Watchman: 2025.07.28.00 - /opt/homebrew/bin/watchman
  npmPackages:
    esbuild: ^0.25.8 => 0.25.8

Details

If you have a file foo.ts that contains 2 exports:

// foo.ts
export const bar = 'bar';
export const paz = 'paz';

Tree shaking will work (aka the unused variable will be stripped out during compilation) when writing:

// stripped.ts
import { bar } from './foo';

But if the file is lazy loaded using import(), paz is kept in the bundle:

// kept.ts
const { bar } = await import('./foo');
import('./foo').then(module => module.bar);
import('./foo').then(({ bar }) => bar);

The config I used is a simple one:

{
    "bundle": true,
    "treeShaking": true,
    "splitting": true,
    "format": "esm",
    "outdir": ".",
    "write": false
}

Reproduce link

https://github.com/Ayc0/code-splitting-issue

Reproduce Steps

You can clone https://github.com/Ayc0/code-splitting-issue and run node --test tests/esbuild.test.mjs (requires node 24.4.0+)

Ayc0 avatar Jul 30 '25 05:07 Ayc0

I have the same problem that doesn't allow me to switch from webpack + babel-loader to esbuild.

acherkashin avatar Oct 23 '25 11:10 acherkashin