Hello, ClojureScript! (with jQuery)

I decided to give ClojureScript a try. It did not come easy, because I found the official documentation somewhat complicated. I know there is ClojureScript One, but that project also is not as simple as it could be. I don’t want fancy functionality, noir/compojure, enlive/hiccup, and tons of other semi-relevant tools. Bare simplistic HTML and a starting hook for ClojureScript is pretty much all I need for the head start, I can add the rest later.

I was looking for something really minimal, and the first simple example on my Google search was Daniel Harper’s article. I got rid of noir, used up to date versions of libraries, and voila – it’s working!

When I had my first “hello world” alert showing on page load, I decided to make things a little bit more interesting and introduce jQuery. I found jayq from Chris Granger and decided to give it a shot. There’s also a sample app on Chris’ blog that helped me with some issues, namely figuring out how to bind events. It references a few more interesting libs (namely fetch & crate), but I’ve had enough for now. I guess I could spend the whole night chasing such references.

In the end, the interesting pieces of code are below:

project.clj (configured to compile CLJS from src-cljs to resources/public/js/cljs.js):

(defproject hello-clojurescript "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [[org.clojure/clojure "1.4.0"]
                 [ring "1.1.6"]
                 [jayq "0.1.0-alpha3"]]
  :plugins [[lein-cljsbuild "0.2.8"]]
  :cljsbuild
  {
   :source-path "src-cljs"
   :compiler
   {
    :output-to "resources/public/js/cljs.js"
    :optimizations :simple
    :pretty-print true
    }
   }
  :main hello-clojurescript.core
  )

core.clj (trivial app, with Ring wrapper configured to serve JS resources):

(ns hello-clojurescript.core
  (:require [ring.adapter.jetty :as jetty]
            [ring.middleware.resource :as resources]))


(defn handler [request]
  {:status 200
   :headers {"Content-Type" "text/html"}
   :body 
   (str "<!DOCTYPE html>"
        "<html>"
        "<head>"
        "</head>"
        "<body>"
        "<p id=\"clickable\">Click me!</p>"
        "<p id=\"toggle\">Toggle Visible</p>"
        "<script src=\"http://code.jquery.com/jquery-1.8.2.min.js\"></script>"
        "<script src=\"js/cljs.js\"></script>"
        "</body>"
        "</html>")})

(def app 
  (-> handler
    (resources/wrap-resource "public")))

(defn -main [& args]
  (jetty/run-jetty app {:port 3000}))

hello-clojurescript.cljs (this one gets compiled to JavaScript):

(ns hello-clojurescript
  (:use [jayq.core :only [$ delegate toggle]]))

(def $body ($ :body))

(delegate $body :#clickable :click
          (fn [e]
            (toggle ($ :#toggle))))

Complete source code with instructions can be found at my GitHub repository.

At the moment I see the following issues:

  • I’m really green at ClojureScript. Tons to learn here!
  • The JavaScript file compiled from this trivial example is 13k lines long and weighs about 500 kb. Doh! Fine for local development on desktop, not that good for targetting mobile.
  • The official docs for ClojureScript are really… discouraging. Just like core Clojure documentation, they are pretty academic and obscure.
  • Docs for jayq are… Wait a minute, nonexistent? At least it’s a fairly thin adapter with small, comprehensible codebase.

10 thoughts on “Hello, ClojureScript! (with jQuery)

  1. Ignacio – thanks. Writing this and then reading the posts you linked (yours and Samrat’s) really helped me get started in this world.

  2. I’m very interested to know about your progress. I like what I’ve read about clojure and the goals behind clojurescript. At the same time I’m quite concerned that the clojurescript community success seems dependent on the success of clojure.js, and I’m not seeing a lot of momentum with clojure.js. For example, I cannot seem to find anyone out there with a closure grid. On the other hand ExtJs has a very impressive amount of power in their grid widget.

    In short if progress and support for clojure.js becomes abandoned, or clojure.js itself falls into obscurity (has it even made it out?) what does that say about any prospective investment I may have made in clojurescript?

  3. Chris – what I clojure.js? Do you mean Google Closure (Closure with “s”, a much older, modular JS library from Google that ClojureScript is based on)?

    Feel free to browse through this blog, I share when I learn/experience something worthwhile. I suspect ClojureScript shines in bigger applications which benefit from modularity, certain discipline, terseness etc. But I am yet to write or see such an application myself.

    With varying amount of plumbing, you can use JS libraries with ClojureScript. jQuery and Angular seem to fit well, Backbone hurts a lot and KO is usable but needs some work. Not sure about ExtJS, I’m in the jQuery camp. :-) There are some pure CLJS libraries emerging (like C2, crate, fetch, enfocus).

    Generally, the more functional the library, the better. OO libs (like Backbone) are pretty hard to integrate.

    All in all, I think ClojureScript is definitely worth a try, but not yet very mature, without known established patterns and libs. It probably will give you a bumpy ride. I feel like an early adopter – enthusiastic and optimistic, learning new ways to solve problems, but sometimes dealing with rough edges and without guarantees that the technology will take off and be in wide use in 5 years.

  4. I did indeed mean closure.js, sorry about the confusion there. My intrest in Sencha (ExtJs and Sencha mobile) is mainly about wishing to find a way to leverage the very large amount of investment that they have made available in those technologies. The ExtJS charting and the Grid is quite impressive. However, I’m not particulary happy about the learning curve that would be required to become a developer of good – best practices code for Sencha. Years perhaps, and by then they could have easily changed major ways of doing things.

    I’m curious to know more about your opinion of backbone.js. Our company has been using that technology as well.

  5. Chris – I know too little about Backbone itself for my opinion to be of much value. I wasn’t sold on what I saw, Knockout feels much lighter and more… doing what I expect.

    There is plenty of smaller libraries for components, some with many components, some for just one (graphing, grid, datepicker etc.). I’ve never really done ExtJS itself, and the things I heard about it from much more experienced friends don’t make me want to. Anyway, from a quick look at the sources of sample apps, it seems like ExtJS may be quite usable from ClojureScript.

  6. Oh, I forgot to expand on the first question I had. You mentioned in your reply that ClojureScript is based on closure.js. Does mean that there is not expectation to “piggy back” on whatever momentum and enhancements made into closure.js? That was the gist of my first question. Not seeing much activity coming from the closure.js community leaves me skeptical about the success of that version of a possible Road Map. However if ClojureScript was only inspired and perhaps borrowing from work done in closure.js but not hitching it’s wagon to it, I’d feel a lot better.

  7. Chris – this explains it well: https://github.com/clojure/clojurescript/wiki/Google-Closure.

    ClojureScript compiles JavaScript that is compatible with Closure advanced compilation. It also uses Closure for dependency management and optimizations (both related to the advanced compilation and aggressive minification). That’s the intended path (assuming you consider Closure optimizations and library worthwhile). It’s also based on the same observations and assumptions as Closure: that dependency management in JavaScript gets messy with scale, that JavaScript does not really support namespaces, modules etc.

    But it’s not the only way.

    You can write ClojureScript, compile it to JavaScript (without Closure at all) and use as plain JavaScript. You would still benefit from the ability to use ClojureScript syntax, get namespaces etc. and you can drop Closure completely.

    Also, you can use any non-Closure library from ClojureScript, but that may require some work. The more object-oriented the library is, the harder it may be on syntactical level.

    And if you do want to go all the way and use Closure, you will need “exports” files for non-Closure libraries, so that the advanced compiler does not translate certain names. For instance, I can use jQuery with advanced compilation if I include an exports file (available for download somewhere on the internet).

    If you’re interested, a *very* good explanation of all this is in “ClojureScript Up and Running” (http://squirrel.pl/blog/2012/12/17/clojurescript-up-and-running-book-review/). Short, easy read and cheap. :-)

Leave a Reply

Your email address will not be published. Required fields are marked *

Spam protection by WP Captcha-Free