There are several leiningen templates to create a basic web application in Clojure. But in this post, I will describe how you can create a basic web application that uses Clojure on the backend and ClojureScript on the front-end. The goal is to help understand all the pieces that are involved and how they need to come together so that you can better understand what some of the templates are actually doing it under-the-hood.
Web Development in Clojure is more about using several libraries - so basically pick your liking => too many things to worry about but it is how it is. There are a few single frameworks but this is more about the former.
So what do we need on the server? On the server-side, for a basic web application, we will need a server to serve static/dynamic content based on the URI for the specific resource. In clojure, web servers are usually “ring-compliant” => which basically means they respect and work with Ring specification. So in all, we will use the following:
Oh, we will use Cursive as our IDE - which is totally awesome.So lets get started.
We will create a leiningen application called groupie.
Once the project is created, import the project into Cursive. If you look at the project.clj; you will find it to be a very simple clojure application. So lets add dependencies to project.clj for Ring, Http-kit and compojure. You can visit the links to get the latest version numbers. After this, my project.clj looks like
(Ignore the project name “groupie” in the defproject. It should be webapp, the name I gave in the lein new command).
As you modify project.clj, you can refresh it within the IDE by View->Tool Windows->Leiningen and then “refresh” icon or you can associate a keymap to the specific action. This, I believe, is equivalent to run “lein deps” from the command line.
Once the project.clj is updated to include the dependencies, lets add a server to our application.
The server.clj added to the source folder could be something like shown below.
There are four methods in the server.clj
Add an index.html to “resources\public” folder in the project (create public folder if unavailable). Then lein run passing the parameters. Test if everything works. For index.html, the file will be server and for any other request - you will simply see Hello World message.
So far, we made use ring middleware, a ring compliant web-server using http-kit & we can serve one request and static content. Now we will make use of compojure to define routes & update the app middleware pipeline.
Now, lets add clojurescript to the project. To do that, we will add clojurescript to the dependencies & add cljsbuild to the :plugins. Then, we define instructions/configuration of the cljsbuild within the defproject. The updated project.clj would look like:
Create folder called “cljs” within src (so as to match what we defined in the project.clj). A very simple client.cljs file would be added.
If you remember, earlier we added the middleware “wrap-reload” in the app to support reload of the changes on the server without rebooting the server. It would be nice if we can make clojurescript changes & the browser gets reloaded without having to manually refresh. This exact same behavior is provided via the “figwheel” plugin. Adding support to figwheel is straight-forward.
Apart from the above, we also adjust the project’s :output-dir to indicate that is where we want it to output the generated js files. The project.clj would look like:
Now, to finish the integration of figwheel, we will update the cljs file to include a call to figwheel’s watch-and-reload.
The index html would be updated as shown below. You will have to require the project cljs file in the script snippet.
The final repository is added to my github at this version.
There are a few more nuances about making REPL work in Cursive - both on the server and on the client. Hopefully, I will write about it in the future when I have a fully working solution that is easy to setup and that works both on command line and from cursive.