Clojure & ClojureScript?

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.

First order of the day is to find a good “compiles-to-Javascript” language with a decent standard library. The candidates so far are Dart, ClojureScript and Reason/OCaml/BuckleScript. There have been quite a lot of discussions about the OCaml stack here, but much less so about Clojure and ClojureScript.

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?

4 Likes

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. :slight_smile:

Plus of course there is the more erlang-geared LFE if you don’t need the ‘to javascript’ part. ^.^;
http://lfe.io

5 Likes

Why would you use ClojureScript instead of:

(I’d probably use the above in that order/of complexity)

3 Likes

I’ve seen that - the “to javascript” part is what I’m after though - but still it might make sense for some validation code and what not.

1 Like

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 :slight_smile: )

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 :slight_smile:

4 Likes

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. :slight_smile:

However, you do have to deal with lisp, JVM, the building infrastructure, etc… ^.^;

4 Likes

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 :slight_smile:

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…

3 Likes

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.

2 Likes

Last time I checked ClojureScript had a mission critical dependency on Google’s Closure Tools which tries really hard to make JavaScript look and behave like Java. And of course it makes sense as it makes it a lot easier to port the core Clojure code that is written in Java. That being said I’m not sure if Google has a “long-term support” schedule for Closure - it hardly has the PR of some of it’s other OSS efforts.

Unfortunately Whalesong didn’t go anywhere - that could have provided a Scheme-y/LISP-y “to JavaScript” language without undue baggage of the Java ecosystem.

1 Like

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.

4 Likes

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).

My personal exposure to ClojureScript was primarily through Mimmo Cosenza’s excellent ClojureScript tutorial - Modern ClojureScript, partially with Études for ClojureScipt and some Reagent via Web Development with Clojure 2e.

So my speculative profile of a contented Clojure programmer? A Java-refugee fed up dealing with all the accidental complexity of the ecosystem seeking improved programmer happiness. A ClojureScript programmer is probably similarly motivated but needs to work on the frontend but would rather put up with “Java-isms” (having previously already been acclimatized to them) than deal with the usual JavaScript antics.

The problem is that you tend to end up writing “Clojure” code malipulating Java OO-style libraries (i.e. Closure Library - look for :import goog.Whatever and goog.events, goog.dom, etc.) on the one hand while interacting directly with JavaScript-y stuff whenever there is something the Closure Libraries don’t cover. So often you end up juggling the Lisp-y Clojure/Java OO/JavaScript mindset all at the same time.

Reagent was my first exposure to React. I can’t recommend that experience. Now that I have dealt with React on the JavaScript level I suspect that I would be in a better position to “get” Reagent. But that would mean that to appreciate Reagent you would have to “get to know” React via JavaScript first anyway.

(Fiddled with some of the early om.next stuff - but not enough to form any kind of opinion about it.)

At least with Elm/PureScript/BuckleScript you are only juggling two worlds - the language you choose and JavaScript. But try as you might at this point I don’t think there is a true escape from (competent) JavaScript.

While I liked Clojure, ClojureScript felt much more fragmented. Anyway all of this is just my opinion - as usual YMMV.

5 Likes

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.

As per the documentation:

For ClojureScript, Google Closure provides a solution to the “library problem” for JavaScript in three distinct ways:

  • Libraries
  • Dependency management
  • Aggressive code minification

Each of these features represents thousands of hours of research, design, development, and testing. Therefore ClojureScript leverages them in its implementation, allowing the Clojure/core team and contributors to focus on enabling the power of Clojure wherever JavaScript is found.

And also:

ClojureScript is written in Clojure and ClojureScript interoperating with the Google Closure JavaScript libraries. However, ClojureScript can interoperate with any JavaScript library or framework.

(emph. theirs)

Rant starts:

Finally, in my opinion, trying to “engage web development on its own terms” in 2004 (when Gmail was launched) was impossible. Boring ES5 didn’t come along until 2009 (the ISO standard in 2011). It’s only recently that the web can be engaged on its own terms, and again it needs hundreds of thousands of engineer-hours to become a viable platform for experiences that match what native (or cross-platform) desktop platforms offered 15 years ago. And with the “always evolving” Javascript nowadays, I doubt we will ever see that.

/Rant over :slight_smile:

3 Likes

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.

“Modern ClojureScript” actually balked that trend by using a forked version of Domina instead of goog.dom and goog.events - only later succumbing to using features like goog.Uri and goog.net.XhrIo. Even back then Domina was essentially dormant so I can only speculate at the reasoning behind the choice. Maybe because Modern JavaScript: Develop and Design (the book the tutorial is based on) uses jQuery or maybe because more frontend developers are familiar with jQuery than the Closure Libraries. “Modern ClojureScript” also bypassed Hiccup which seems to be the de facto Clojure(Script) standard for expressing HTML.

While the Gmail beta was launched in 2004, Closure Tools didn’t become available to the public until 2009. By that point in time jQuery had already been fueling the a lot of frontend development since 2006. I just fail to see what “the Java mindset” embodied by Closure Tools had to contribute to frontend development - Google had the resources to develop tools to abstract away the cross-browser differences while building on the “Good Parts” of JavaScript. Now obviously Google can do whatever it wants.

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 was introduced in 2011 and back then it made sense to leverage every bit of existing technology to move forward. For Clojure it’s easy enough to accept the “JVM/Java” shining through because it has to run on the JVM anyway. But I found for that for ClojureScript these “ties to Java” get annoying rather quickly (which was more pronounced when I was referencing the Closure Libraries). In an isomorphic/universal full stack situation this may be a minor issue as you are tied to the JVM for Clojure anyway. But I remain unconvinced of the “isomorphic/universal advantage” - backend and frontend development are very different and as such probably benefit from different languages, each more suited for their particular target environment. ClojureScript’s persistent data structures are nice but in the absence of Clojure(Script)-style frontend libraries (maybe there are some now?) writing LISP Flavoured JavaScript (like (.-value (.getElementById js/document "email"))) or fiddling with Java-style JS libraries didn’t really create a compelling case for using ClojureScript on the frontend for me.

2 Likes

I recommend you to look at FSharp/Fable/Elmish, since that one is like OCaml with an even saner syntax.

If you decide for Clojure, this Book gets frequently recommended:

The pro for FSharp is the type inference which spends you type checking for free and it means less code to read and write.

I see FSharp far more readable as Clojure, while this might be a personal opinion.

For the server side, there is Websharper and a huge number of other projects. :slight_smile:

You can compile Clojure in .Net via ClojureCLR and mix it with FSharp.

Here is a huge bunch of resources for Clojure: https://github.com/matthiasn/Clojure-Resources

Clojure and FSharp are the two functional oriented languages with the highest interop, which is important imho.

Much fun :smiley:

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).

4 Likes

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.

So yeah in summary, thumbs up, give it a go!

6 Likes

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).

1 Like

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:

npm install -g http-proxy-cli

Then run:

http-proxy -p 9001 -v /api=localhost:4000/api 3453

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!

3 Likes

Wow, this is fantastic information. I will keep referring back to this thread with my discoveries as I make them :slight_smile:

Good luck with everything :slight_smile: