Felix Dahlke is a software developer particularly interested in games and open source. He writes most of his code in JavaScript, C++ and Python. Felix is a DZone MVB and is not an employee of DZone and has posted 16 posts at DZone. You can read more from them at their website. View Full User Profile

Settling down with ClojureScript

11.07.2011
| 3326 views |
  • submit to reddit

I recently blogged about using ClojureScript for a new internal application at work. After some initial difficulties, I’m finally up to speed with it. I thought it’s about time I shared some more insights.

Since the application we’re building offers a REST API to be consumed by multiple clients, we decided to eat our own dog food from the start and make the web frontend use the same API. So what we’re doing with ClojureScript is a pure client-side web project.

Generating HTML

Since we’re making a pure client-side application, we needed some kind of client-side templating. I didn’t feel like bothering with HTML after getting accustomed to Hiccup in Compojure, so we used the dom-helpers namespace from the TwitterBuzz ClojureScript demo. Now we can generate markup like this:

(dom/build [:div#content
            [:h1 title]
            [:div#messages
             [:div#message-input
              [:div
               [:label "Your name:"]
               [:input#author-name-input {:type "text"}]]
              [:textarea#message-textarea]
              [:button#send-button "Send message"]]
             [:div#message-list]]]))

The dom-helpers are basically a nice abstraction for Google Closure’s DOM manipulation utilities. I’m sure that ClojureScript will include something like that in the future.

Avoiding Google Closure

Knowing that amazing web applications like Google Docs use it, I really wanted to give Google Closure, which is included in ClojureScript, a chance. The utility functions are actually quite handy, but the lack of documentation makes using most parts, e.g. the UI widgets, a royal pain. Add to that the fact that it feels more like using a cumbersome Java framework than a JavaScript library, I decided to avoid it where possible. Google Closure is technically sophisticated, but lacks elegance and convenience.

Building with Leiningen

When we started to use ClojureScript, we built it from source and invoked the ClojureScript compiler from a Makefile. I can’t begin to tell you how weird this felt. Since we’re using Leiningen to build the backend, we decided to use it for the frontend as well, so I wrote a custom Leiningen plugin that performs the tasks we need, e.g. calling the ClojureScript compiler and packing the output into a WAR file. We’re not planning to release this plugin, it’s pretty hard wired towards our needs and not really thought through.

Instead, I started to contribute to lein-clojurescript, first making it work with a stable release of Leiningen. The author likes my ideas about offering multiple modes for development and production, and making the respective options configurable in the project.clj, so that’s the plugin you want to use.

Promising stuff

REPL in the browser

When ClojureScript was first announced a while ago, the REPL used Rhino for JavaScript evaluation and DOM manipulation was not possible. The ClojureScript developers have addressed that problem and made it possible to use the Browser as evaluation environment. It looks promising, but I didn’t really find the time to play around with it yet.

Compiling automatically

Compiling without optimizations is pretty fast, but manually invoking the compiler before refreshing the browser still feels wrong when doing web development. cljs-watch attempts to solve that problem by watching your ClojureScript sources, recompiling as soon as anything changes, e.g. you save a file. I trie it, but couldn’t make it work right away, so I postponed that. I guess something similar can be build into lein-clojurescript.

Problems

As I told you at the beginning of this post, I’m pretty happy with ClojureScript by now. We had to put some extra energy into setting up our development environment and build system, but now we’re up to speed. A few problems, however, remain.

No unit testing

I haven’t yet invested the time to figure out how to execute unit tests for ClojureScript code, it will probably be easier now that we build with Leiningen. This is something I’ll have to approach soon, working without tests feels really bad.

Still no release

I really don’t know why the Clojure/core folks announced ClojureScript without having a release candidate of ClojureScript ready, or even a tag. That hasn’t changed. At first, we forked the ClojureScript project on GitHub and created a tag to ensure reproducible builds. Now that we use lein-clojurescript, we use the ClojureScript version from Clojars, but that doesn’t feel much better – it’s still an arbitrary snapshot.

Conclusion

Despite the problems, ClojureScript made a very good first and second impression. It proved very stable (I didn’t come across a single compiler weirdness, of which I’ve seen plenty in GWT), which made me take languages that compile to JavaScript seriously again. Instead of whining about programmer inconvenience and immature tooling, I’ve decided to contribute, starting with lein-clojurescript. Once that’s powerful enough to replace our custom plugin, I’ll see if I can help out with ClojureScript itself, it really needs an initial release.

 

From http://ubercode.de/blog/settling-down-with-clojurescript

Published at DZone with permission of Felix Dahlke, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Amara Amjad replied on Sun, 2012/03/25 - 2:14am

Currently, lein-cljsbuild does not have any way to specify different compiler options for build versus development settings, but I’m motivated to add support for that. I’d be very interested in your thoughts on how to make it work!

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.