shadow-cljs

magra 2025-04-14T08:44:47.316369Z

I would like a macro to elide and include different code on the server, in a webworker and in the browser ui. Can I use reader-features for this controlled by module, not by build, and if so how?

thheller 2025-04-14T08:48:52.241429Z

server/client sure. client/worker no, since that would require some kind of runtime knowledge?

thheller 2025-04-14T08:49:19.238289Z

and no reader features cannot be used for this at all

thheller 2025-04-14T08:49:52.759469Z

but the macro can check (:ns &env) . that is generally only available when compiling CLJS, so would be nil when expanding clojure code

magra 2025-04-14T08:52:09.028889Z

@thheller Thanks!! How could a macro know whether it is in the worker or in the ui module? If I set a var, will this leak between ui and worker?

thheller 2025-04-14T08:52:53.212159Z

just forget about that line of thought. it is unreliable and bug prone at best

thheller 2025-04-14T08:53:20.927679Z

do no write macros that want to keep 3 "worlds" in one

thheller 2025-04-14T08:54:35.779769Z

if you provide more context of what you are trying to do I can maybe make suggestions

thheller 2025-04-14T08:54:55.626019Z

but the compiler itself has no notion of what a worker is during compilation

thheller 2025-04-14T08:55:21.141259Z

the :web-worker option literally just prepends a bit of code to the output file after compilation

magra 2025-04-14T09:14:39.966079Z

@thheller I have fulcro mutations and database mutations on server and worker. Let us say the mutation is net.markusgraf.hhh.address.model/add-address. Since the database mutations are on the server AND the worker they need to go into a cljc file. But I can not have a cljc and a cljs file by the same name. So either these mutations live in the same file or I have to do some namespace translation hackery. At the moment I do the hackery: At the moment I have the files model.cljs and db_model.cljc and translate every incoming mutation by changing net.markusgraf.hhh.address.model/add-address to net.markusgraf.hhh.address.db-model/add-address. This bugs me every few months because it is an ugly hack.

magra 2025-04-14T09:18:40.227579Z

I also do not want to separate them to much because tests access both together to simulate roundtrips.

thheller 2025-04-14T09:21:53.845759Z

so since its fulcro I'm assuming that the mutation is still called via its eql stuff, so the UI not actually referencing the mutation, but instead constructing the mutation "list"?

thheller 2025-04-14T09:22:35.933879Z

asked differently does the UI code (:require [net.markusgraf.hhh.address.model :as x]) or some kind of other indirect reference instead?

magra 2025-04-14T09:23:23.993869Z

Yes.

thheller 2025-04-14T09:23:43.099019Z

problem is that if the UI code requires the mutation code it will end up as part of the UI code, i.e. get pulled out of any worker specific module

thheller 2025-04-14T09:24:02.057129Z

if it does not require the mutations. it will remain in the worker

thheller 2025-04-14T09:24:12.289719Z

or is the worker a separate build?

magra 2025-04-14T09:25:06.164999Z

At the moment the worker is only a different module. I have been thinking whether it would be better to make it a different build.

magra 2025-04-14T09:25:31.373509Z

I already have the defmutation macro modified to handle server push.

thheller 2025-04-14T09:26:16.064279Z

well, if the mutation only ever really "runs" in the worker it is best to just ensure it stays in the worker

thheller 2025-04-14T09:26:49.693869Z

I assume fulcro still using this eql mutation stuff

magra 2025-04-14T09:27:17.444069Z

What do you mean by eql mutation stuff?

magra 2025-04-14T09:27:57.274629Z

I did not change much fulcro, just replaced the remote and work without pathom.

magra 2025-04-14T09:29:19.259619Z

The defmutation modifications just add stuff.

thheller 2025-04-14T09:30:55.778239Z

I mean a eql list is constructed in the UI code, vs. actually calling the function?

magra 2025-04-14T09:30:56.657619Z

I basically try to work around the inability to have two files with the same namespace to feed to the worker and client.

thheller 2025-04-14T09:31:17.695149Z

`(some-alias/add-address ~some-args)

thheller 2025-04-14T09:31:20.675989Z

or something like that?

magra 2025-04-14T09:31:29.322469Z

Ah. Yes. I call transact like this yes.

thheller 2025-04-14T09:31:45.179909Z

ok, so in theory the UI then does not need to "know" the mutation

magra 2025-04-14T09:32:03.607119Z

Yes

thheller 2025-04-14T09:32:03.842829Z

(:require [net.markusgraf.hhh.address.model :as-alias x]) would still allow to write the exact same code

thheller 2025-04-14T09:32:17.144369Z

but would not pull the code into the actual UI module and leave it in the worker

thheller 2025-04-14T09:32:27.387969Z

assuming the worker somehow requires it normally of course πŸ˜›

thheller 2025-04-14T09:33:29.063929Z

but honestly, just thinking about all this just makes my head hurt already. it'll be so brittle that IMHO its not worth doing πŸ˜›

magra 2025-04-14T09:37:09.046479Z

Yeahhhh. I guess I will habe to keep doing the hack with the namespacetranslation. It is ugly but it works. Thanks a lot!!!! And thank you for shadow-cljs!!!

magra 2025-04-14T09:38:06.913349Z

I might put a macro in there to do it at compile time.

magra 2025-04-14T09:41:07.844579Z

You just gave me another idea. The defmutation macro creates multimethod methods. I could translate the symbol there. Thank you again!!!

thheller 2025-04-14T09:42:43.442659Z

btw create a build report, so that you know where your code actually lives. https://shadow-cljs.github.io/docs/UsersGuide.html#build-report

thheller 2025-04-14T09:43:15.487859Z

in theory you can query which module a certain namespace is in during compilation. but I strongly advise not doing that since it creates all sorts of issues with caching

magra 2025-04-14T09:44:57.396349Z

The multimethod for ui and db are in seperate namespaces already, the ui being fulcro.mutations/mutate. I can just have the macros unify the symbols they create, like getting rid of an intermediate ui- or db-. Then the it does not matter anymore that the mutations get defined in different namespaces.

magra 2025-04-14T09:45:18.431749Z

I will definitely use the build-report.

magra 2025-04-14T09:47:01.413599Z

It was the coupling of namespace to file on one hand and the coupling of namespace to mutation on the other that I tried to work around.

Marten Sytema 2025-04-14T08:55:32.940049Z

I have one more hurdle, as my CSS changes are not picked up: My http server serves the CSS files under /assets/css/style.css, and is stored at $PROJECTROOT$/resources/public/css/style.css And the shadow-cljs generated js is put in $PROJECTROOT$/public/js so that’s not in the same tree structure. This is my shadow-cljs.edn:

{:deps true
 :dev-http {3022 "public"}
 :builds
 {:app
  {:target           :browser
   :output-dir       "public/js"
   :asset-path       "/js"
   :modules          {:main {:init-fn cs2.core/init}}
   :devtools         {:watch-dir  "../resources/public"
                      :watch-path "/assets"}
  ,,,
  }}}
i’ve experimented with watch-dir / watch-path but currently to no avail. Should the repl be restarted btw, after each chagne in shadow-cljs.edn?

thheller 2025-04-14T08:56:24.844079Z

:watch-dir "../resources/public" why is that not just :watch-dir "resources/public"?

thheller 2025-04-14T08:56:29.458649Z

why the ../. I'm guessing thats not needed. :watch-path you do not need at all.

thheller 2025-04-14T08:57:24.924179Z

:watch-dir changes are currently only picked up when the watch is restarted. which you can do from the UI or by restarting shadow-cljs

Marten Sytema 2025-04-14T08:57:31.720829Z

so project structure: public/js <-- here goes shadowcljs js resources/public/css/ <-- css dir ON DISK /assets/css/ <-- virtual dir served from my custom httpkit HTTP server

thheller 2025-04-14T08:58:03.361869Z

why make your live difficult with "virtual" stuff πŸ˜› but yes, in that case :watch-path "/assets" is correct. and would be :watch-dir "resources/public". basically watch that directory, find that resources/public/css/whatever.css is changed. strips that prefix, so /css/whatever.css and prepends :watch-path, so /assets/css/whatever.css is reloaded

❀️ 1
Marten Sytema 2025-04-14T08:58:16.595759Z

yeah good point lol πŸ™‚

Marten Sytema 2025-04-14T08:58:30.675929Z

it’s been this way since 2018

Marten Sytema 2025-04-14T08:58:34.679949Z

figwheel

Marten Sytema 2025-04-14T08:58:36.811179Z

now migrating..

Marten Sytema 2025-04-14T08:58:54.547009Z

alright thanks πŸ™‚

Marten Sytema 2025-04-14T09:06:42.426539Z

hooray it works

Marten Sytema 2025-04-14T09:06:56.388139Z

restart of repl did the trick. and indeed, as you said.

πŸ‘ 1