Setup ClojureScript with Shadow CLJS
Here's how to set up a simple ClojureScript project with shadow-cljs.
shadow-cljs
Shadow CLJS is so many things, I don't think I can currently enumerate them. In this case, it's going to configure the building of ClojureScript into JavaScript. It'll give us a nice development server too.
Dependencies
On a Clojure/Script project, dependencies are usually in deps.edn
. You can put them in shadow-cljs config too, but let's stick with the standard. So, here's deps.edn
:
{:paths ["src"]
:aliases {:cljs {:extra-deps {thheller/shadow-cljs {:mvn/version "2.23.3"}}}}}
By setting up the alias, we're making shadow-cljs available where it needs to be.
The Build
The build and dev server are defined in shadow-cljs.edn
:
{:deps {:aliases [:cljs]}
:builds {:app {:target :browser
:output-dir "public/js"
:modules {:main {:init-fn app.core/init}}}}
:dev-http {5555 "public"}}
:deps
indicates that shadow-cljs should look in deps.edn
for dependencies. This build is for an in-browser web app. You could build for Node.js too.
The :init-fn
shows the entry point to our application, which we have yet to write.
The Source
As we indicated in our deps.edn
, src
will be where our ClojureScript code is. Here is core.cljs
:
(ns app.core)
(defn on-load []
(js/console.log "Hi ya yahoos")
(let [root (js/document.getElementById "root")]
(set! (.-innerHTML root) "Loaded, yay!")))
(defn ^:export init []
(js/document.addEventListener "DOMContentLoaded" on-load))
The namespace matches to full path in :init-fn
. There's not much here, but it should demonstrate a few things:
^:export
is putting metadata on the function, and it's equivalent to a named export in ES modules.
The js/
namespace is available globally in cljs. Methods and attributes usually available on window
/global
are available here.
set!
is the cljs api for setting variables
.-
is used to access properties on objects.
Lots more to learn there, but these are the basics: A callback will be trigger on a DOM event, the console will print, and the DOM will be manipulated.
Run the App
We need to make the shadow-cljs
cli available to run commands. You can do that with npx
or install it where it's in your $PATH, as local node_modules are for my system:
npm init -y
npm install shadow-cljs --save-dev
Now we can run the dev server. For watch mode:
shadow-cljs watch app
app
is the build identifier from shadow-cljs.edn
.
Now you're ready on your :dev-http
port:
xdg-open localhost:5555
You'll see the console.log and the DOM changed. You're CLJS'ing now!