What is not so great is that Google's closure team (not be confused with clojure) decided to remove various functions, making breaking changes - for no obvious reasons other than saving a few lines of code.
Example Things like `goog.isArray` is gone, a library that was adopted by many (including the CLJS compiler) to help smooth out the differences in JS versions and supported features.
The closure team even has great advice for you:
"goog.isArray has been deleted. Use Array.isArray instead."
Well, how about you just delegate to that, Google team, and I can just upgrade?
This kind of library maintenance is what keeps me away from JS/TS where prior investments seem to be less valuable:
React deprecating lifecycle methods, Typescript's breaking changes page is pretty long (but admittedly, being MSFT, they try to care about backward compatibility), Vue.js 3: functional components deprecated, manual changes required.
Who can afford these shenanigans?
Changes in re-frame, reagent etc. have been a lot more careful. Not quite perfect (looking at you Reagent 1.0!), but I'm sleeping much better working with a stable, slow-moving framework - at the cost of maybe a few more repaints.
Cljs never should have been built on top of closure.
There's also a reason SemVer exists, to notify you to the fact of breaking changes (whether the library maintainers actually abide by the correct usage is another conversation).
Don't want breaking changes? Dont upgrade your stuff, sounds easy to me.
Semver is not an excuse to break your clients.
The reason given was "code size and keeping the API surface small".
Both are bogus, especially since this is part of an optimizing compiler who will REMOVE unused code.
Leaving simple forward from goog.isArray to Array.isArray in there does not cost any maintenance, does not mean extra tests (you already have those) and does not mean your API surface is overblown.
It felt really exciting because of the cross pollination that was happening between the two languages, Redux felt very familiar, and we have re-frame for clojurescript.
There was a ton of promise with Apollo.js and an improvement on the `connect` functionality by upgrading to a proper query language for getting state into a component versus wrapping functions around multiple `state.some.path` `state.some.other.path`.
David Nolen built om.next around that very idea, it was basically Apollo.js lite, and it was very exciting scientifically but never quite caught on because maybe it was a little clunky. But using datomic pull query syntax to fetch state for use in a component was thrilling. (if you got this far and decided you hate me and your eyes are rolling so hard I get it lol)
And this was all years ago now. All that excitement and progress and effort seems to have been trapped inside of Typescript, and React hooks, and did everyone forget?
I'm not actively involved with CLJS development anymore but last I checked that still continued, with tools like figwheel/deps.edn/shadow-cljs all sort of doing similar things differently, and there being good-but-not-as-good-as-clojure support in different editors like emacs, intellij and vscode. Similarly, there were a number of different, but still alpha quality ways, to use cljs with react native, all suffering from some major pain points.
Cursive is really good at handling cljs too, with jump-to-definition and refactoring without using a REPL
I found this to be a major timesink when debugging things, and never came up with a good bulletproof solution to automate this traversal. It was especially painful with random breakages due to NPM's automatic dependency/transitive dependency upgrades due to version ranges (ie, things that don't just fix themselves by checking out a previous known good version).
I think Om.Next was just a collection of a few, rather conceptual, abstract objectives, quite experimental (perhaps even ahead of their time) and untested in production.
Too bad that Cognitect couldn't give David Nolen a carte-blanche and let him work on it 100% of his work time.
I'd rather live in a world where libraries like Om.Next become popular, and not stuff like Angular.
ps.: I used Angular. And I loved it. Angular made sense. Sometime around 2009-2010. But it stopped making sense. And I stopped liking it. You still can build awesome things with it, and people still do. And I still don't like it.
Personally I find it harder and harder these days to justify writing code that doesn't have static types. Even for personal projects, if I'm writing more than 100 lines, I want editor checks and standardized documentation. Particularly when I'm not doing anything wildly novel, and particularly (but not exclusively) for larger projects.
It's not hard for me to imagine industry reaching a similar conclusion, especially when the novelty of most of the web apps being cranked out tends to be lower, and the scale tends to be larger.
And where industry goes, hobbyists tend to go so that they get to put relevant stuff on their resume (not to mention paid employees who release in-house tooling and libraries as open source).
Spec is for specification which can be used for more things than precompile problem checking
Clj-kondo is for precompile static analysis that also supports minimal typing
On the ClojureScript side, I would like to see more projects integrating with platforms like Nextjs and Gatsby.
The hard part is that most Clojure devs default to using the JVM server side so there’s not much appetite there to do the work to embrace JS server side frameworks.
But you're right, for most "serious" projects, people tend to reach for the JVM. Yet, I think a strong ClojureScript presence on the JAMstack would benefit beginners a lot.
Clojurescript is dynamic, beside the lisp syntax which is arguably cleaner, and offer some nice advantages like homoiconicity
What is the real advantage of Clojurescript (?)
Clojurescript has the best client-side build tool I have used in https://shadow-cljs.github.io/docs/UsersGuide.html and everyone uses it.
Clojurescript targets/outputs Google Closure compatible code which is easily the most sophisticated JS compiler out there. The reason no one uses it is because writing compatible code by hand is a nightmare.
Clojurescript's front end libraries are incredible, they are basically a better expression of Redux because the Clojure language has constructs that enable a more expressive API https://day8.github.io/re-frame/re-frame/
It has everything you need and gets rid of most of the stuff that enables people to write bad code. (Assuming you like functional programming, of course)
>because the standard clojurescript library has everything+
My favourite "type checker" is clj-kondo
I needed a debounce the other which was just importing
`[goog.functions :refer [debounce]]`
Reagent and re-frame have been awesome since Day 1, even as react has tried to play catch-up with hooks etc.
I would not use local state apart from fine-grained performance optimizations or temporary, always-can-be-thrown-away state specific to the component itself.
Example: email field input before passing validation.
Also because of immutable data structures it has a very clean comparison semantics e.g. you can compare data structures by value with `=` which helps a lot in React-like environments.
The absence of static typing enables you to write more general code with less effort. All that leads to simple, clean and compact code. If you check Real World App statistics  you'll see that Clojurescript/Re-frame implementation has the fewest LOC (almost 4x less than Elm and 3x less than Purescript).
Typescript is probably a better fit for most people doing most things.
IMO. Interactive development. It allows you to connect to a running program (local or remote) and tweak things on the fly. Without even affecting the state of the program. Without even having to save or re-compile. It's hard to explain the benefits of that approach. One has to experience it.
Most things this person says in every thread about Clojure are false.
Hobbyist/toy project - sure, using shadow-cljs you can do your front end entirely in ClojureScript and make calls out to whatever backend you want
Professional project with ClojureScript backend - sure, you can use shadow-cljs to target both node (using :node target) and the browser which will allow you to utilize ClojureScript for full stack and not have to rely on Clojure
Professional Project with non-clojure(script) backend - no. It would not be worth it to spend resources to learn clojurescript (talent pool of existing clojure devs is small) and not taking advantage of full stack clojure(script) can be detrimental
Allow me to offer a contradicting point of view. On my last project we used Elixir on the backend and Clojurescript (with re-frame) on the frontend.
So yeah, if it's a new project in my opinion it is worth exploring Clojurescript, even if you don't plan on using Clojure.
We could not have done half the things we did without ClojureScript on the front end.
Also, the learning curve is not very steep if you're just doing a re-frame front ends. You really just need the basic 1/3 of Clojure, and rarely if ever touch all the complex parts.
Would probably have been the same boost in productivity if you had chosen TypeScript though. And choosing TypeScript obviously comes with numerous benefits (large pool of developers, ecosystem, first-class integration in VSCode, backed and highly maintained by Microsoft, etc).
Nope. It wouldn't. You can replace "Typescript" in your sentence with pretty much any other "-script" thing: Coffescript, ScalaJS, KotlinJS, etc., and it still wouldn't be closer to the truth.
The biggest advantage of Clojurescript is out-of-the-box support for interactive development. You are connected to your running application. And without any ceremony, without re-compiling or even saving anything on the disk, you can tweak the program without resetting the state of it. If you have never experienced that first hand, it would feel like it's not a big deal. Alas, it really is.
Clojurescript right now (at least for me personally) is the fastest way to prototype anything for the browser. Building things like web-scrapers feels like magic. You just run the program, connect to it and keep experimenting with things until you get the results you want. No other language ecosystem today gives you that liberating feeling. Almost everything else feels too formal and bureaucratic - can't do "this" without "that". It becomes pretty tedious and often removes "the fun" from programming.
So, yes, I attest to that - Clojurescript can give you incredible productivity boost.
I'd pick CLJS over JS but not over TS.
On the backend, I'd pick Clojure over both JS and TS in a heartbeat, though.
For example, you can build a suite of specs that denote a ledger - where amounts in every transaction depend on each other. That is not a trivial task - most other type-systems don't give you good instruments to achieve something like that.
You can then use those specs to generate data for property-based tests.
You can also use them to validate the data flow in the back-end for different data stores. And re-use the same specs on the front-end for input validation. Clojure and Clojurescript allow you to get as much code-reuse as possible (even though the code has to run in completely different environments).
> I don't feel the need to reload a bunch of times because everything usually works on the first try.
Tomorrow perhaps something better comes up. But Typescript today is not an option for me. I have tried it multiple times in multiple projects. "Joy of Typescript" doesn't even sound right. "Joy of Clojure" though is a thing. People love Clojure and Clojurescript, and not without good reasons.
Based on my experience, no, it's definitely not the same boost. Elm felt more productive than Typescript, and Clojurescript felt more productive than Elm.