I've been thinking about this a lot lately and I think you might be right. I've been using ClojureScript professionally for years, shipped some stuff with TypeScript, used GHCJS for some side-projects, and not feeling satisfied with doing front end development with any of them I spent some time catching up with new front end tech and AltJS languages over the Christmas break. Here's my highly opinionated and shallow thoughts on this matter:
* ClojureScript: This is the only AltJS language I've done real work in and used in anger, so naturally it's the one I'd complain about the most. I don't like being negative so I'll keep it short: It doesn't provide the same increase in productivity relative to the host language as Clojure does to Java. The advantages it has over ES6 fail to make up for the loss of a huge ecosystem and this only seems to get worse because of the rate big JS community innovates (whether you'd classify this as 'churn' is another matter).
* GHCJS: One of the most impressive compilers out there that target JavaScript. If you are already spoiled by Haskell and comfortable with it's semantics and runtime system definitely go for it. But if you are approaching this from the perspective of a front end developer who's looking for a better language this will feel like learning C++ just so that you can compile it with Emscripten.
I've used GHCJS to build https://github.com/osener/markup.rocks which runs Pandoc in browsers and it's certainly the best, if not only, option if you are looking to compile some existing Haskell codebase to JavaScript. My decision to stop using it has more to do with my lack of experience with Haskell than any problems with GHCJS itself. I tried to adopt so much new stuff at once with my limited Haskell experience, Reflex, GHCJS, FRP etc., and I'm having a hard time pinpointing which ones netted the increase in program robustness I've experienced (app development in JS feels so brittle in comparison) and which ones caused my lack of productivity.
After visiting this codebase after spending more than half a year without doing any Haskell GHCJS DOM APIs were revamped and I was so unfamiliar with my codebase that I didn't know where to start converting it to the new API let alone add new features. I started exploring packages like https://hackage.haskell.org/package/react-flux to see if I can take a more conservative approach with GHCJS and get the benefit of leveraging the ready-made React components out there. Unfortunately I was also very unhappy with the 26MB uncompressed JS output and wanted to add JS based renderers for stuff like Markdown and split Pandoc to its own .js file to lazily load it when it's needed. Thinking about this I realized that my main use case for GHCJS was compiling Pandoc and once I split that up I don't need to choose between two Haskell front end libraries and write the app itself using a more pragmatic stack and get some performance benefits (GHCJS produced code is especially hard on mobile browsers).
At this point I was pretty spoiled by Haskell and wanted to keep most of it while taking a more pragmatic approach. This brought me to
* Elm: I didn't know a language could provide such a good UX until I discovered Elm. From simplicity of the syntax to compiler messages, wonderful piece of work! I won't get into it's shortcomings compared to Haskell; although I can see the usefulness of additions like Typeclasses there are lots of posts from experienced Haskellers suggesting language features, and posts from Elm's designers explaining their choices not to include these. I'm not educated enough in these matters to say anything that hasn't been said before in favor of either stance.
My real suprise wasn't lack of Typeclasses; it was how unpragmatic Elm is, especially since it's not an attempt to adapt an existing language for front end development but a language designed specifically for it. I certainly applaud their goal to create a better way to write browser apps and I understand that they are in it for the long haul but I need to be productive right now and even GHCJS has a better FFI solution than Elm. When people ask how to use a JavaScript library from Elm in mailgroups and stackoverflow, their communities stance seems to be "include CSS and rewrite the JS code in Elm". This might be fine if all you need is to rewrite Bootstrap's dropdown logic in Elm but for doing real work not being able to leverage existing open source projects will quickly invalidate any productivity benefits you get from using Elm.
I love everything about Elm and I'm sure it will keep getting better & gaining mindshare but for now I can only rationalize using it in a small well contained part of a big application that lives in an island (and it is hard to find a good fit for this). Elm programmers; please standardize a better way to use native libraries and lose that 'yuck, that's unsafe' attitude against existing solutions written in JS. After publishing a complete library by writing bindings you can always rewrite it internally in Elm one function at a time.
So Elm is not for me right now. If you are still with me, I'll finally cover...
* PureScript: For some reason, during my journey through AltJS languages I've never considered PureScript before exhausting most of my options. I think this has to do with the grumpy attitude I used to have about front end development years ago when I first started doing less and less back end work. I wanted to keep all my trusted tools and always sought solutions that would let me. I liked how ClojureScript would let me use Leiningen, GHCJS would let me use Cabal etc. to build my projects. After front end development started to be something I enjoy doing rather than something I have to do, I realized I should start seeking solutions that would let me embrace tools web community has to offer and piece well-made blocks together to create web applications rather than fighting against it and living in my own island grudgingly rewriting everything. I love how PureScript is just a part of the toolstack like CoffeeScript and each .purs file produces one .js file without any runtime. On a scale from line-to-line transpilers like CoffeeScripts to beasts like Emscripten this is the sweet spot for me.
I've been using React almost since it's first incarnation and after writing a lot of CLJS/Om code I've come to realize that HTML is the best DSL to write HTML in and plain React+JSX is the best way to create views for me. Plus, all the React components I can just grab and use give a huge advantage over any 'virtual-dom' based library like Elm-HTML, Halogen. JS leaves a lot to be desired regarding app structure, error handling, side effects, business logic etc. and fortunately you can mix-and-match PureScript with JavaScript however you like. It has a FFI system that's best-in-class and semantics that are easy to reason about and won't need a big context switch when interacting with the outside world.
In fact, the approach I'm taking now doesn't require me to write the main application in PureScript with React bindings and treat the JS code to be as the 'outside world' because you can just https://github.com/ethul/purs-loader in your existing Webpack configuration and start doing require('./PurescriptModule') right away. If you are using Redux for example, you can write your Views in JS and let React+JSX do what they do best and write your Actions and Reducers in PureScript. This will give you the benefit of being able to use existing React components and concisely define browser rendering while defining your business logic & execute side effects in a safer and more expressive language.
> The advantages [ClojureScript] has over ES6 fail to make up for the loss of a huge ecosystem…
What kind of "loss of a huge ecosystem" did you have in mind?
> …and this only seems to get worse because of the rate big JS community innovates (whether you'd classify this as 'churn' is another matter).
Last time I looked at CLJS and JS, it was the JS community that was catching up with CLJS (figwheel vs hot reloading, re-frame vs redux). People like David Nolen, Bruce Hauman and Mike Fikes are doing a lot of stellar work!
One really nice thing about purescript is that it dumps out readable JS. It's a really handy aid to figuring out "So how can I use this with library X?"
* ClojureScript: This is the only AltJS language I've done real work in and used in anger, so naturally it's the one I'd complain about the most. I don't like being negative so I'll keep it short: It doesn't provide the same increase in productivity relative to the host language as Clojure does to Java. The advantages it has over ES6 fail to make up for the loss of a huge ecosystem and this only seems to get worse because of the rate big JS community innovates (whether you'd classify this as 'churn' is another matter).
* GHCJS: One of the most impressive compilers out there that target JavaScript. If you are already spoiled by Haskell and comfortable with it's semantics and runtime system definitely go for it. But if you are approaching this from the perspective of a front end developer who's looking for a better language this will feel like learning C++ just so that you can compile it with Emscripten.
I've used GHCJS to build https://github.com/osener/markup.rocks which runs Pandoc in browsers and it's certainly the best, if not only, option if you are looking to compile some existing Haskell codebase to JavaScript. My decision to stop using it has more to do with my lack of experience with Haskell than any problems with GHCJS itself. I tried to adopt so much new stuff at once with my limited Haskell experience, Reflex, GHCJS, FRP etc., and I'm having a hard time pinpointing which ones netted the increase in program robustness I've experienced (app development in JS feels so brittle in comparison) and which ones caused my lack of productivity.
After visiting this codebase after spending more than half a year without doing any Haskell GHCJS DOM APIs were revamped and I was so unfamiliar with my codebase that I didn't know where to start converting it to the new API let alone add new features. I started exploring packages like https://hackage.haskell.org/package/react-flux to see if I can take a more conservative approach with GHCJS and get the benefit of leveraging the ready-made React components out there. Unfortunately I was also very unhappy with the 26MB uncompressed JS output and wanted to add JS based renderers for stuff like Markdown and split Pandoc to its own .js file to lazily load it when it's needed. Thinking about this I realized that my main use case for GHCJS was compiling Pandoc and once I split that up I don't need to choose between two Haskell front end libraries and write the app itself using a more pragmatic stack and get some performance benefits (GHCJS produced code is especially hard on mobile browsers).
At this point I was pretty spoiled by Haskell and wanted to keep most of it while taking a more pragmatic approach. This brought me to
* Elm: I didn't know a language could provide such a good UX until I discovered Elm. From simplicity of the syntax to compiler messages, wonderful piece of work! I won't get into it's shortcomings compared to Haskell; although I can see the usefulness of additions like Typeclasses there are lots of posts from experienced Haskellers suggesting language features, and posts from Elm's designers explaining their choices not to include these. I'm not educated enough in these matters to say anything that hasn't been said before in favor of either stance.
My real suprise wasn't lack of Typeclasses; it was how unpragmatic Elm is, especially since it's not an attempt to adapt an existing language for front end development but a language designed specifically for it. I certainly applaud their goal to create a better way to write browser apps and I understand that they are in it for the long haul but I need to be productive right now and even GHCJS has a better FFI solution than Elm. When people ask how to use a JavaScript library from Elm in mailgroups and stackoverflow, their communities stance seems to be "include CSS and rewrite the JS code in Elm". This might be fine if all you need is to rewrite Bootstrap's dropdown logic in Elm but for doing real work not being able to leverage existing open source projects will quickly invalidate any productivity benefits you get from using Elm.
I love everything about Elm and I'm sure it will keep getting better & gaining mindshare but for now I can only rationalize using it in a small well contained part of a big application that lives in an island (and it is hard to find a good fit for this). Elm programmers; please standardize a better way to use native libraries and lose that 'yuck, that's unsafe' attitude against existing solutions written in JS. After publishing a complete library by writing bindings you can always rewrite it internally in Elm one function at a time.
So Elm is not for me right now. If you are still with me, I'll finally cover...
* PureScript: For some reason, during my journey through AltJS languages I've never considered PureScript before exhausting most of my options. I think this has to do with the grumpy attitude I used to have about front end development years ago when I first started doing less and less back end work. I wanted to keep all my trusted tools and always sought solutions that would let me. I liked how ClojureScript would let me use Leiningen, GHCJS would let me use Cabal etc. to build my projects. After front end development started to be something I enjoy doing rather than something I have to do, I realized I should start seeking solutions that would let me embrace tools web community has to offer and piece well-made blocks together to create web applications rather than fighting against it and living in my own island grudgingly rewriting everything. I love how PureScript is just a part of the toolstack like CoffeeScript and each .purs file produces one .js file without any runtime. On a scale from line-to-line transpilers like CoffeeScripts to beasts like Emscripten this is the sweet spot for me.
I've been using React almost since it's first incarnation and after writing a lot of CLJS/Om code I've come to realize that HTML is the best DSL to write HTML in and plain React+JSX is the best way to create views for me. Plus, all the React components I can just grab and use give a huge advantage over any 'virtual-dom' based library like Elm-HTML, Halogen. JS leaves a lot to be desired regarding app structure, error handling, side effects, business logic etc. and fortunately you can mix-and-match PureScript with JavaScript however you like. It has a FFI system that's best-in-class and semantics that are easy to reason about and won't need a big context switch when interacting with the outside world. In fact, the approach I'm taking now doesn't require me to write the main application in PureScript with React bindings and treat the JS code to be as the 'outside world' because you can just https://github.com/ethul/purs-loader in your existing Webpack configuration and start doing require('./PurescriptModule') right away. If you are using Redux for example, you can write your Views in JS and let React+JSX do what they do best and write your Actions and Reducers in PureScript. This will give you the benefit of being able to use existing React components and concisely define browser rendering while defining your business logic & execute side effects in a safer and more expressive language.