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 [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
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 [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/clojure/45ca024f-d4cb-4e02-97dc-771c02ab4e3c%40googlegroups.com.