Chapter 2. Hello World

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

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.

Installing Leiningen on OS X and Linux

  1. 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).

  2. Set the script to be executable (e.g., chmod +x ./lein).

  3. 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.

Installing Leiningen on Windows

  1. Download the lein.bat file from the Leiningen GitHub page, and save it to your hard drive.

  2. Install either wget or curl. These are programs that the Leiningen batch script can use to automatically download the rest of its dependencies.

  3. 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.

Using lein-cljsbuild

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).

Getting Started with the REPL

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.

Compiling a ClojureScript File to JavaScript

Structuring the Leiningen project

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.

Updating the project configuration

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.

Writing a ClojureScript file

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>")

Compiling

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.

Running ClojureScript in the Browser

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.

Other Capabilities of lein-cljsbuild

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.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset