evanw/esbuild

Statements generated from syntax lowering or keepNames block treeshaking

Closed this issue · 3 comments

When using the transform API with syntax lowering (e.g. for classes) or with keepNames (--keep-names), the code generated often look something like this:

const _Foo = class _Foo {
};
__name(_Foo, "Foo");
__publicField(_Foo, "prop", "value");
export let Foo = _Foo;

Playground link

Because the __publicField and __name aren't marked as pure (/* @__PURE__ */), even if _Foo is unused, bundlers are not able to assume it's safe to treeshake it. Should esbuild be prepending the /* @__PURE__ */ comments to __publicField and __name?

The __publicField and __name statements are holding a value on _Foo, which prevents it from being treeshaken if the exports are unused in bundlers.


I noticed for function expressions and keepNames, e.g. with export const foo = () => {}, esbuild is already transforming it to export const _foo = /* @__PURE__ */ __name(() => {}, "foo"). This has allowed esbuild to treeshake it if unused.

Perhaps something similar can be done for non-expressions and for the lowering code.

FYI, pure annotations don't work on statements. The only way to mark the Foo as pure in your case is:

export let Foo = /* @__PURE__ */ (() => {
	const _Foo = class _Foo {
	};
	__name(_Foo, "Foo");
	__publicField(_Foo, "prop", "value");
	return _Foo;
})();

Ah that pretty much makes this feature request moot then. I don't know if esbuild is up to transforming to that way to solve the treeshaking issue, or if there's some other solution to this.

bluwy commented

Going to close this for now as the issue is kinda broad and is probably worth as a better feature request to resolve the issue generically.