I made the switch to Clojure a little over a year ago, and since then have became obsessed with pulling as much of the development process into the Clojure world as practical. While I have been looking to get into ClojureScript for a long time I have always had a lot of trouble getting started. Often I would block off some time to build a sample app and spend almost all of my time struggling to get the repl to connect to the browser, and be too exhausted to actually build anything. Fortunately I have finally gotten everything behaving, I today I am going to walk you through doing the same.
A little about my setup, in my Clojure development environment I run TTD with Speclj, and live coding in Emacs with the excellent Emacs-Live package. This allow for an instant feedback cycle for both running code snippet, in emacs documentation, unit tests, and the full end to end tests. It was very important to me to have the same degree of control and being able to use the same tools for my ClojureScript development environment. Lucky for me I discovered Chestnut.
Chestnut is a Clojure(Script) template that out of the box gives you Ring support for web application support, Figwheel to push ClojureScript changes to the client, Weasel for the ClojureScript Browser REPL connection via WebSocket, and the powerful Om to give us the latest and greatest from Facebook’s React library.
Note: On my system I am running Leiningan 2.5.0 on Java 1.8.0_05 Java HotSpot(TM) 64-Bit Server VM, I have not tested this on any other platform, YMMV.
Getting started with Chestnut is as simple as:
This provides us with the following:
Taking a look at the project.clj we can see that a lot of the dependencies are already there for us. If any of this is unfamiliar to you I would urge you to invest the time to understand what is going on here, it can really save a lot of debugging time down the road.
While this is an amazing start we still are going to need to do a bit of work to get everything running smoothly. First lets start by adding some dependencies that I have found to make everything run more smoothly, and our Speclj dependencies. This is what my project.clj file looks like after adding in those changes.
To run the cljs tests we are going to need Phantomjs installed. If you use Homebrew it is as simple as
$ brew install phantomjs. Once that is ready to go create runner file for PhantomJs:
Now drop in some stubs for the test files:
Update the default app state for our hello world moment:
If you do not plan on using Emacs-Live you can skip the next two sections, otherwise read on.
Now is a good time to double check the version of Cider being run by your
M-x cider-jack-in. At the time of these writing the default Emacs-Live installation had cider 0.6.0, which does not play well with with the cljs repl. The easiest way to update this is change your ~/.lein/profiles.clj to look like so. Also if you already have a profiles.clj, you can just add the two plug-ins below and it should take care of it.
Additionally, now that we have cider 0.7.0 the Emacs plug-in auto-complete will start causing all sorts of hanging and trouble. I wish I had a non-hacky way to solve this but sadly the intricacies of the Emacs-Live package system are still opaque to me. The hackey solution is in emacs
M-x package-install company which will give us Company-Mode a non-buggy replacement for auto-complete. Then whenever you open a clj do
M-x auto-complete-mode to disable it. I know, its really hackey but for now this is the best I have so lets just get to the good part.
With the heavy lifting complete lets confirm we are good to go.
Step one, Speclj auto-run testing:
Step two, Specljs auto-run and auto-compile testing
Ideally this would run in the repl/cider-jack-in, but I couldn't figure out a clean way to do it. Fortunately we can just run an separate cljsbuild in the terminal to do that auto-testing for us.
Step three, this one is for all the cookies. This can be done either way depending on your preference.
Straight from the repl
If everything went well and we haven't fallen out of the development gods' favor, then opening up your web browser to
localhost:10555 and you should see "Hello Moo Cow!" smiling down at you.
Finally, our last step is to inform the browser you are its new master by issuing it a command:
Note: if the command gave you an error like this,
java.io.IOException: No client connected to Websocket try refreshing
localhost:10555 and it should now be connected.
With that you should now have:
1. An auto-run Speclj service alerting you if your .clj test pass after every save
2. An auto-run auto-compile Specljs service alerting you for your .cljs tests
3. A repl connection allowing you to interact live with the browser
Of course I have left the making the test pass up to the reader. Once that is done you should be ready to get hacking on an Om. For next steps I would recommend David Nolan's basic tutorial to get you started with the Om's core concepts. Though it is light table centric, there is plenty to be gained from any development environment. The full project source is available here:
Thanks for reading.