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

esbuild.keepNames causes typescript closure/function to not be tree shaken #9164

Closed
7 tasks done
Pyrolistical opened this issue Jul 17, 2022 · 0 comments · Fixed by #9166
Closed
7 tasks done

esbuild.keepNames causes typescript closure/function to not be tree shaken #9164

Pyrolistical opened this issue Jul 17, 2022 · 0 comments · Fixed by #9166
Labels
p3-minor-bug 🔨 An edge case that only affects very specific usage (priority)

Comments

@Pyrolistical
Copy link

Pyrolistical commented Jul 17, 2022

Describe the bug

When esbuild.keepNames is enabled tree shaking doesn't work with closure/functions written in typescript.

In my reproduction case I setup 4 functions

  1. devOnlyClosure that starts with if (import.meta.env.PROD) return;
  2. devOnlyFunction that starts with if (import.meta.env.PROD) return;
  3. thisClosureIsNeverCalled that is never called
  4. thisFunctionIsNeverCalled that is never called

From my main file, I import the first two functions can call them.

When I make a production build I expect no JavaScript bundle as both of the called functions are effectively empty and remaining closure/function is never called nor imported.

But what I end up getting is this:

var l = Object.defineProperty;
var e = (n, o) => l(n, 'name', { value: o, configurable: !0 });
var t = Object.defineProperty,
  r = e((n, o) => t(n, 'name', { value: o, configurable: !0 }), '__name');
const i = r(() => {}, 'devOnlyClosure');
function u() {}
e(u, 'devOnlyFunction');
r(u, 'devOnlyFunction');
function c() {
  console.log('imagine 10,000 lines of code');
}
e(c, 'thisFunctionIsNeverCalled');
r(c, 'thisFunctionIsNeverCalled');
i();

What is unexpected:

  1. devOnlyClosure has been correctly transformed into an empty closure but still remains
  2. The call to devOnlyClosure hasn't been removed
  3. devOnlyFunction has been correctly transformed into an empty function but still remains
  4. thisFunctionIsNeverCalled is never called but still remains
  5. the functions have their .name assigned twice

What is strange:

  • the call to devOnlyFunction was removed, but devOnlyClosure wasn't
  • thisClosureIsNeverCalled was removed, but thisFunctionIsNeverCalled wasn't
  • functions get double .name assignment, but closures only get one
  • if functions.ts is renamed to be a javascript file functions.js, then production build returns empty correctly
  • if esbuild.keepNames is turned off, then production build returns empty correctly

What I suspect is happening is the typescript file is fed through esbuild transform, then after rollup has created the bundle, it is fed through esbuild again to minify. This is why there is a double .name assignment.

Reproduction

https://stackblitz.com/edit/vitejs-vite-79hhqf?file=dist/assets/index.70f295b1.js

System Info

System:
    OS: Linux 5.0 undefined
    CPU: (4) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
    Memory: 0 Bytes / 0 Bytes
    Shell: 1.0 - /bin/jsh
  Binaries:
    Node: 16.14.2 - /usr/local/bin/node
    Yarn: 1.22.10 - /bin/yarn
    npm: 7.17.0 - /bin/npm
  npmPackages:
    vite: 3.0.0 => 3.0.0

Used Package Manager

npm

Logs

No response

Validations

@sapphi-red sapphi-red added the p3-minor-bug 🔨 An edge case that only affects very specific usage (priority) label Jul 17, 2022
@github-actions github-actions bot locked and limited conversation to collaborators Aug 1, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
p3-minor-bug 🔨 An edge case that only affects very specific usage (priority)
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants