Even though Clojure and ClojureScript are largely identical in their semantics, their interop/build process/runtimes/tooling are very different, and quite frankly, when it comes to new user adoption, once I mention Java-on-the-server, it becomes an instant “no thanks, not interested”.
Is it time for ClojureScript to take center stage? Should the community start looking at ClojureScript/Node.js for server-side development (e.g. Macchiato) as a viable alternative to Clojure/Java?
Just some thoughts from a Clojure fan-boy who’d love to see more people using it.
Also, I don’t mean to be rude, but:
Who in their right mind would choose NodeJS over the JVM for server side programming?
Is, maybe, the kind of attitude that can alienate the millions of developers who do just that.
Maybe I should be taking a look in the mirror. If I want more people looking at ClojureScript/Node.js for server-side development, I should start promoting it to those around me as a start.
Java is still the primary choice of many, many companies – and especially “enterprise” companies. The JVM is heavily optimized for performance over the long haul. I agree with @borkdude: I cannot imagine anyone choosing NodeJS over the JVM for serious server side programming! I want multi-threading and battle-tested infrastructure, not callback hell.
I think there are people pursuing using Node and clojurescript as their backend, with the main driver being React server side rendering. (Although there are also people going the other way and using GraalVM for that).
But ClojureScript will IMO always struggle to offer the same development experience as Clojure because of the complexities and limitations of being a compile-to-js language. Clojure lives within its runtime and thus can offer the dynamic behavior of a true LISP. Clojurescript is “just” a compiler.
It’s also a very hypothetical question, a shift like that simply will not happen. What could happen is that a new project takes the lessons learned from Clojure and clojurescript and takes them in a new direction with different design goals. Either as a fork or as something brand new. That would certainly be interesting to see.
I’m curious about this. Maybe I’m missing some of the nuance in the differences between Clojure and ClojureScript, but my development experience via the REPL has been largely the same for both.
In both cases (Clojure via Clojure CLI/deps.edn , and ClojureScript via Shadow-cljs) I can connect the REPL to a running process, evaluate code in my application, and instantly see the changes. Is there something more to the experience that I’m missing?
 Thanks to Sean’s dot-clojure, which is a great reference
But you pitched your original post as an argument for ClojureScript/Node.js to replace Clojure/JVM which I think is wrong-headed: people who chose the JVM for all its benefits are simply not going to choose Node.js and therefore in parallel with encouraging JS devs to switch to cljs we should also keep up the encouragement for Java/Scala/Groovy/etc devs to switch to Clojure. In both cases, you have developers who are comfortable with their infrastructure and used to the tooling and devops around it, and “all” they need to do is trade up from their current language to Clojure/Script and keep everything else the same.
And don’t forget ClojureCLR where we can encourage C# and F# developers to switch to Clojure and still keep everything else the same!
There are also differences where Clojure is simply richer as a language than ClojureScript: Vars (as reified entities), refs, STM, agents, namespaces (distinct entities in Clojure, regular JS vars in cljs), etc per https://www.clojurescript.org/about/differences
I wouldn’t say I suggested that everyone running Clojure/JVM should stop what their doing, tear everything down, and switch to ClojureScript/Node.js. Just like I wouldn’t suggest that everyone using ClojureCLR stops using that.
I’m not an expert, but my understanding was that Clojure on JVM was a pragmatic choice, based on the dominance of Java at the time and the desire to leverage an existing ecosystem.
Is the fact that Clojure is so closely associated with the JVM a hindrance to further adoption?
I don’t have a bone to pick with the JVM. I just want more developers to try Clojure, but for many of them, the JVM is a dealbreaker, which is unfortunate.
I’d say that Clojure and ClojureScript complement each other wonderfully. Neither should or can “replace” the other. I will never write anything server-side running node when I have the option to use Clojure. ClojureScript can reach places that Clojure can’t. That was the original plan and it is working great.
I realize that most everyone here (already heavy Clojure users, and likely intimately familiar with Java/JVM) are productive and happy with the current state of affairs.
I just wanted to raise the question, would Clojure have greater adoption if ClojureScript was presented as a first-class option for server-side development?
Who says it isn’t? It is not a job of the Clojure team to promote anything. It is a community thing. Just write about how cool CLJS is and stop using the JVM as an argument or even mentioning it. In ClojureScript it certainly is not an issue and probably nobody ever wrote any Java to write ClojureScript. Maybe people just equate the JVM with Java which just completely misses the point. Anyone dismissing ClojureScript just because of the JVM probably didn’t have much interest to begin with.
Especially “younger developers” probably lack the experience to judge for themselves properly and get infected by the anti-JVM FUD more easily. If your company forbids using the JVM they probably wouldn’t allow ClojureScript in the first place either.
Getting started with Clojure(Script) is hard. The learning curve is absolutely steep. There are soo many things to learn all at once. I don’t think that the JVM is the problem we need to address (or a problem at all for that matter). I heard from enough people that were actually surprised that shadow-cljs used the JVM so it can’t be that big of a factor.
We maybe don’t express it well. CLJS is absolutely viable, we just prefer Clojure when we have the option. This however also comes from experience so it might be worth considering that this is not without reason and maybe we should talk more about why that is.
I think in terms of dollar sign, JVM is still ahead of NodeJS. And I’d be willing to bet that C# might be second or even beats the JVM, again, in terms of dollar signs. While I have no data to back this up, and actually would love it if someone had data about this, even if it shows me wrong
Anyways, I am in full support of efforts to make ClojureScript server side more viable. I also love self-hosted ClojureScript, but the issue is that the Google Closure compiler is Java based, and its JS counterpart lags behind and is still experimental and it’s not clear if Google will ever shift its focus from the Java one to the JS one.
As a full featured language, Node provides less opportunities, the platform isn’t as evolved yet, but it could catch up eventually, though maybe Node is just another JS fad soon to be replaced by Deno who knows.
With all that in mind, I think it’s best to address what some others mentioned:
What’s lacking when it comes to ClojureScript?
Why not both?
I think reach is a fundamental goal of Clojure, and that’s why Rich Hickey actually provided three implementations: Clojure, ClojureCLR and ClojureScript. And nowadays we also have a pretty solid interpreted variant Babashka (and SCI), and something that’s getting close to production ready in Magic (for Mono) and in Clojerl (for Erlang).
I love all of them and think the future is all of them. Which one will become dominant I don’t know, but a personal appeal of Clojure is that reach.
I can’t help but agree with this. JS is becoming the universal runtime, implemented by multiple large organizations with huge investments, and growing rapidly. Dismissing it seems classic innovators dilemma.
Personally, I occasionally daydream about a clojure like lang minus the java idioms, more js ecosystem native and that plugs into the denojs runtime as typescript does.