-
-
Notifications
You must be signed in to change notification settings - Fork 22
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
Investigate tree-shaking #24
Comments
@thheller I haven't looked into the esm build implementation that closely yet, but maybe this rings any bells? |
Regular JS tree-shaking is very limited. It is not comparable to the Closure Compiler The So, for exports it does this and the final JS output it generates looks something like:
Where part of the The regular JS tree-shaking doesn't recognize this and as such doesn't eliminate anything. |
Makes sense. |
This might be a hack, but it seemed to work. Invoking the google closure compile once again:
Instead of 300kb we now end up with 160kb. |
Perhaps we can do some rewriting manually on the outputted cherry/cljs.core ES6 module as a one time hack on the Closure output. A nice research project of its own which is fairly isolated. If anyone wants to investigate this, help is welcome! |
I did some research and found a pretty comprehensive comment on this topic from Evan Wallace, who wrote esbuild (I also found a related comment). Long story short, the optimizations that Closure Compiler does, by looking at object properties and rewriting/eliminating the ones that aren't used, are considered to be unsafe and inherently problematic, and in general tools such as esbuild or Terser do more conservative static analysis, and this kind of analysis and minimization works well for basically all JS code that isn't written in Closure Compiler's format. Another point of consideration is that all of the current minimization tools (including the two above) are basically on par or sometimes slightly better at minimizing JS code than Closure Compiler based on this benchmark. With these in mind, and since cherry is targeting a more standard ES6 output, I would say that it's probably worthwhile to rewrite |
@jo-sm Thanks. Yes, rewriting the Closure output is probably the best idea. That, or bootstrapping core itself with cherry (which will be more work but maybe in the future, attainable). |
(Or hacking Closure) |
I would guess that for the short term rewriting makes sense, but it depends on how simple/complex/feasible bootstrapping in Cherry is. Do you think it makes sense to automate it, and if so, is it fine to hardcode some of the things based on the output generated by shadow (e.g. I noticed that there is |
@jo-sm Yes, it will take a long time before we're able to fully bootstrap, if we will ever get there: it depends on if it's worth pursuing as well. So for now, the rewriting strategy seems good. You can probably get some insights using |
I have to strongly disagree here. The JS tools are not even remotely close. One big caveat of course is that you only get the full benefit if you have code that was written with Another huge caveat is of course the flexibility you lose. Sometimes its not worth losing that, especially when publishing libraries that then run through another build tool again. Of course the unsafe part is true, thats why externs are sometimes an issue still.
shadow-cljs uses the This is actually just using the |
We can agree to disagree 🙂 At the risk of making the thread go into the rabbit hole of GCC discussion: Yes it's not running benchmarks against big projects, but it's running benchmarks against nontrivial JS code (these libraries are large, including ones like With all this in mind I'll look at rewriting |
If you want to discuss GCC vs other tools, you can open a discussion here. |
That is missing the point. The point of this thread and my comment is tree-shaking or dead code elimination, ie. removing unused code. When minifying libraries on their own this obviously cannot be done. It can't know what the consumer is going to use, so it has to keep everything. So, you are really just minifying. We agree that the Closure Compiler is an average (and slow) minifier compared to the alternatives. That is what the benchmark you linked is testing. It is not testing tree-shaking or DCE, which is sort of what If you are fine with just minifying just use |
I think it's a good discussion to have, but let's continue here: #36 |
Hmm, I'm having trouble running |
@jo-sm You probably just need to upgrade bb. |
BTW just to give a quick update: I worked on it a bit a while back but had to drop it to deal with other things going on (for now, at least). I would like to pick it back up and finish my prototype, but basically what I did was to perform a few operations:
I was also doing this in TypeScript because working with the JS AST is otherwise a huge pain (it still kind of is, but TS makes it much easier to work with and makes me feel more confident because of the complexity of the JS AST). It was still a bit buggy when I worked on it a few weeks ago, but I was able to kind of get proper dead code elimination working. |
@jo-sm Very interesting and hopeful! I'd love to see continued work on this. |
When using only one function from cherry/cljs.core.js, e.g.
js-keys
, and then processing this with a treeshaker like esbuild or ncc, it seems that it's still pulling in the entire package.Repro:
index.mjs:
shell:
Output:
The text was updated successfully, but these errors were encountered: