Saturday, April 21, 2012

Hello World in ClojureScript

Hello CLJS

Edit October 18, 2013

If you want to get started with ClojureScript I highly recommend that you read Mimmo Cosenza's series of tutorials at https://github.com/magomimmo/modern-cljs . This is the best resource I have found on learning ClojureScript. Please check it out, and don't waste a second reading my old post.

There is probably no reason to keep the original text, but in case there is some value in it I have overlooked, I will leave it unchanged.


I have wanted to learn about ClojureScript, but I haven't known where to start. Like so much in Clojure it turns out to be much simpler than I expected. The instructions for the various projects are each very clear, but I still found it overwhelming at first. Rather than go into detail, I will try to give an overview and link to the related projects.

The appeal of JavaScript, and thus ClojureScript, is that it can be used in so many ways. For example, you can use cljs to do client-side programming in a traditional web application, to do all of the dynamic code in a single page web app, or to do server side scripting in node.js.

Overview

ClojureScript, wherever you use it is compiled to JavaScript. It is the .js file generated by the compiler that you will refer to in your application.

While it is possible to use the ClojureScript compiler directly, the recommended method is to use lein-cljsbuild. If you are creating a new noir web application that you want to use ClojureScript with you can use the cljs-template which will install and configure lein-cljsbuild for you. For anything but a brand new noir project, you will need to set up lein-cljsbuild yourself.

Again, following the instructions on lein-cljsbuild is all you need to do, but I like to see the big picture before I get to the details.

To install cljs-build you add a reference to it with a :pluggins tag on an existing project that you created with leiningen. Configure the plugin by adding :cljsbuild tag, also in the project definition. specifying a path to your ClojureScript source files. If you are writing scripts to use in node.js you will need to specify :target :nodejs in the compiler options. Leiningen will actually install the plugin the first time you try to compile your script files.

Example

I will do a quick walkthrough, to make sure everything is working. I am going to create a very basic script that simply displays an alert when a page is loaded. I will then create a simple html file that will host that script.

My instructions will be very similar to the instructions in the lein-cljsbuild read me, except that I structure my source and destination folders a little differently. Assuming you have Leiningen 1.7 or later installed at the terminal create a new project:

lein new hello-cljs
cd hello-cljs

Edit the project.clj file, adding a :pluggins tag and setting the build options:

(defproject hello-cljs "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.3.0"]]
  :plugins [[lein-cljsbuild "0.1.8"]]
  :cljsbuild {
             :builds [{
                       :source-path "src-cljs"
                       :compiler {
                                  :output-to "web/js/main.js"
                                  :optimzations :whitespace
                                  :pretty-print true}}]})

Create a src-cljs directory, and in it create a file called main.cljs. Your main.cljs should contain the following:

(ns hello-cljs.main)

(js/alert "Hello from ClojureScript.")

From your project's root directory compile the ClojureScript to javascript by typing:

lein cljsbuild once

Compiling will create the destination folders, if they do not already exist.

Go to your web directory, and create a file hello.html:

<html>
 <head>
    <title>Hello CLJS</title>
  </head>
  <body>
    You should have seen an alert if everything is working.
    <script type="text/javascript" src="js/main.js"<>/script>
  </body>
</html>

Not a project that will win any awards, but it is nice to know you are set up correctly.

I wanted to mention one additional thing. In this example we compiled the cljs file to js using the command "lein cljsbuild once". Instead, you can use the command "lein cljsbuild auto" and cljsbuild will monitor your cljs source code directory and recompile any file that changes. Another good option to know is "lein cljsbuild clean" which will delete the compiled js file.

2 comments:

  1. Hi Rick thanks for sharing.
    I got an error building the script :

    $ lein cljsbuild once
    Compiling ClojureScript.
    Exception in thread "main" java.lang.NoClassDefFoundError:
    Caused by: java.lang.ClassNotFoundException:
    at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
    lein cljsbuild once 10,45s user 0,93s system 120% cpu 9,410 total

    any idea ?

    ReplyDelete
    Replies
    1. Hi Jean-Sébastien,

      I am sorry that you had an error. I did all of my testing on Leiningen version 1.7 on OSX. What version of Leiningen are you using, and is it working otherwise, for example does lein repl work? If you think it would be easer you can email me at rickhall2000 at hotmail dot com. When we find a solution we can come back and added to the comments for other people to see.

      Rick

      Delete