js interop in Clojurescript is dead simple. Moreover, you can have shared logic between different runtimes. The promise of Nodejs for code re-use, in practice turned out to be not as straightforward, even though you have js runtime in both places. With Clojurescript, you can have the shared logic in the same namespace - it's mindblowing, you can have functions that work on both - JVM and JS.
> it's mindblowing, you can have functions that work on both - JVM and JS
Thats basically what you could do long before Nodejs (that made server/client code sharing popular) came out in Haxe. You could target a huge number of targets from a single codebase.
The Clojurescript way isn't about transpiling between different compile-to-JS languages. It's simpler: write once in Clojure, compile to both JVM and JS directly. No intermediate language chains needed. And you are free to use whatever js and java libs directly.
Yes, sure - valid point about Haxe, you're right, it actually did this before Clojurescript or even before Node existed. IIRC Haxe could compile a single codebase to multiple targets. That multi-target approach tho required writing in a lowest-common-denominator lang. Cljs practical in the sense that you get the full power of Clojure on the JVM side and reasonable JS semantics on front-end - without compromise. Haxe often meant sacrificing language features to stay compatible across all targets.
Clojurescript is surprisingly pragmatic in that sense and works well. The downside - you can use Cljs on its own, but it truly shines when paired with Clojure, but JVM, despite being amazing piece of tech has a marketing problem - people hear JVM and immediately think Java.