I’m pretty happy so far with my understanding of Elixir; however, I also do a lot of front-end web development and I decided to shed my reservations and approach it from an engineering point of view.
I was surprised to see that a lot of Elixir is quite similar to Clojure if you ignore the superficial syntax differences. It also seems that the Clojure(script) community attracts quite experienced developers that are trying to “push the envelope” on software development.
I am at the book reading stage but so far my thoughts on ClojureScript specifically is that it’s a quite cool language with some maturity and good community & tooling: FigWheel gives you excellent in-browser reloading (without actually refreshing the page every time), connect your browser to a REPL, wrappers on top of React and some nice shortcuts to generate HTML (Hiccup) and many other smaller good vibes.
Are there any ClojureScript users on this forum? Has anyone combined an Elixir-backed server with ClojureScript on the front-end? Thoughts?
I’ve not used clojurescript before, but if you are curious, there is a clojure->beam compiler if you want to program in clojure but run it on the beam (they’d interact fine with elixir, just not the macro’s, but considering clojure has much more powerful macro’s than elixir, meh… ^.^):
It’s still fairly new but being actively worked on.
Been there, done that - eventually I hit a complexity ceiling that makes me want to tear my hair out. For some time with ES2015 I thought it would be better, but it’s really not. And of course they keep piling syntax onto the language, instead of adding a sane stdlib.
Again, complexity. You can’t avoid working with a live DOM at some point (e.g. you want to upload a file asynchronously, render an image locally, parse text from the client, use a Rich Text Editor and so on).
If I would use VueJS, I would use it from ClojureScript, the same way that the ClojureScript community has embraced React and produced numerous wrappers and additions to it, to make it feel Clojure-y and work with their immutable collections.
Immaturity (it’s a very new thing). I don’t want to be a trailblazer (I just don’t have the budget )
It’s under consideration, but it doesn’t seem to have a community as cohesive and active as ClojureScript. I think this will change as Reason stabilises and attracts more people to the ecosystem.
Too restrictive, and JS interop from what I hear is a bit iffy - which is unfortunate. I think if I wanted to use a restrictive type-based compiler I’d go with OCaml/BuckleScript since it’s 20 years old and fast
ClojureScript has a large community built up, it generates crazy-efficient code, and the lisp-macro’s (it is a Lisp after all) are beyond compare, allowing you to build things with less and more readable code than you can do in anything else.
However, you do have to deal with lisp, JVM, the building infrastructure, etc… ^.^;
Haha, I think to me the upside is that I will finally push myself to learn Lisp properly. I learned enough 9 years ago to write some ELisp for Emacs, then forgot all about it. The syntax is easy to learn though
I cut my teeth on the JVM 15 years ago (Java 1.4 was a big deal back then) so it’s funny using Java again after such a long time.
It’s funny that nobody cares about Dart - I tried it briefly and it feels like Python for the web; sane, dynamic, familiar syntax, batteries included, uses Closure under the hood for fast and compatible code… and it will gain a “strong” mode soon that will give it a sound type system. The only problem is that you’re at the mercy of Google for getting updates, but they seem to run the Adwords UI on it now - they claim it’s 70B of revenue every year, so it’s probably not going to go away any time soon…
Can generate. Last time I spent time with it the whole persistent data structure thing was a bit at odds with how JS garbage collection worked (it can make lots of garbage), and there were inefficiencies about things being made into seqs only to be transformed back into other things, etc. As I understand the situation has improved some since then, and you can always make abstractions on top of plain js objects.
I’d count the dependency on the Closure compiler as a big win. It’s got really excellent dead code elimination and rewriting, and a bunch of useful functionality built in for everything from data structures to common things like messing with the dom. It’s even got a good book. As I remember, it’s also a big part of things like Gmail and other big Google properties, so probably not going away any time soon.
I’m not knocking the capability of the tool but I do question the culture that gave rise to it’s development. It gives me the impression that Google decided to attempt to make frontend development more “Java-developer friendly” rather than to encourage their developers to engage web development on its own terms and become competent in web development in general (the whole “child proofing the world” vs. “world proofing the child” kind of issue).
(Fiddled with some of the early om.next stuff - but not enough to form any kind of opinion about it.)
While I liked Clojure, ClojureScript felt much more fragmented. Anyway all of this is just my opinion - as usual YMMV.
Thanks for sharing your experience. It seems though that the ClojureScript community has greatly improved their tooling and interop story in the past year or so, which what triggered me to re-evaluate them.
A minor nitpick - Closure Compiler is not the same as the Closure Library. The first one is an advanced transpiler (that targets ES3, making it one of the best ways to serve people with old devices and browsers). The latter is a “standard library” for the web, including a lot of UI components.
Aggressive code minification
I’m fully aware of that. In fact lots of projects use the Closure Compiler or at least give you the option of doing so because it is so good at what it does. However a year or so ago a lot of the ClojureScript resources available (not related to Reagent or Om) would showcase code that goes straight to goog.events and goog.dom for the usual interactions with the browser, making the Closure Library seem to be the de facto standard. And there is some incentive to use the Closure Library because:
The Closure Library is server-agnostic, and is intended for use with the Closure Compiler.
In 2009 I happily used jQuery so I didn’t have to deal with cross-browser issues. But now in late 2017 I view jQuery as much less relevant - in fact it seems that projects now often have to remove any dependency to jQuery in order to continue to attract new adopters (and contributors). So when it comes to adopting ClojureScript in late 2017 it’s typical dependencies (even when they are optional) need to stand up to similar scrutiny. Now it makes sense for Google to stick with Closure Tools given how heavily they have invested in it - but that doesn’t mean it’s a good idea for non-Google entities to adopt it or something that potentially depends on it in late 2017.
ClojureScript is fantastic. You’ll likely want to pick a client side library to use. There are a few now–several based around REACT. I built my first app using Om. I wouldn’t again. Things get complicated too fast and it likes to be monolithic. I don’t know where Om.next is, as I haven’t been following it, but might be worth looking at. I built the second significant app using re-frame. It’s cool and made writing a REACT-type app much simpler than I found Om to do. The library I prefer now is not REACT-based. It’s called “Hoplon” and it gets so much right. It’s not popular, but it has smart and passionate people behind it (the guys who wrote Boot). Check it out at http://hoplon.io Even if you never use Hoplon, definitely look at Javelin, which it uses, and its whole cell metaphor. You can use it separately (it’s a separate library developed for and used by Hoplon).
Just spotted thread but I thought I’d chime in on my experience with combining Elixir and ClojureScript - I’ve been working on a few apps using re-frame in the browser, talking to Elixir with both JSON endpoints and lately some stuff with channels and Phoenix Presence too.
I personally have found it one of the most productive and enjoyable environments in which to do front end web development. As you mention, Figwheel live reloading on the front end keeps you direcly in the part of the app you’re changing without restarting every time, Phoenix hot reloading in the back end make for really speedy iteration, although it’s a slight brain twister switching between the 2 languages syntax wise but at least both sides have a functional and immutable basis.
I find ClojureScript in the browser is a pretty pragmatic choice, you get great interop with existing libraries if you need them, plus a great selection of Clojurescript ones. Reagent (the React wrapper underneath Re-Frame) plays really well with existing JS React component libraries if you need them, and Re-Frame is reasonably similar to the Elm architecture which I’ve found to be a great way to structure single page apps. Thinking back to previous work I’ve done using Angular for example… what a struggle that was in comparison.
I’m locking onto re-frame as well, it seems extremely well documented and pragmatic.
Did you find any particular difficulties in combining the Phoenix with ClojureScript? I would assume that the watch command for Phoenix would launch your figwheel repl, and then at release time you’d have to make sure your assets are stored under priv/.
I wonder though how do you make sure that during development you get served the API from Phoenix and frontend from Figwheel? Do you just use the Figwheel server and ensure that Phoenix can do CORS requests? Or some kind of proxying to avoid the CORS complications?
I have found so far that in many cases only the syntax differs, and the logic between the two is almost identical (at least when using the various collections).
My approach is to keep the ClojureScript front end and Elixir projects separate repos and don’t try to combine the build process at all. I’ve tried the CORS approach where the browser connects to Figwheel and then the clojurescript code calls to the API routes on the Phoenix port, but my favourite approach during development is to use an http proxy. There are also various flags with figwheel to tell it to inject its websocket link as URL that’s not just ‘localhost’ - sometimes I need that if I’m testing the front end directly on a phone served up from my laptop.
For development I either use Traefik and forward just the /api route to the phoenix back end, and everything else to the Figwheel port. Traefik supports websockets nicely so it works well for Phoenix channels as well as the figwheel connection.
If you don’t need websockets to Phoenix, then a simple alternative is a node http proxy:
That listens on port 9001 and forwards /api to your phoenix server, everything else goes to port 3453 which is where Figwheel is listening (I tend to have quite a few figwheels running for various projects so it’s on a non-default port…).
With that command you can add extra routes to various other endpoints, for example, I have a few routes for password reset forms etc that are normal Phoenix html templates that get forwarded on too.
For production I use nginx to do the reverse proxying, with the production build of the re-frame app served from a separate directory, and the /api route forwarded to a release of the Phoenix application. But you could definitely package the compiled cljs and serve it as static assets from Phoenix.
As to the 2 languages… it’s sometimes a pain how the various collection / enum functions are “the same but different”, usually something like the ordering of the various parameters to map and the accumulator for example but nothing too bad, and occasionally one language is missing a function that the other has. Keeps you on your toes!