Setting up to use ClojureScript

The only thing that's missing is JavaScript. We can also generate this with ClojureScript (https://github.com/clojure/clojurescript). This is an implementation of Clojure that compiles to JavaScript.

Why will we want to write JavaScript in Clojure? First, it simplifies your project when both the client and the server are written in the same language. It also allows you to share code between the two sides of your application, which can cut down the complexity of your code as well as the lines of code.

For the rest of this chapter, we'll be creating charts and graphs using ClojureScript. These recipes will show you how to install ClojureScript and get it working. We'll take the web application we started in the Serving data with Ring and Compojure and Creating HTML with Hiccup recipes and add an alert to the index page. This isn't anything more than a hello world application, but this will prove that ClojureScript is working in our application.

Getting ready

To add ClojureScript to our project, we'll first add a dependency on ClojureScript. Now, this is how the :dependencies section of the project.clj file will look:

  :dependencies [[org.clojure/clojure "1.6.0"]
                 [ring/ring-core "1.3.1"]
                 [ring/ring-jetty-adapter "1.3.1"]
                 [compojure "1.2.0"]
                 [hiccup "1.0.5"]
                 [org.clojure/clojurescript "0.0-2371"]]

Next, we'll add the lein-cljsbuild plugin to our Leiningen project.clj file. Now, our :plugins directive should look similar to this:

  :plugins [[lein-ring "0.88.3"]
            [lein-cljsbuild "11.0.3"]]

How to do it…

To set up ClojureScript, most of what we need to do is configuration. We have to tell the ClojureScript compiler where to find the input and where to put the output. We'll go into details on this in a minute.

  1. First, we'll just add this key-value pair to our project.clj configuration file:
      :cljsbuild {:builds
                  [{:source-paths ["src-cljs"],
                    :compiler
                    {:pretty-print true,
                     :output-to "resources/js/script.js",
                     :optimizations :whitespace}}]}
  2. Now, let's go to the command prompt and create the directories we'll use:
    $ mkdir -p src-cljs/webviz
    $ mkdir -p resources/js
  3. Create the src-cljs/webviz/core.cljs file. This will look a lot like a regular Clojure file:
    (ns webviz.core)
    (defn ^:export hello [world]
      (js/alert (str "Hello, " world)))
  4. From the command line, enter this command. This will start the ClojureScript compiler that watches all the ClojureScript files and automatically compiles them whenever we save one:
    $ lein cljsbuild auto
    Compiling ClojureScript.
    Compiling "resources/js/scripts.js" from "src-cljs"...
    Successfully compiled "resources/js/script.js" in 4.707129 seconds.
  5. Next, we'll add our compiled ClojureScript file to our Hiccup template. Let's open src/web_viz/web.clj again and change the index-page function to look as shown here:
    (defn index-page []
      (html5
        [:head
         [:title "Web Charts"]]
        [:body
         [:h1 {:id "web-charts"} "Web Charts"]
         [:ol
          [:li [:a {:href "/data/census-race.json"}
                "2010 Census Race Data"]]]
         (include-js "js/script.js")
         (javascript-tag 
           "webviz.core.hello('from ClojureScript!'),")]))

Now when we start the Ring server and look at the main page, we should see the following screen:

How to do it…

How it works…

A lot took place in this recipe, and there's a lot that we need to talk about in a little more detail.

First, we need to talk about ClojureScript. If we open up the generated file, resources/js/script.js, we'll see a lot that's not in our code. Why is there so much more in there?

The explanation is pretty simple. ClojureScript doesn't just target JavaScript as a compilation platform. It targets the Google-Closure-compiler-advanced-mode JavaScript. Because of this, it includes most of the Google Closure libraries, so we have these immediately available, and we'll use them in the upcoming recipes. Also, we can run our output through the Closure compilers by changing the :optimizations parameter in the :cljsbuild options, and it will shake out the parts of the code that we don't use. This not only includes our code but also the parts of the Clojure libraries and the Google Closure libraries that we don't use. In the end, this is a huge win. Unfortunately, not all libraries can be used with the Closure compiler's advanced mode; D3, for example, requires a file that lists all the functions it exports. The d3-externs project (https://github.com/shripadk/d3-externs) is an attempt to provide this interface file for the Closure compiler.

Also, note that the hello function is annotated with the ^:export metadata. This signals the ClojureScript compiler that it needs to make this function available to the outside world. This is a good, lightweight way of enforcing scoping according to JavaScript's best practices.

Also, inside the hello function, the alert function is called from the js namespace (js/alert). This namespace represents the global JavaScript context. Whenever we call a JavaScript object from the global context (when working in the window browser), we have to prefix it with the js/ namespace in ClojureScript.

Next, we should take a look at the :cljsbuild configuration in the project.clj file. This configuration section defines the build information. In this case, we tell it to compile everything in src-cljs/ to js/script.js.

Finally, I will also make a note here about the workflow. If you're keeping count, you probably have at least three terminal or console windows open. One for the Ring server, one for the ClojureScript compiler, and one or more for the REPL or shell to work in. That's what I have going right now. If you can use a terminal multiplexer such as tmux (http://tmux.sourceforge.net/) or Screen (http://www.gnu.org/software/screen/), this can simplify things. You can set the Ring server and ClojureScript compiler running in a background window and just check them for errors periodically.

There's more…

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

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