shadow-cljs 2025-04-26

Hmm. I'm trying to figure out how to manage dependencies. I have a deps.edn with aliases for :dev and :prod, but it seems that shadow-cljs.edn lets me specify :deps only at the top level. I thought I could specify per-build dependencies, so for a :dev build I'd have :deps {:aliases [:dev]} and for a :prod build I'd have :deps {:aliases [:prod]}. But that doesn't seem to work.

I usually keep deps in deps.edn under aliases, and have :deps true in shadow config which tells shadow that deps are managed externally

Hmm. But my dev deps are different from production deps, and when I build one of the shadow-cljs :builds, how do I choose one set of deps over the other, if there is only a single :deps entry at the top level?

Aliases have :extra-deps field

generally it doesn't matter what your dependencies are. shadow-cljs only compiles what is actually required.

so it doesn't matter if you have dev dependencies active

shadow-cljs.edn does not allow you to set dependencies per build for that reason

also also because it requires launching a new JVM to swap dependencies

but if you must have that just go through clj directly

clj -M:my:extra:aliases -m shadow.cljs.devtools.cli release app is exactly the same as npx shadow-cljs release app with :deps {:aliases [:my :extra :aliases]} in shadow-cljs.edn. the :deps key is only used if the shadow-cljs command is used

👍 1

although I consider switching dependencies an anti pattern it works perfectly fine this way

also consider reading https://code.thheller.com/blog/shadow-cljs/2024/10/18/fullstack-cljs-workflow-with-shadow-cljs.html if you haven't. it described a more clj focused workflow, entirely without npm. so maybe more familiar

I have read this article, btw it's very good, thanks for writing it! It seems I will have to rethink the way my app is constructed. I currently have a different set of paths for dev and prod builds. So there is a source file that is different depending on whether the build is dev or prod. It seems this approach will not work with shadow-cljs and I need to find a different way.

it does work just fine as I said. I just don't recommend it

:release
  {:build-options
   {:ns-aliases
    {day8.re-frame.tracing day8.re-frame.tracing-stubs}}}}}}

so any require the code may have for day8.re-frame.tracing is swapped with the stubs instead

I'm thinking about dropping undertow in shadow-cljs and using jetty instead. the reasons I went with undertow are no longer valid and jetty is actually the better server these days. websocket support was kinda annoying 10 years ago, but now it seems fine. should have no impact apart from switching the dependencies and some internal code

👍 7

Have you taken into account the jdk-httpserver? is it too new for your use case? (jdk17+)

shadow is now java21+, so that is not a problem. last time I checked the thing was too simple and didn't support websockets?

also prefer something that knows how to serve files on its own

any consideration for http-kit (https://github.com/http-kit/http-kit)? zero deps, good websocket support.

also too basic. basically requires ring handlers for everything. no http2 support. not something I'd use in production.

also has bitten me in the past, so kinda not too keen to back to it. I'm sure its better now, but still

👍 1

Understood, it's certainly possible that jetty is a better choice for this use case. For the avoidance of fud, or at least for some counter-fud, we happily use http-kit in production (and have for 10+ years) on many mission critical projects.

If my app already uses Jetty could there be a conflict of versions?

Jetty is also frequently a subject of CVEs

conflict only if you run in embedded mode and not the current versions. I'd go with the latest release version and update regularly

CVEs mean the thing is getting used and bugs are "known". I'd expect undertow to have more unknown bugs

none of that is relevant for a local development tool that should never be reachable over the public internet anyway

undertow has some annoying warning spam on startup since java23 that is bugging me 😛