Skip to content

Setup for development

ozzy edited this page Mar 28, 2021 · 5 revisions

There are different options to optimize your development workflow:

  • Reload namespaces on source file changes
    • Setup with lein-ring plugin
    • Setup with boot
  • Use a module lifecycle library Interactive Development

The first approach is fast, simple to setup. The ring-devel library provides middleware for this purpose.

Downside, namespace reloading does not reload application state. Consequently, there can be situation requiring to restart the server.

Setup using the lein-ring plugin

The Lein-Ring plugin is the most straightforward way. Create two files

  • src/sample.clj
  • project.clj

A simple service returning 'Hello World' in src/sample.clj

(ns sample)

(defn handler [request]
  {:status 200
   :headers {"Content-Type" "text/plain"}
   :body "Hello world."})

Add lein-ring and configure the ring handler to your project file, project.clj:

:ring {:handler sample/handler}

A minimal project.clj:

(defproject lein-demo "0.1.0-SNAPSHOT"
  :dependencies [[org.clojure/clojure "1.8.0"]
                 [ring/ring-core "1.6.3"]
                 [ring/ring-jetty-adapter "1.6.3"]
                 [ring/ring-devel "1.6.3"]]
  :ring {:handler sample/handler}
  :plugins [[lein-ring "0.12.5"]])

Start a development server:

  lein ring server    

Visit the server at http://localhost:3000

The server will automatically reload any modified files in your source directory.

Setup using boot

Boot is a build tool for Clojure', https://boot-clj.github.io/

Create two files

  • build.boot
  • src/sample.clj

A minimal build.boot

(set-env!
  :resource-paths #{"src"}
  :dependencies '[[org.clojure/clojure "1.8.0"]
                  [ring/ring-core "1.6.3"]
                  [ring/ring-jetty-adapter "1.6.3"]
                  [ring/ring-devel "1.6.3"]])

(deftask dev
  "Run server hot reloading Clojure namespaces"
  [p port PORT int "Server port (default 3000)"]
  (require '[sample :as app])
  (apply (resolve 'app/run-dev-server) [(or port 3000)]))

A simple service returning 'Hello World' without reloading in src/sample.clj

(ns sample
  (:require
   [ring.adapter.jetty :refer [run-jetty]]))

(defn handler [request]
  {:status 200
   :headers {"Content-Type" "text/plain"}
   :body "Hello world"})

(defn run-dev-server
  [port]
  (run-jetty handler {:port port}))

Inspect your boot task

boot dev -h

Run the server

boot dev

Visit http://localhost:3000

Next, we can add hot reloading. Check that the dependencies in build.boot include ring/ring-devel. Wrap the handler into a wrap-reload handler.

(ns sample
  (:require
   [ring.adapter.jetty :refer [run-jetty]]
   [ring.middleware.reload :refer [wrap-reload]]))

(defn handler [request]
  {:status 200
   :headers {"Content-Type" "text/plain"}
   :body "Hello world"})

(def dev-handler
  (wrap-reload #'handler))

(defn run-dev-server
  [port]
  (run-jetty dev-handler {:port port}))

Restart the server and visit http://localhost:3000

Now, the server will automatically reload any modified files in your source directory.

Clone this wiki locally