I'm experimenting with different ways to organize a Clojure/ClojureScript Monorepo using the Clojure CLI Tools.
NOTE: My monorepo contains CLJ and CLJS projects
I started with Monorepo Version 1. Everything worked perfectly. I had to move off this because extra-paths
no longer allows paths to specify files outside of the project. Why was I adding :extra-paths
from outside my project? My Clojure project in a Clojure webserver. The other project is a CLJS front end app. During dev, I need my compiled CLJS (JS) to be served by my web server (app-server
). That's why it had :extra-path
of resources
and target
.
This document now explores the different approaches I found of tackling this issue:
├── packages
│ ├── app-client
│ │ ├── deps.edn # aliases, deps, paths
│ │ ├── resources/
│ │ ├── target/
│ │ ├── src/
│ ├── app-server
│ │ ├── deps.edn # aliases, deps, paths
│ │ ├── resources/
│ │ ├── src/
app-client
- contains all the frontend code:
html
,css
(resources/) andcljs
(src/) andcompiled cljs
(target/) - CLJS compiles to js and output-to
target
dir - ratonale: No need for front end dev to be in same dir as backend (separate concerns)
- contains all the frontend code:
app-server
- has
:extra-paths
toapp-client
:resources/
,target/
. This enables me to dev front end inapp-client
and haveapp-server
pickup all of the changes.
- has
├── packages
│ ├── app-client
│ │ ├── deps.edn # aliases, deps, paths
│ │ ├── resources/
│ │ ├── target/
│ │ ├── src/
│ ├── app-server
│ │ ├── deps.edn # aliases, deps, paths
│ │ ├── resources/
│ │ ├── src/
The structure for the above is the same as in Monorepo Version 1. The difference is that I update app-client/deps.edn
to have the top-level :paths
key to include resources
and target
:
;; app-client/deps.edn
{:paths ["src" "resources" "target"]
;; ...
}
and then in app-server
I add a :dep
in the :dev
alias like this:
{:paths [...]
:deps {...}
:aliases
{:dev
{:deps {app-client/app-client {:local/root "../app-client"}}}}
This get's rid of the warnings and makes all of my dev JS artifacts and front end assets accessible to app-server
without getting any of the warnings.
Possible Cons
target
is always being made available inapp-server
.
This version is inspired by Sean Corfield's deps.edn monorepo.
├── packages
│ ├── app
│ │ ├── deps.edn # deps only
│ │ ├── node_modules/
│ │ ├── resources/
│ │ ├── target/
│ │ ├── src/
│ ├── app-server
│ │ ├── deps.edn # deps only
│ │ ├── resources/
│ │ ├── src/
│ ├── deps.edn # NEW! aliases, paths
In the above structure, the difference when compared to the other versions:
- Each package has it's own
deps.edn
with justdependencies
- The
packages
dir get's it's owndeps.edn
file which hasaliases
andpaths
What's the challenge? If you run figwheel.main
from the root of the packages
dir you will need to:
- add the module name infront of resources in the build.edn file
- specify the
:target-dir
- and figure out a way to make
node_modules
visible to the cljs compiler. no possible right now.- The CLJS compiler could be updated to allow customizations, but not a high priority for the team. (understandably)
The last point is the main blocker right now.
current issue
- moving the CLJS packages figwheel-main commands to the top level might not be possible (still investigating)
It's the same as version 3, but in order to improve the developer experience we add babashka tasks because:
- Avoid verbose and error prone CLI invocations
- Improve discoverable commands
- Consistent project commands
- Give the appearence of all commands being controlled from the packages dir (CLJS projects)
- Configuring env variables through bb