Hacker News new | ask | show | jobs
by cjpearson 723 days ago
The old joke is that there's a new JavaScript framework every month. That's not really true — we've had the same big three for a decade — but there has been an explosion of new bundlers: vite, esbuild, turbopack, farm, swc, rome/biome, rspack, rolldown, mako. And of course plenty of projects are still using rollup and webpack.

Some competition is a good thing, and it seems to have led to a drive for performance in all these projects which I'm not complaining about, but I wonder if more could be gained by working together. Does every major company or framework need their own bundler?

4 comments

> The old joke is that there's a new JavaScript framework every month. That's not really true — we've had the same big three for a decade

Yup. I know a few people who were using React 10 years ago and still use it today. What has changed frequently is the tooling. e.g. Bower going away in favor of NPM; Gulp/Grunt going away in favor of Webpack, which is slowly going away in favor of Vite; CoffeeScript going away in favor of TypeScript; AMD/CJS/UMD going away in favor of ES modules, and so on.

ClojureScript has a great deal of stability in both the language itself and tooling, but nowadays I can't give up the developer experience of TypeScript and Vite. The churn in the tooling of the JS/TS ecosystem is wild, but since about 2021 I have found ESM + TypeScript + Vite to provide fast compile times, fearless refactoring, and a similar level of hot-reloading that I enjoyed in Clojure(Script). Can't say I miss Webpack, though!

> ClojureScript has a great deal of stability in both the language itself and tooling

Does it still use Google's Closure (they've chosen it just for the name, right?) compiler? Is that still supported by Google?

Major parts of the compiler have been unchanged since its original public release. It still uses Google Closure Compiler (GCC), but the community understands that was the wrong choice of technology in retrospect. The compiler is still actively developed and used internally by Google. What is going away is the Google Closure Library (GCL), since modern JavaScript now has most of what GCL offered, and it's become easier to consume third party libraries that offer the rest of GCL's functionality.

The reason ClojureScript has not moved away from GCC has to do with the fact it performs optimizations -- like inlining, peephole ops, object pruning, etc. -- that ensure ClojureScript's compiler output becomes relatively fast JavaScript code. The closest alternative to GCC's full-program optimization would be Uglify-JS, but it doesn't perform nearly as much optimizations as GCC does.

For a concrete example, consider the following code. I am intentionally using raw JS values so that the JS output is minimal and can be pasted easily.

  (ns cljs.user)

  (defn f [x]
    (let [foo 42
          bar (- foo x)
          baz (+ foo bar)]
      #js {:bar bar
           :baz baz}))

  (defn g [x]
    (let [result (f x)]
      (when (pos? (.-bar result))
        (js/console.log "It works"))))

  (g 0)
The ClojureScript compiler will compile this code to something like this

  var cljs = cljs || {};
  cljs.user = cljs.user || {};
  cljs.user.f = (function cljs$user$f(x){
    var foo = (42);
    var bar = (foo - x);
    var baz = (foo + bar);
    return ({"bar": bar, "baz": baz});
  });
  cljs.user.g = (function cljs$user$g(x){
    var result = cljs.user.f.call(null,x);
    if((result.bar > (0))){
      return console.log("It works");
    } else {
      return null;
    }
  });
  cljs.user.g.call(null,(0));
Paste this into `npx google-closure-compiler -O ADVANCED` and the output is simply

  console.log("It works");
On the other hand, `npx uglify-js --compress unsafe` gives us

  var cljs=cljs||{};cljs.user=cljs.user||{},cljs.user.f=function(x){x=42-x;return{bar:x,baz:42+x}},cljs.user.g=function(x){return 0<cljs.user.f.call(null,x).bar?console.log("It works"):null},cljs.user.g.call(null,0);
This is quite larger, and possibly slower, than the output of GCC.
Thanks for your reply! Btw. my question was really out of interest and not to criticise ClojureScript.
You're welcome. I am not sure why you were downvoted, but I think your question was valid.

My response can be summarized as follows:

- Google indeed uses and supports the compiler

- Google is moving away from the library that shipped with their compiler

- ClojureScript made a wrong bet on technology

- The design of ClojureScript necessitates the full-program optimization of Google's compiler

Haven't you heard ? Rebuilding everything in rust is the new meta. To be quite honest, call me old fashioned but the fact we need so many bundlers that we are considering which are more performant is a symptom and and not a blessing.
For me is the fact that we need a bundler is the underlying issue. I would love that bundlers became first class citizens and come already with the Javascript runtime, similar on how Bun and in some degree Deno does (AFAIK their bundler is intended to use to bundle apps to use in the server and not in the browser).
Or change the specs of ES/JS to introduce types. It will eliminate use of many projects and even typescript.

Seems like something to bring to WinterCG ? [1]

[1]https://wintercg.org/

That was the initial promise of dart when it was first release but somehow it never got really there
Aren't we doing the same with compilers?
I would say not really, at least compilers are an essential component of a compiled language in my eyes. Javascript is transpiled, and I know you can say the same for all compiled also in a roundabout way.

Thinking about it only recently, Go fits in nicely with fast compile times for ' 'builders' esbuild comes to mind. But Rust.. Crazy

By all of them being written in Rust they could reuse other's packages (crates), AFAIK the vite team is writing rolldown (to replace rollup) and they are using crates from the oxc project, not sure about the others.
You forgot Parcel, which is working on v3 https://parceljs.org/