At work we use
deps.edn for everything and we have many Clojure web apps. Mostly they use either
jetty (and we can actually choose which one to start at runtime, based on an environment variable).
Our workflow is usually to start the server process from within the REPL. We use Stuart Sierra’s Component library to manage the
stop lifecycle of the web server (and everything else in our app). Mount uses global state – it’s “easy” but not “simple” (because global, mutable state is never simple). Component and Integrant avoid global state so they are “simple” but not quite as “easy”.
We typically have a
(comment ,,,) form at the bottom of each main namespace that contains Clojure expressions that we can evaluate to create and
start the Component for the app (mirroring what happens in
-main but usually simpler – omitting monitoring agents etc).
Having started the server process, we edit code and evaluate it into the running app as we make each change. We don’t need to “reload” anything – we don’t need
tools.namespace, we rarely
stop the running component (although we can easily do so since we
def it into a global purely for working in the REPL).
This example project might help you understand how we work: https://github.com/seancorfield/usermanager-example/