The next chapter will explain in detail how the ClojureScript compiler works, and its various options and their applications. But for now, you probably want to jump right in and get started.
Due to the relative youth of ClojureScript as a technology, there aren’t any highly standardized ways of working or best practices yet. What conventions there are tend to change frequently, and the built-in tools that ClojureScript ships with are somewhat low-level and labor-intensive to use.
Therefore, in the spirit of the Up and Running title of this book, we will recommend Leiningen and lein-cljsbuild as tools for getting started, and these will be introduced in this chapter and used throughout the rest of the book. They are more mature than other tools currently available, are relatively easy to use, work on all three major platforms (Windows, Linux, and OS X), and are likely to be around for some time.
Instructions for installing ClojureScript from source and running its lower-level, more primitive tools will also be included in Chapter 9. However, for most users, Leiningen should prove more than sufficient for both learning and real-world production use.
Leiningen is a build system for Clojure, named to highlight its opposition to the venerable but labor-intensive Ant build system for Java (see the short story Leiningen Versus the Ants by Carl Stephenson). It is the de facto standard for building Clojure projects in the Clojure community, and has a wide array of useful features.
It utilizes Maven for dependency resolution, and can seamlessly connect to any Maven repository to acquire dependencies. However, it features an original build system optimized for Clojure workflows, and can also compile Java source code. In addition, it exposes integration points for third-party plug-ins, enabling its use with a wide variety of other programming languages, including ClojureScript via the lein-cljsbuild plug-in discussed below.
This book describes Leiningen version 2, which is much more featureful than previous versions and is recommended for new projects at the time of writing. If you do need to use ClojureScript with existing versions of Leiningen, don’t worry: lein-cljsbuild is fully compatible with Leiningen 1.7.0 and up. However, you’ll need to read the legacy Leiningen documentation, as the examples included here use new configuration properties introduced in 2.0.0.
Don’t worry if some things described in this chapter don’t make sense, or if you don’t understand some of the syntax or terms used. Everything covered here will be elaborated in much greater detail throughout the rest of the book.
Download the latest version of the lein
script
from the Leiningen GitHub
page, and save it to a location on your system’s PATH
(typically ~/bin
or
/usr/local/bin
).
Set the script to be executable (e.g., chmod +x
./lein
).
Run the script (e.g., ./lein
). Leiningen will
automatically download everything it needs to function
properly.
That’s it! You’re now ready to use Leiningen.
Download the lein.bat
file from the Leiningen GitHub
page, and save it to your hard drive.
Install either wget
or curl
. These are
programs that the Leiningen batch script can use to automatically
download the rest of its dependencies.
Run lein.bat
, passing it the
self-install
argument (.lein.bat
self-install
). Leiningen will download the rest of its
dependencies and finish installing itself.
That’s all! Leiningen is now installed on your Windows system.
Leiningen does not yet support building ClojureScript code on its
own. Fortunately, thanks to its plug-in system, using the
lein-cljsbuild plug-in for ClojureScript development
is easy: just reference it in the :plugins
key of your
project.clj
build configuration (demonstrated below).
Before you can use lein-cljsbuild, you’ll need to create a Leiningen project (if you don’t have one already). In your command console, switch to a directory of your choice, then type:
lein new hello-world
This will generate a new directory prepopulated with some default
files. It should contain a project.clj
file, which initially
will look something like this:
(defproject hello-world "0.1.0-SNAPSHOT" :description "FIXME: write description" :url "http://example.com/FIXME" :license {:name "Eclipse Public License" :url "http://www.eclipse.org/legal/epl-v10.html"} :dependencies [[org.clojure/clojure "1.4.0"]])
To enable lein-cljsbuild, you’ll need to add
two lines: a :plugins
key adding
lein-cljsbuild to the project, and a
:cljsbuild
key containing build configurations (which will
start out empty). Once you’ve added them, your project.clj
should look something like the following:
(defproject hello-world "0.1.0-SNAPSHOT" :description "FIXME: write description" :url "http://example.com/FIXME" :license {:name "Eclipse Public License" :url "http://www.eclipse.org/legal/epl-v10.html"} :dependencies [[org.clojure/clojure "1.4.0"] [org.clojure/clojurescript "0.0-1450"]] :plugins [[lein-cljsbuild "0.2.7"]] :cljsbuild {:builds []})
Note that on a new project, you should specify whichever versions of
Clojure, ClojureScript, and lein-cljsbuild are most
recent (at the time of writing, this is 1.4.0, 0.0-1450, and 0.2.7,
respectively, as shown in the example project.clj
).
The fastest way to start writing ClojureScript code is to fire up the REPL. For those not already familiar with the concept of a REPL from Clojure or another Lisp, REPL stands for Read Eval Print Loop, and is similar to a shell console in other languages because it can be used to program interactively. It works by successively reading text input into Lisp data structures, evaluating them in the running environment (via compilation to JavaScript, in ClojureScript’s case), printing the results of the expression back to the console, and looping back and waiting for more input.
To start a basic REPL in a lein-cljsbuild project, type the following at the command line from anywhere in the project’s directory structure:
lein trampoline cljsbuild repl-rhino
This statement deserves some unpacking:
lein
invokes the Leiningen build system.
trampoline
is some ceremony Leiningen requires
for running tasks with interactive user input in the console.
cljsbuild
invokes the
lein-cljsbuild plug-in.
repl-rhino
specifies that you’ll use the
Rhino REPL. Rhino is a headless JavaScript
engine that runs on the JVM, which is convenient for basic
experimentation with ClojureScript.
Once the REPL starts up, you should see the ClojureScript REPL prompt:
ClojureScript:cljs.user>
Type a ClojureScript expression (for example, the
println
function to print to standard out in Rhino), and
press Enter to evaluate it:
ClojureScript:cljs.user> (println “Hello, world!”) Hello, world! nil
You will immediately see the string you specified printed, and the
return value of the expression (which is nil
, in the case
of println
).
You can use the Rhino REPL like this to explore any of ClojureScript’s basic syntax and standard libraries.
To add a ClojureScript file to your Leiningen project, you’ll want to make a few tweaks to your project directory layout. Initially, your project layout will look something like this:
- hello-world/ - README.md - project.clj - src/ - hello_world/ - core.clj
(Note that test files and folders are omitted for clarity, but you should definitely write unit tests wherever appropriate.)
Since this default structure is designed around having only one type of source code (Clojure), you’ll want to modify the directory structure slightly, to match the following:
- hello-world/ - README.md - project.clj - src/ - clj/ - hello_world/ - core.clj - cljs/ - hello_world - resources/ - public/
As you can see, the src
folder now has two
subfolders, one for each type of source code. You’ll need to add a
:source-paths
configuration key to your
project.clj
file to reflect the new location of the
Clojure source code (see the example below for what the new
project.clj
file will look like). You will also need to
create a folder in which to place the compiled JavaScript:
resources/public
is a common choice.
Then, you must add a build entry in the :cljsbuild
configuration map in project.clj
:
(defproject hello-world "0.1.0-SNAPSHOT" :plugins [[lein-cljsbuild "0.2.7"]] :dependencies [[org.clojure/clojure "1.4.0"] [org.clojure/clojurescript "0.0-1450"]] :source-paths ["src/clj"] :cljsbuild { :builds [{ :source-path "src/cljs" :compiler { :output-to "resources/public/hello.js" :optimizations :whitespace :pretty-print true}}]})
The :source-path
key specifies where the build
looks for ClojureScript source files, and the :output-to
key of the :compiler
option map specifies where the
ClojureScript compiler will emit compiled JavaScript files. Other
compiler options will be explained in more detail in the next chapter:
for now, just use the ones provided.
Finally, write a ClojureScript file! You can start with
something very simple, intended to be run in a browser. The following
ClojureScript file just declares a namespace, and then prints out
“Hello World” using the document.write
JavaScript
function. Place it in a file named hello.cljs
in the
src/cljs/hello_world/
folder (named
to match the namespace you declared) in your ClojureScript source
folder.
(ns hello-world.hello) (.write js/document "<p>Hello, world!</p>")
Your Leiningen project is now fully configured to compile
ClojureScript. Try compiling your ClojureScript by invoking the
lein cljsbuild once
command from the command line,
anywhere inside your Leiningen project folder. You should see a status
message about successfully compiling
resources/public/hello.js
. If you like, you can inspect
the emitted JavaScript file: Be aware, though, that it also includes
the core ClojureScript runtime and parts of the standard library, so
it’s quite long. See the next chapter for details of how this process
works.
You might also want to try running lein cljsbuild
auto
. This will keep a process open that will watch all the
*.cljs files in the specified source directories,
and whenever one is saved, it will recompile it automatically and
replace the output file.
You should also be aware of the lein cljsbuild
clean
command, which will delete all the compiled JavaScript
files. By default, lein-cljsbuild will not
recompile a file unless it detects that the file has been changed by
comparing timestamps. Sometimes, however, it’s useful to force a
recompile by wiping all the compiler output and restarting with a
clean slate.
If you’ve written a ClojureScript file as described in the
previous section, all you need to do to see it run in a browser is to
write an HTML file that includes the emitted JS files in the standard
way. It is common practice to place static HTML files in
resources/public
.
<html> <head><title>ClojureScript Hello World</title></head> <body> <script type="text/javascript" src="hello.js"></script> </body> </html>
Open this file in the browser, and you should see your greeting,
as coded in your hello.cljs
file. If you’re running
lein-cljsbuild in automatic mode, simply edit the
message in hello.cljs
, save the file, and refresh the
browser to see your change.
Note that in addition to this basic compilation, lein-cljsbuild provides several other useful development tools and options. These include:
Multiple ClojureScript builds with different options.
Launching the browser REPL.
Cross compiling the same code as both Clojure and ClojureScript (provided it meets certain requirements).
See Chapter 9 for full instructions on all the configuration options and features available.