shadow-cljs provides everything you need to compile your ClojureScript code with a focus on simplicity and ease of use.

To install shadow-cljs, use npm:

npm install -g shadow-cljs

shadow-cljs requires Java, make sure you have Java installed. Don’t worry, shadow-cljs handles Java for you. If you still want to learn more about ClojureScript, checkout this list.

Compile to browser

Say you have a project:

.

├── README.md

├── assets

│ └── index.html

├── package.json

├── shadow-cljs.edn

├── src

│ └── app

│ ├── lib.cljs

│ └── main.cljs

└── yarn.lock

assets/index.html (please copy it to target/index.html in order that it can be accessed) looks like:

<script src="main.js"></script>

src/app/main.cljs may look like:

(ns app.main) (def value-a 1) (defonce value-b 2) (defn reload! []

(println "Code updated.")

(println "Trying values:" value-a value-b)) (defn main! []

(println "App loaded!"))

The namespace for this project is just app . To compile this project, first create a shadow-cljs.edn file, with configs:

{:source-paths ["src"]

:dependencies []

:dev-http {8080 "target/"}

:builds {:app {:output-dir "target/"

:asset-path "."

:target :browser

:modules {:main {:init-fn app.main/main!}}

:devtools {:after-load app.main/reload!}}}}

Here’s how it’s configured:

:source-paths is where you put source code

is where you put source code :dependencies is ClojureScript deps of this projects

is ClojureScript deps of this projects :builds is where you specify build configurations

is where you specify build configurations :app is a build id named by us, we will need it to run specific compilations from command line tools or from APIs

is a build id named by us, we will need it to run specific compilations from command line tools or from APIs :output-dir decides where the generated files are saved

decides where the generated files are saved :asset-path is the base path of files of the hot updated code

is the base path of files of the hot updated code :target is short for “compilation target”, :browser is for browser apps

is short for “compilation target”, is for browser apps :modules specifies the modules we want to generate, :main also means the bundle will be named main.js

specifies the modules we want to generate, also means the bundle will be named :init-fn specifies the main function of the whole program

specifies the main function of the whole program :devtools specifies configurations for development tools

specifies configurations for development tools :dev-http tells shadow-cljs to serve the folder target/ on port 8080.

During development, we can compile with hot code swapping, watch how we use the build id :app :

shadow-cljs watch app

After initial compilation finished, shadow-cljs would generate code in target/main.js and serve target/ folder on http://localhost:8080. When you open the url, the page will connect to shadow-cljs’ server and listen for updates. As you modify code and save files, the app will be hot reloaded and then app.main/reload! will be called.

To compile and optimize code:

shadow-cljs release app

For the complete example, please clone this repo:

Compile to Node.js

It’s quite similar steps to compile ClojureScript targeting Node.js , for the project:

.

├── README.md

├── package.json

├── shadow-cljs.edn

├── src

│ └── server

│ └── main.cljs

└── yarn.lock

src/server/main.cljs may look like:

(ns server.main) (def value-a 1) (defonce value-b 2) (defn reload! []

(println "Code updated.")

(println "Trying values:" value-a value-b)) (defn main! []

(println "App loaded!"))

We can use shadow-cljs.edn with configurations:

{:source-paths ["src"]

:dependencies []

:builds {:app {:target :node-script

:output-to "target/main.js"

:main server.main/main!

:devtools {:after-load server.main/reload!}}}}

Now we use :node-script as the compilation :target . And there are two fields:

:output-to specifies the output file

specifies the output file :main specifies the main function

Like in previous demo, we can start compilation in development mode, and run it with Node.js :

shadow-cljs watch app # in another terminal

node target/main.js

As Node.js runs, it will connect to shadow-cljs’ WebSocket server listening for updates. Some npm modules( ws and source-map-support ) are required, please install them. It also does hot code swapping as well as calling reload! function.

To create a release bundle, use the sub-command:

shadow-cljs release app

You may also add :compiler-options {:optimizations :simple}} to disable mangling. To try the full example, clone this repo:

More

There are also examples you can browse in shadow-cljs, like using Macros:

Or like compile code with long term caching:

And some examples run in several environments of JavaScript:

Explore more on shadow-cljs and send feedbacks on GitHub :)