Howdy Clojurians, I recently started developing a new Clojure+Clojurescript web application, and I wanted to see if I could set up my development environment using just the Clojure CLI tools. After a good deal of digging around through tutorials on a number of different websites and a fair amount of experimenting, I've managed to create a very simple (IMHO) configuration that provides me with both development and production mode CLJS->JS compilation, development and production mode ring handlers, and the always delightful FIgwheel development environment all from just the simple "clojure" command. Since I haven't seen this before, I thought I'd share it with all of you in case it helps someone else out there who doesn't need (or want) all of leiningen or boot to develop a simple web app.
Here goes: Step 1: Create your project structure like so: ├── cljsbuild.edn ├── deps.edn ├── figwheel.edn ├── resources │ └── public │ ├── cljs │ ├── css │ │ ├── style.css │ ├── images │ └── js ├── src │ ├── clj │ │ └── my_project │ │ ├── handler.clj │ │ ├── server.clj │ │ ├── views.clj │ └── cljs │ └── my_project │ ├── client.cljs Step 2: Make the deps.edn file (replace :deps and my-project.server namespace as necessary for your project) {:paths ["src/clj" "resources"] :deps {org.clojure/clojure {:mvn/version "1.9.0"} org.clojure/clojurescript {:mvn/version "1.10.312"} ring {:mvn/version "1.7.0-RC1"} ring/ring-defaults {:mvn/version "0.3.2"} prone {:mvn/version "1.6.0"} compojure {:mvn/version "1.6.1"} hiccup {:mvn/version "1.0.5"} reagent {:mvn/version "0.8.1"}} :aliases {:run {:main-opts ["-m" "my-project.server"]} :cljsbuild {:extra-paths ["src/cljs"] :main-opts ["-m" "cljs.main" "-co" "cljsbuild.edn" "-c"]} :figwheel {:extra-deps {org.clojure/tools.nrepl {:mvn/version "0.2.13"} cider/cider-nrepl {:mvn/version "0.17.0"} com.cemerick/piggieback {:mvn/version "0.2.2"} figwheel-sidecar {:mvn/version "0.5.14"}} :main-opts ["-e" "(use,'figwheel-sidecar.repl-api),(start-figwheel!)"]}}} Step 3: Make the cljsbuild.edn file (replace :main for your project) {:main "my-project.client" :output-dir "resources/public/cljs" :output-to "resources/public/cljs/app.js" :source-map "resources/public/cljs/app.js.map" :optimizations :advanced :pretty-print false} Step 4: Make the figwheel.edn file (replace :ring-handler, :on-jsload, and :main for your project) {:nrepl-port 7000 :nrepl-middleware ["cider.nrepl/cider-middleware" "cemerick.piggieback/wrap-cljs-repl"] :server-port 3000 :ring-handler my-project.handler/development-app :http-server-root "public" :css-dirs ["resources/public/css"] :builds [{:id "dev" :source-paths ["src/cljs"] :figwheel {:on-jsload "my-project.client/mount-root"} :compiler {:main "my-project.client" :output-dir "resources/public/cljs/out" :output-to "resources/public/cljs/app.js" :asset-path "/cljs/out" :source-map true :optimizations :none :pretty-print true}}]} Step 5: Write server.clj (ns my-project.server (:require [ring.adapter.jetty :refer [run-jetty]] [my-project.handler :refer [development-app production-app]]) (:gen-class)) (defonce server (atom nil)) (defn start-server! [& [port mode]] (reset! server (run-jetty (case mode "dev" #'development-app "prod" #'production-app #'production-app) {:port (if port (Integer/parseInt port) 3000) :join? false}))) (defn stop-server! [] (when @server (.stop @server) (reset! server nil))) (def -main start-server!) Step 6: Write handler.clj (ns my-project.handler (:require [ring.middleware.defaults :refer [wrap-defaults site-defaults]] [ring.middleware.reload :refer [wrap-reload]] [prone.middleware :refer [wrap-exceptions]] [compojure.core :refer [defroutes GET]] [compojure.route :refer [not-found]] [my-project.views :refer [render-page]])) (defroutes routes (GET "/" [] (render-page)) (not-found "Not Found")) (def development-app (wrap-reload (wrap-exceptions (wrap-defaults #'routes site-defaults)))) (def production-app (wrap-defaults #'routes site-defaults)) Step 7: Write views.clj (ns my-project.views (:require [hiccup.page :refer [html5 include-css include-js]])) (defn render-page [] (html5 [:head [:title "My Project"] [:meta {:charset "utf-8"}] [:meta {:name "viewport" :content "width=device-width, initial-scale=1" }] (include-css "/css/style.css") (include-js "/cljs/app.js")] [:body [:div#app] [:script {:type "text/javascript"} "my_project.client.mount_root();"])) Step 8: Write client.cljs (replace Reagent with whichever front-end library you prefer) (ns my-project.client (:require [reagent.core :as r])) (defn root-component [] [:div [:h1 "Hello world!"]]) (defn ^:export mount-root [] (r/render [root-component] (.getElementById js/document "app"))) Step 9: Write some CSS in resources/public/css/style.css #app { border: 2px solid green; } Step 10: Try out your new dev tools! At this point, your project setup is complete, and you are ready to start developing your awesome new Clojure+Clojurescript web app. You have the following 3 project management commands available at your command prompt: *1. Compile Clojurescript to Javascript* To compile the Clojurescript files under src/cljs to Javascript under resources/public/cljs, navigate to the toplevel project directory and run: $ clojure -A:cljsbuild The main Javascript entry point file will be written to resources/public/cljs/app.js. The Clojurescript build options are read from the toplevel cljsbuild.edn file. They are set to use advanced compilation mode for a production build. *2. Run your Web Application * To compile and run your web application, navigate to the toplevel project directory and run: $ clojure -A:run [port] [dev|prod] The website will then be available at http://localhost:3000 or on whichever port you specified. In dev mode, server-side exceptions will be displayed in the browser and Clojure source files will be reloaded whenever you refresh the page. These features are disabled in prod mode. If the second argument to run is omitted, it will default to prod mode. *3. Launch Figwheel* To start the Figwheel server, navigate to the toplevel project directory and run: $ clojure -A:figwheel This will start an http-kit webserver on http://localhost:3000, which serves up the website in dev mode. It will also open an nREPL on port 7000, which provides the special command "(cljs-repl)" to switch from a Clojure REPL to a Clojurescript REPL. Finally, any changes to CLJS or CSS files will automatically be pushed to the browser when the files are saved. Okay, folks. That's all from me for now. Setting this all up was quite an interesting learning exercise, but I'm very happy with the results. I hope someone out there finds this setup useful for your next Clojure project. If someone has the power to add this tutorial to the Clojure website (or other documentation site), I think it would be a great addition. Also, someone should definitely make a *clj-new* project template from this setup. *I'm looking at you, Sean Corfield.* ;-D Have fun, everyone, and happy hacking! ~Gary -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.