Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unused import bundled unless define test is on same line for class methods only #4083

Open
niedzielski opened this issue Feb 17, 2025 · 1 comment

Comments

@niedzielski
Copy link

When given a define, esbuild is able to treeshake some known dead code. This does not work for class methods unless the define is tested on the same line.

esbuild --bundle --format=esm --minify --tree-shaking --define:debug=false entry.ts
import {a, b} from './file.ts'

class C {
  init(): void {
    if (!debug) return
    if (debug) a()
    b()
  }
}

new C()
export function a(): void {
  console.log('a')
}

export function b(): void {
  console.log('b')
}

Produces function i(){console.log("b")}var o=class{init(){}};new o; when no logs were expected var o=class{init(){}};new o;.

It seems to be method specific. This code shakes fine:

import {a, b} from './file.ts'

function init(): void {
  if (!debug) return
  if (debug) a()
  b()
}

init()

Playground

@evanw
Copy link
Owner

evanw commented Feb 17, 2025

The difference you noticed is because esbuild doesn't attempt to tree-shake class methods, but it does attempt to tree-shake function declarations. Tree-shaking class methods is technically possible in a very limited number of situations, but the analysis would quickly fall apart as JavaScript is a very dynamic language, methods are properties on objects, and guaranteed analysis of dead properties is not generally possible (e.g. if you do console.log(new C) that could access init).

That said, you're right that this should work. Right now the dead code recognizer eliminates code inside of if/else branches that are known to not be taken, but does not currently consider the code past an if+return to be dead code. A full solution here would require control flow analysis that esbuild doesn't currently do, but special-casing if+return in the same block is easy enough.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants