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

Good configuration defaults so you don't have to sweat the details Seamless npm integration Fast builds, reliable caching, ... Supporting various targets :browser , :node-script , :npm-module , :react-native , :chrome-extension , ... Live Reload (CLJS + CSS) CLJS REPL Code splitting (via :modules )

To use shadow-cljs, add your configurations in a shadow-cljs.edn file, and run:

npm install -g shadow-cljs shadow-cljs compile app

Configurations

For a browser app, create a shadow-cljs.edn file like:

{ :source-paths [ "src" ] :dependencies [[reagent "0.8.1" ]] :builds { :app { :target :browser :output-dir "public/js" :asset-path "/js" :modules { :main { :init-fn app.main/main!}}}}}

which means:

{ :source-paths [ "src" ] :dependencies [[reagent "0.8.1" ]] :builds { :app { :target :browser :output-dir "public/js" :asset-path "/js" :modules { :main { :init-fn app.main/main!}}}}}

To publish a ClojureScript package with dependencies from npm, add a dep.cljs file. shadow-cljs will read it and install those npm modules.

CLI tools

Some useful shadow-cljs commands during development are:

shadow-cljs compile app shadow-cljs watch app shadow-cljs cljs-repl app shadow-cljs node-repl

Running a release build optimized for production use.

shadow-cljs release app

Find out more commands in the docs .

Using modules from npm

With shadow-cljs, most npm modules for browser can be imported with modules installed locally.

( ns app.main ( :require [ "md5" :as md5] [ "fs" :as fs])) ( println ( md5 "text" )) ( fs/readFileSync "deps.den" "utf8" )

Lifecycle Hooks

You can configure the compiler to run functions just before hot code reload brings in updated code, and just after. These are useful for stopping/starting things that would otherwise close over old code.

( ns my.app) ( defn ^ :dev/before-load stop [] ( js/console.log "stop" )) ( defn ^ :dev/after-load start [] ( js/console.log "start" ))

Find more configs in user manual .

Non-code resources

There are various use-cases where you’d want to use a static resource as part of the compilation of your source files. shadow-cljs provides a macro shadow.resource/inline for loading files from inside classpaths:

( ns demo.app ( :require [shadow.resource :as rc])) ( def docs ( rc/inline "./docs.md" ))

This will resolve the ./docs.md file relative to the current namespace, which means it will end up including demo/docs.md from somewhere on the classpath.

Long-term caching

By setting in :module-hash-names field you may tell shadow-cljs to add MD5 hash in the filenames generated. It's a trivial feature in Webpack and now it's a one-liner config in ClojureScript. Meanwhile the assets.edn file can be emitted for indexing js files in HTML.

{ :source-paths [ "src" ] :dependencies [[mvc-works/hsl "0.1.2" ]] :builds { :browser { :target :browser :output-dir "target/browser" :modules { :main { :init-fn app.main/main!}} :release { :output-dir "dist/" :module-hash-names 8 :build-options { :manifest-name "assets.edn" }}}}}

After compilation, two files will be generated in dist/ with names:

=>> l dist/ assets.edn main.9683CD2F.js

Embedding in the JS Ecosystem — The :npm-module and :esm Target

There is an additional target that is intended to help you use shadow-cljs as part of a project and provide seamless integration with existing JS tools (eg. webpack, browserify, babel, create-react-app, …​) with as little configuration as possible.

Sample source for src/main/demo/foo.cljs

( ns demo.foo) ( defn hello [who] ( str "Hello, " who "!" ))

Compile code to `:npm-module` target

{ :builds { :npm { :target :npm-module }}}

The generated exports will be named shadow-cljs/ with the CLJS namespace.

$ node > var x = require("shadow-cljs/demo.foo"); undefined > x.hello("JS") 'Hello, JS!'

It is now also possible to generate “almost” standards-complient ESM output. It says “almost” because it is technically cheating in development. release builds are fully :advanced optimized and compliant as they don’t leak any globals or do any other kinds of eval tricks.

The generated code can be loaded as a module. Find out more about `:esm` target.

< script type = "module" src = "/js/demo.js" > </ script >

Other features

There are more features in shadow-cljs, such as:

Read the User Guide to learn about all the features.

Getting started