Preferences

I wonder why tree-shaking wasn't always the default for, say, JS bundlers. If a compiler/analyzer knows what the entry point of a program is, as well as any symbols it exports to the outside world, isn't it relatively simple to figure out what's not being used?

I could be misunderstanding something.


Couple of weird language edge cases

JS allows functions to by called by name.

A.foo();

Can be

A["foo"]()

Because foo is now a string it's possible to add levels of indirection.

Action(name) { A[name](); }

It's possible the list of actions to perform are sent to the client as data.

This amiguity has left enough doubt for most tools, and people making tree shaking a practice on code not commonly performed. The longer that happens the scarier it becomes to start investigating.

Since the browser will tree shake for you the incentive to cleanup your source is also less important.

But in this case A is exported. No one is going to tree shake methods of a class.
It doesn't need to be a class; that's a detail:

  function foo() { ... }
  var callthis = "foo"
  window[callthis]()
And this is true for any object; attaching functions to objects is kinda common.

And of course, "callthis" is usually defined in a much more complex way, such as if (user_input_is_this) callthis = "foo" else callthis = "bar". Or what about callthis = "foo"; callthis += "_bar"?

In general this kind of stuff is tricky in dynamic languages (and also in static languages once you start using reflection); JavaScript isn't really an exception here. You really need to have a deep understanding of the code and logic to truly be certain that something will never be called.

> [...] Often contrasted with traditional single-library dead code elimination techniques common to minifiers, tree shaking eliminates unused functions from across the bundle by starting at the entry point and only including functions that may be executed.

Assuming, that methods of classes count as "function" in the terminology of that wiki page, then it seems to say methods of a class are shaken out. If they are not seen as functions (again, in that terminology), then I guess not.

I think the article is over-simplifying, I believe most tree-shaking is done at the `import`/`export` boundaries.

Code that isn't used locally in a module and is not imported by any other modules is omitted.

---

It helps that there isn't a global object for the local module scope, otherwise in-module dead code detection would also not be possible, since any line of code within it could use dynamic access and static analysis wouldn't be able to prove that it isn't used.

Dead code elimination is only straightforward if your language has sane naming semantics (lexical scope, static name resolution, etc). If your language does crazy stuff like allowing function lookup by the string representation of its name in the source code (e.g. JavaScript) it becomes much harder.
Which is why Google's jscompiler requires a stricter subset of JS for "advanced optimizations" including dead code elimination.
C allows you to call functions by string...

C++ also allows it, but the function names are a bit harder to guess.

> C allows you to call functions by string

please elaborate

Possibly OP meant dlopen/dlsym on itself? But that's a stretch, and not really language feature...
And functions aren't guaranteed to be included in the binary unless you pass additional compiler flags with that strategy.
Very few things are guaranteed in C. If you want to guarantee the function exists let the operating system look up the function names by string for you.
Create a string, look up the address of a function in the library. Assign the address to a function pointer, call it.
I think tree-shaking will be a default in new JS bundler. ESbuild seem to enable it by default: https://esbuild.github.io/

I think the reason some other bundlers like webpack didn't/don't have it by default is because tree-shaking became popular after they were invented and tree-shaking was added to the bundler later on as an extra nice-to-have feature.

It seems webpack has built-in support for tree-shaking from version 2. Latest version of webpack might have it enabled by default (not 100% sure but possible) https://webpack.js.org/guides/tree-shaking/

This item has no comments currently.

Keyboard Shortcuts

Story Lists

j
Next story
k
Previous story
Shift+j
Last story
Shift+k
First story
o Enter
Go to story URL
c
Go to comments
u
Go to author

Navigation

Shift+t
Go to top stories
Shift+n
Go to new stories
Shift+b
Go to best stories
Shift+a
Go to Ask HN
Shift+s
Go to Show HN

Miscellaneous

?
Show this modal