First steps with Clojurescript

Clojurescript is a compiler for Clojure that targets Javascript. Using Clojurescript you can write your Javascript app in Clojure, taking advantage from functional programming paradigms, for example immutable data structures, on top of the excellent Google Closure Tools library that powers many Google products.

Clojurescript logo
Clojurescript logo

If you are not familiar with the concepts in the first paragraphs, I highly recommend you to read all the linked pages. Depending on your background you may realise that understanding some concepts takes time. Don’t discourage yourself! The journey to master this concepts is long, but I think it professionally pays with interests.

I started using Clojurescript time ago for fun, with no experience at all, and I was able to learn enough Clojure to start playing with the code thanks to 4clojure and some other online resources.

I realised that at the beginning I spent a lot of time dealing with the language tools and trying to find my way through the ecosystem. As this is a quite common complain for people getting started with Clojure I decided to write this post that describes some of the things you need to know to start a new Clojurescript project from scratch, hoping to save you some time.

All the choices I made are opinionated, don’t take everything for granted, I might choose different tools than yours and this is what worked for me. Let’s start.

1- Use a community supported editor

The first decision to take might look trivial, of course you need an editor to write Clojurescript code. Turns out this is an important decision for two main reasons:

  • as you might know, Clojure is a lisp. Its syntax requires you to write a lot of parenthesis and an editor with specific plugins will help you a lot.
  • Clojure and Clojurescript both provide interactive development through the REPL, which is simply amazing. At the beginning you might not know what this REPL is about, but I’ll tell you, you want to use a REPL integrated editor.

Now, according to the 2015 state of clojure the most used editors for Clojure are:

As a long-time Vim user the first combo I tried was obviously Vim + Fireplace, which works fine. Later on I decided to invest some time and switch to Emacs, but I don’t consider it necessary and trust me, you don’t want to do that while learning a new language.

If you are an IDE type of guy you will certainly appreciate Cursive, a plugin for Intellij specific for Clojure and Clojurescript. I watched a talk about it and it looks amazing.

A small percentage of users are using LightTable or Sublime Text. It’s possible, but it’s less used and therefore less supported by the community.

My suggestion is to use one of the three editors above, you’ll find amazing community support and I can ensure you’ll be immediately productive.

2- Choose a build tool

If you created a Clojure project in the past, you’ll certainly heard of Leiningen, which is by far the most popular build tool for Clojure and Clojurescript projects. You will use it for example to fetch dependencies, to build and run your project, to execute tests. But Leiningen is not the only build tool available for Clojure and Clojurescript projects, there’s a relatively new kid in town these days called boot.

Here is a list of the things I think you need to know before starting your first Clojurescript project:

Leiningen is declarative and almost all the configuration happens inside a big project map that you keep at the root of your project, in a file called project.clj. With Leiningen you can use Figwheel, which is a popular library for reloading and evaluating your code in the browser, dramatically improving the feedback loop (watch this awesome talk).

Boot instead rely on a more programmatic approach. Defining a simple build.boot file at the root of your project, you can customise multiple set of tasks in a developer friendly way, it’s just Clojure code. If you want the reload capabilities of Figwheel, you can include in your project the boot-reload library, which does more or less the same job.

Both build tools are documented pretty well and I suggest you to discover their internals.

I personally don’t like the big project map you need to use when configuring a project with Leiningen. Here is an example taken from one of my projects:

(defproject project-name "0.1.0-SNAPSHOT"
  :dependencies [...]

  :min-lein-version "2.5.3"

  :source-paths ["src/clj" "script"]

  :plugins [[lein-cljsbuild "1.1.1"]
            [lein-doo "0.1.6"]]

  :clean-targets ^{:protect false} ["resources/public/js/compiled" "target"

  :cljsbuild {:builds [{:id "dev"
                        :source-paths ["src/cljs"]
                        :compiler {:main project-name.core
                                   :output-to "resources/public/js/compiled/app.js"
                                   :output-dir "resources/public/js/compiled/out"
                                   :asset-path "js/compiled/out"
                                   :source-map-timestamp true}
                       :source-map true}

                       {:id "test"
                        :source-paths ["src/cljs" "test/cljs"]
                        :compiler {:output-to "resources/public/js/compiled/test.js"
                                   :main project-name.runner
                                   :optimizations :none}}

                       {:id "min"
                        :source-paths ["src/cljs"]
                        :compiler {:main project-name.core
                                   :output-to "resources/public/js/compiled/app.js"
                                   :optimizations :advanced
                                   :closure-defines {goog.DEBUG false}
                                   :pretty-print false}}]}

  :profiles  {:dev  {:dependencies  [[com.cemerick/piggieback "0.2.1"]
                                     [figwheel-sidecar "0.5.0-6"]
                                     [reloaded.repl "0.2.1"]]
                     :surce-paths  ["dev" "cljs_src"]}}

  :repl-options {:nrepl-middleware [cemerick.piggieback/wrap-cljs-repl]})

Compare it with a build.boot file:

 :source-paths    #{"sass" "src/cljs"}
 :resource-paths  #{"resources"}
 :dependencies '[...])

 '[adzerk.boot-cljs             :refer [cljs]]
 '[adzerk.boot-cljs-repl        :refer [cljs-repl start-repl]]
 '[adzerk.boot-reload           :refer [reload]]
 '[pandeiro.boot-http           :refer [serve]]
 '[crisptrutski.boot-cljs-test  :refer [test-cljs]]
 '[mathias.boot-sassc           :refer [sass]])

(deftask build []
  (comp (speak)
        (sass :output-dir "css")))

(deftask run []
  (comp (serve)

(deftask production []
  (task-options! cljs   {:optimizations :advanced}
                 sass   {:output-style "compressed"})

(deftask development []
  (task-options! cljs       {:optimizations :none :source-map true}
                 reload     {:on-jsload '}
                 sass       {:line-numbers true
                             :source-maps  true})

(deftask dev
  "Simple alias to run application in development mode"
  (comp (development)

(deftask testing []
  (set-env! :source-paths #(conj % "test/cljs"))

;;; This prevents a name collision WARNING between the test task and
;;; clojure.core/test, a function that nobody really uses or cares
;;; about.
(ns-unmap 'boot.user 'test)

(deftask test []
  (comp (testing)
        (test-cljs :js-env :phantom
                   :exit?  true)))

(deftask auto-test []
  (comp (testing)
        (test-cljs :js-env :phantom)))

Even if you don’t know anything about boot, try to guess what the boot dev command will do. Isn’t it simpler and self-explanatory compared to the Leiningen project map? I believe it is, that’s why I suggest you to use boot for your first project.

Now, I omitted on purpose a lot of important differences between Leiningen and boot in this section, because the first thing I saw as a beginner was this configuration and I think you’ll do the same. If you want to understand more, the boot wiki is a great starting point.

In some communities the build tool is an obvious choice (the majority of the people in the Ruby community for example use Rake), in the Clojure community the choice is less straightforward. Other people might suggest you to use Leiningen, it’s fine, but the rest of the post is in line with my choice of using boot.

3- Pick a project template

To create a Clojure or Clojurescript project you can start from scratch, or you can create a new project using an existing template. This is somewhat similar to the creation of a new Rails project, which in turn gives you some features out-of-the-box, for example sass and coffeescript support.

Tenzing is a simple and well documented template for Clojurescript boot projects. It optionally lets you include some features during the creation of the project, for example sass or less compilation, a react wrapper (Reagent or Om), a test runner. Tenzing generates for you a nice build.boot file ready to be run, that you can then configure in the future.

I really suggest you to create your first project using the Tenzing template, you’ll save some manual configuration.

If you didn’t follow my advice when I recommended boot in step 2, you can use a template for Leiningen. There are two popular templates I want to suggest:

Both Om and Reagent are excellent interfaces to React.

4- Configure your editor for the REPL

The last step before actually start coding consists in configuring your editor to use the REPL. You need to do this if you want to be able to select a piece of code in your editor, press a keystroke and have it automatically evaluated, in the editor or in the browser connected via websockets.

When I was using Vim on a Leiningen project I really lost a lot of time with this configuration, it’s not complex but I couldn’t find my way through vim-fireplace, figwheel, piggieback and friends, and it seems I was not the only one experiencing the pain. I ended up creating a new tmux window with the active REPL and sending commands to that window using tslime, a Vim plugin that pushes an highlighted piece of code from a window to another. It works, it doesn’t evaluate code inside the editor but the outcome is pretty close.

Using boot and the corresponding boot-reload library instead of Figwheel I was able to configure Vim to send commands directly from the editor to the REPL and the browser. The configuration is simple and involves the steps described into the boot-cljs-repl README.

If you are using Emacs + CIDER the README of the project explains exactly what you have to do to connect your editor using to the REPL. Here is the section about boot projects.

5- Start coding

Congratulations! You should now have a working Clojurescript application with REPL evaluation and reload on code changes.

It’s time to start coding, have fun!