Hacker News new | ask | show | jobs
by koito17 720 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

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!

1 comments

> 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