polylith

2025-05-06T20:07:27.977419Z

We're in the process of migrating to polylith and have gotten everything pretty figured out, except for the clojurescript part. We have 4 different clojurescript builds, that all have to be loaded from a resources folders served up by a reitit backend. Should we be putting all the clojurescript builds into one basis, or separate them out into their own basis for each build, or one project, or separate projects for each? We're on the clojurescript branch of polylith but we're still not unsure how to structure things. Thanks!

DenisMc 2025-05-12T21:10:12.912719Z

Im not sure if its best practice, but I have my cljs project in one base and the ring api in another, the build.clj ensures that a) shadowcljs builds the prod artifact and b) the artifact is in a known location on the classpath, and then within ring I have configured static routes to match the required paths (i.e. the JavaScript file location and the css file location, which is tailwind in my case). One additional feature of my setup is that my ring route dynamically generates the index.html file used by the cljs build, as I need to dynamically set some og: tags based on the request url.

2025-05-12T22:29:53.127229Z

@denis.mccarthy.kerry thanks! could you please elaborate on what "a known location on the classpath" means? is it the resources folder on the ring base, or project, or somewhere else?

seancorfield 2025-05-06T20:32:04.924429Z

Disclaimer: I don't use ClojureScript but... My sense is that one of the core tenets of Polylith is to separate "apps" from "reusable components" and also separate out "builds". Apps are bases, builds are projects. I don't quite understand what you mean about "4 different clojurescript builds" but projects are where "builds" are described (and, generally, run), and they generally depend on one base and multiple components...

2025-05-06T21:18:51.219779Z

Hey Sean, yes, the clojure separation makes perfect sense to us with components and bases. For clojurescript, we're building 4 different shadow-cljs :builds, creating 4 different output javascript files. All 4 builds are frontend apps that do something different, but they all also all call some cljc files shared across the whole monolith. I think the core issue is that our backend webapp base has to serve all 4 output javascripts in a "resources" folder so they can be served by the backend. Thus, we're not sure how to structure the CLJS stuff.

DenisMc 2025-05-13T20:03:06.426849Z

I put it into /resources in the base, which in turn is copied to the project as part of the build.

msolli 2025-05-07T07:16:52.707279Z

You mention "our backend webapp". Since your CLJS builds will be built and deployed together with this backend, it seems you should put them in the same project as the backend. The builds, I mean. I don't know about the CLJS source code - do you put that in the base (the same base as the backend), or in separate components? It'd be interesting to hear, as we're journeying in the same direction at work (though with only one CLJS build).

2025-05-07T08:04:13.811599Z

@kanwei Maybe you are expecting that Polylith will do something with the cljs build process? I believe the clojurescript branch just adds things that don't exist in normal clj apps like :require-macros and support for cljs files to figure out the internal dependencies. I assume you will have to create a custom script that puts the builds of all your clojurescript projects into the resources dir of your backend app. Probably you can make this a bit more efficient by only having to do a build when something changed for those projects * So maybe you can share more if I am incorrect, but here it goes: I think you will need a base AND a project for each cljs project. Maybe only one base if they are really the same. Then you will need some scripts that put the builds in the right place(s). If you want to work on all the projects at the same time it might be more complicated (*) poly ws get:changes:changed-or-affected-projects

2025-05-07T17:31:10.394779Z

Yes, I was expecting some actual tooling around shadow-cljs, but it seems like the CLJS branch isn't really finished and some docs are lacking. For example the realworld-example-app has a "realworld-frontend" project, with a shadow-cljs.edn in it, but it doesn't actually do anything because you can delete it and the project still builds. https://github.com/furkan3ayraktar/clojure-polylith-realworld-example-app/blob/cljs-frontend/projects/realworld-frontend/shadow-cljs.edn

2025-05-07T17:36:59.783389Z

I do think it makes sense to have each CLJS build as its own base, question is then where do the generated JS files go? In the base's resources folder? How does the backend base then serve the files? And also, why do projects have a resource folder if they aren't supposed to have source codd?

2025-05-07T18:26:52.856359Z

I think I would create a script that would copy the js builds from the cljs projects to the resource folder of the backend base and serve the files from there. In order for the backend to serve updated files you would have to run this script every time there is a change. CI can check if the file that is checked in has the same checksum as the generated one. Just thinking out loud here maybe there are better solutions