Hi Jag, Would love to learn more about your approach. I have just gotten started with shadow-cljs. I read about Stasis some time ago but havent actually used it.
TIA, Ray On Monday, April 27, 2020 at 8:24:22 PM UTC+8, Jag Gunawardana wrote: > > Thanks Gary for posting this up. Was a great help for a slightly different > use case. I was using static site generators like Hugo, but always found > that I ended up having to learn their internals/templating to make larger > changes. I also wanted to use Clojurescript and it was painful to do so. I > made a few changes: > > I used the Stasis library to turn my hiccup and assets into a static site > (but serve up with Ring in development). > I used shadow-cljs to compile my Clojurescript. > I also use deps.edn rather than Lein (even though Lein still feels easier). > My final artifact was a largely static website, packaged up into an Nginx > docker. I have a small amount of clojurescript which gets built into one > main.js file. > > I can post up the details/a repo if anyone else wants to do similar. > > I always feel that you can do pretty much anything with Clojure(script), > but sometimes there is a bit of a dark art to getting there. I think I > would use this approach for any site that I would have used a static site > generator for now. > > > On Monday, 9 July 2018 17:14:22 UTC+1, Gary Johnson wrote: >> >> 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. To view this discussion on the web visit https://groups.google.com/d/msgid/clojure/45ca024f-d4cb-4e02-97dc-771c02ab4e3c%40googlegroups.com.