Last summer I moved boodle from Figwheel to Figwheel Main. I was pretty
satisfied with this setup, but the rise of shadow-cljs in the Clojure community
has been tickling my curiosity over and over again. While configuring
shadow-cljs
I took the chance to set lein
aside and finally explore clj
and
deps.edn
, another thing on my to-do list that has been waiting for me for some
time.
Let’s start with deps.edn
:
{:deps
{
;; … Clojure dependencies …
}
:paths ["src/clj" "resources"]
:aliases {:run {:main-opts ["-m" "boodle.core"]}
:test {:extra-paths ["test/clj"]
:extra-deps {lambdaisland/kaocha {:mvn/version "0.0-266"}}}
:outdated {:extra-deps {olical/depot {:mvn/version "1.4.0"}}
:main-opts ["-m" "depot.outdated.main"]}}}
One thing worth of notice here is :paths
. I included the resources
directory in
it because I serve it via compojure
/http-kit
and that’s where I put the static
assets used in my main index page. This solution works when I run
mount.core/start
via REPL and when I use the :run
alias from the command line.
Speaking of aliases, they are invaluable. With :run
I can use clj -A:run
instead
of lein run
, and with clj -A:outdated -a outdated
I can easily check for
outdated dependencies in my deps.edn
thanks to depot. Unit tests are now handled
by kaocha, and as per its instructions I have a bin/kaocha
file which picks up
the :test
alias and runs all my tests.
I love the simplicity of deps.edn
, it feels like a de-cluttered project.clj
.
Configuring shadow-cljs
was a bit more complicated. It took me a while to
understand how to properly integrate it with CIDER. However, the manual is great
and the fine people on Slack’s #shadow-cljs
(thanks Ryan Haywood and Thomas
Heller!) made it all nice and smooth.
This is my shadow-cljs.edn
:
{:source-paths ["src/cljs"]
:nrepl {:port 8777
:middleware [refactor-nrepl.middleware/wrap-refactor]}
:dependencies [
;; … ClojureScript dependencies …
]
:builds {:boodle {:target :browser
:output-dir "resources/public/js"
:asset-path "/js"
:modules {:main {:entries [boodle.core]}}}}}
Basic setup, straight from the manual pages. Notice that :output-dir
refers to
the same resources
directory configured in deps.edn
. This tells shadow-cljs
to
place the build output exactly where I need.
The other important change is in the CLJS libraries I use. shadow-cljs
does not
support CLJSJS, so I had to install pikaday
and moment
via yarn
.
$ yarn add pikaday moment
Since boodle
relies on re-frame
, I had to install three other libraries to make
shadow-cljs
build my code happily:
$ yarn add react react-dom create-react-class
In the namespace where I use them, the :require
had to be changed:
(:require ;; … other requires …
["react-dom" :refer [findDOMNode]]
["pikaday" :as pikaday])
And the code had to be adapted:
(let [default-opts {:field (findDOMNode this)
;; … other options …
}
instance (pikaday. opts)]
;; … other ClojureScript code …
)
However, a project setup is not ready unless I can work on it via Emacs. These are the steps I made to have a working CLJ/CLJS development environment. When this issue will be fixed some of it may become unnecessary.
First, I added a couple of dependencies in shadow-cljs.edn
:
:dependencies [;; … other dependencies …
[cider/cider-nrepl "0.18.0"]
[refactor-nrepl "2.4.0"]]
Then I removed everything Figwheel Main related from the .dir-locals.el
file
located in the root directory of boodle
:
((nil
(cider-default-cljs-repl . shadow-select)
(cider-pprint-fn . zprint)
(cider-preferred-build-tool . clojure-cli)
(cider-known-endpoints . (("hathaway" "localhost" "8777")))
(cider-ns-refresh-after-fn . "mount.core/start")
(cider-ns-refresh-before-fn . "mount.core/stop"))
(emacs-lisp-mode
(flycheck-disabled-checkers . "emacs-lisp-checkdoc")))
I ran cider-jack-in-clj
to have a CLJ REPL and check I didn’t break something on
the Clojure side of boodle
.
From a terminal, I used shadow-cljs watch boodle
to have shadow-cljs
build
boodle
and offer me a nice nREPL server listening on port 8777
, the one
I specified in shadow-cljs.edn
.
Back in CIDER, cider-connect-cljs
brought up a REPL connected to shadow-cljs
nREPL server, and let me select the build I want it operating on (default is
dev
, I just typed in boodle
). Connecting to boodle
via the browser finalized the
connection between my code and the CLJS environment.
A great journey. Once again, boodle
proved fertile ground to understand the
Clojure ecosystem and play with it to learn something new. If you want more
details, the project is on my GitHub.