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
targetdir - 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-pathstoapp-client:resources/,target/. This enables me to dev front end inapp-clientand haveapp-serverpickup 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
targetis 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, pathsIn the above structure, the difference when compared to the other versions:
- Each package has it's own
deps.ednwith justdependencies - The
packagesdir get's it's owndeps.ednfile which hasaliasesandpaths
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_modulesvisible 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