= ClojureScript
:experimental:

NOTE: CIDER works well with ClojureScript, but not all CIDER features are
available in ClojureScript (yet). For instance, the test runner and
debugger are currently Clojure-only features.

Unlike the Clojure ecosystem that is dominated by a single REPL, the
ClojureScript ecosystem has a number of different choices for REPLs
(e.g. `browser`, `node`, `weasel`, `figwheel` and `shadow-cljs`). You'll have to
decide which one you want to run and how you want CIDER to interact with it.

In this section we'll take a look at how ClojureScript support is implemented in CIDER,
and in the subsequent sections we'll discuss how to launch a ClojureScript REPL
and how to setup the most popular ClojureScript REPLs.

== nREPL and ClojureScript

nREPL doesn't natively support ClojureScript evaluation, that's why an additional
middleware is needed. For most REPLs (with the notable exceptions of `shadow-cljs`, `nbb`), CIDER relies on the popular Piggieback middleware for its
ClojureScript support.

Piggieback works in the following manner:

* You start a regular Clojure REPL
* You run some Clojure code in it, that converts it to a ClojureScript REPL

This means that jacking-in is a two-fold process for ClojureScript, compared to Clojure,
as now we have the extra REPL "upgrade" step.

On the bright side - this also means that you can host side by side Clojure and ClojureScript
REPLs in a single nREPL connection! This opens up all sorts of interesting possibilities
that we'll discuss later on.

NOTE: `shadow-cljs`'s REPL is implemented in a very similar fashion, but its mechanism is provided by its own nREPL middleware - not Piggieback.

== Piggieback differences with the Standard ClojureScript REPL

While the Piggieback-powered ClojureScript REPLs behave more or less
the same as the standard ClojureScript REPL, there are few subtle
differences everyone has to be aware of.

=== Handling of Multiple Forms

Here's how the standard ClojureScript behaves with multiple input forms:

[source,clojure]
----
cljs.user>
(declare is-odd?)
(defn is-even? [n] (if (= n 0) true (is-odd? (dec n))))
(defn is-odd? [n] (if (= n 0) false (is-even? (dec n))))
#'cljs.user/is-odd?
#'cljs.user/is-even?
#'cljs.user/is-odd?
cljs.user> (is-even? 4)
true
----

And here's how a Piggieback-powered REPL behaves:

[source,clojure]
----
cljs.user>
(declare is-odd?)
(defn is-even? [n] (if (= n 0) true (is-odd? (dec n))))
(defn is-odd? [n] (if (= n 0) false (is-even? (dec n))))
#'cljs.user/is-odd?
cljs.user> (is-even? 4)
Compile Warning   <cljs repl>   line:1  column:2

  Use of undeclared Var cljs.user/is-even?

  1  (is-even? 4)
      ^---

#object[TypeError TypeError: Cannot read property 'call' of undefined]
	 (<NO_SOURCE_FILE>)
cljs.user>
----

This difference comes from a performance optimization in Piggieback, which avoids
creating different REPLs for each ClojureScript form it evaluates.

TIP: You can learn more about this difference https://github.com/nrepl/piggieback/pull/98[here].

== Dealing with Dependencies

CIDER doesn't handle automatically ClojureScript REPL dependencies when you're doing
`cider-jack-in-cljs`. You'll have to configure those manually yourselves
as documented in the subsequent sections of this manual.

Actually, CIDER will handle automatically the most important dependency - namely Piggieback.
The problem with the other dependencies, however, is that you might need to install
some external tools (e.g. `node`, `shadow-cljs`) and that ClojureScript development
tools like Figwheel and shadow-cljs also require some setup to be useful.

CIDER will try to help you identify missing requirements by running a check, right before
attempting to upgrade a Clojure REPL to a ClojureScript REPL. The nature of this check
differs for the different REPL types:

* For a `node` REPL we check whether the `node` binary is on your `exec-path` (Emacs's version of `PATH`)
* For tools like `figwheel` we check whether they are available on the classpath (by trying to require
some of their namespaces)

We'll discuss those checks further in the upcoming sections.

== Limitations

CIDER currently doesn't support self-hosted ClojureScript implementations.
The reason for this is that there's no self-hosted version of nREPL (implemented in ClojureScript)
available today.

Another unsupported REPL is Rhino. Supporting in it Piggieback required a lot of ugly hacks
and eventually it was decided we were better off without Rhino. Given the abundance
of better solutions today, I doubt anyone's going to miss Rhino anyways.

Additionally, as noted earlier on this page - many of CIDER's advanced features are
currently not available for ClojureScript.

== Next

In the next section we'll show you how to start a ClojureScript REPL with CIDER.
