Experiencing the interactive workflow that results from being able to evaluate Clojure expressions that are present in your editor’s buffer frame is enlightening. When you have this ability to quickly verify behavior without the ceremony of restarting an application, you will start to move forward with more confidence. You have the ability to check that a function works against glaring edge cases in seconds. This allows you to think more clearly about what your code is actually doing, and more clearly about what you actually need.
Many editors provide support for evaluating ClojureScript code via a REPL connection, however the process for setting this up can seem complex, mysterious and convoluted.
Why does this complexity exist? The main reason that there is complexity in connecting a ClojureScript REPL to your editor is that the environment is just well … complex.
The typical path of code that will ultimately evaluated in a Browser and eventually returned to an editor:
The main problem here is that a lot is going on. When we evaluate Clojure remotely the message just needs to travel to the Clojure runtime and back. When we are using ClojureScript the code has to travel to the compiler and then to the browser and back.
The Major Players
Because of this complexity it is best if we start and understand the pieces. In practice you will not often have to set these up yourself but things can become very confusing very quickly if you don’t understand what they are.
It is common for Clojure developers to start an nREPL server inside an application that is running on a remote server so they can interactively debug particularly thorny problems.
nREPL provides the server endpoint that most editors integrations talk to when they want to evaluate Clojure/ClojureScript code.
The simplest way to explain how nREPL works is that it understands a
set of messages. The most important one for our purposes is the
:eval message that includes a
nREPL is extensible via middleware that can receive and handle these messages.
Piggieback is nREPL middleware that intercepts
:eval messages and
re-directs them to a ClojureScript REPL for evaluation. So Piggieback
is an extension of nREPL and we have to extend nREPL because it knows
nothing about ClojureScript.
There are two main parts to using Piggieback. First, it has to be
inserted into the middleware of the nREPL server that you are going to
be using. Second, you have to start your ClojureScript REPL with a
cider.piggieback/cljs-repl. You have to start your REPL this
way so that it can do the bookkeeping necessary to re-direct
messages to the ClojureScript REPL.
The ClojureScript REPL is written in Clojure and is what allows us to evaluate ClojureScript code in the first place.
You can run a ClojureScript REPL locally and this is what happens when
clojure -m figwheel.main -b dev -r. This is pretty simple to
accomplish. However, it is when you wan to run it remotely over nREPL
that things get more difficult.
Figwheel Websocket Server
Editors and nREPL
Almost all editor integrations in the ClojureScript ecosystem can utilize nREPL for communication. This is why understanding it and its role as a REPL server is important.
There are other ways for editors to connect to Clojure remotely but currently nREPL integrations tend to provide the most editor functionality (i.e. documentation, auto-complete, jump to definition). You can opt to connect to a REPL by another means but the nREPL integrations are by far the most used.
Editors and Stream REPLs
A traditional way for editors to communicate with a REPL is to pipe forms (Clojure expressions in this case), to the STDIN of the REPL and capture the STDOUT as a response. This form of communication is much simpler.
Currently both Emacs and Cursive support this type of
communication. Emacs has its
has particularly good support for this type of REPL communication when
you create a
Don’t worry if neither of those are your favorite editors as there are many other integrations out there. But you should know that CIDER and Cursive account for a whopping 80% of Clojure editor use and this is not by accident as both CIDER and Cursive are under intense active development.
10% of Clojurists use Vim Fireplace. The Vim support for Clojure/Script is nowhere near as extensive as the previous two, I’ll chalk its high rate of adoption up to the sheer popularity of Vi among the hacker crowd.
I know that Emacs is the other text editor but I highly recommend
that Vi users use Emacs with
evil-mode, many Clojurists who are come
from a Vi background have switched and are happy about it. The main
reason is that Emacs Clojure integration via CIDER is heads and
shoulders above the currently available Vi integration.
See this blog post for an experience report on switching to Emacs.