Fork me on GitHub
#shadow-cljs
<
2023-02-21
>
Geoffrey Gaillard09:02:59

Hello! I’m experiencing a behavior I don’t understand with Shadow. I have a hierarchy of namespaces:

root.cljs
   |
   | depends on
   ˇ
parent.cljc
   |
   ˇ
child.cljc
   |
   ˇ
grandchild.cljc
During a watch, with :cache-level :off : • saving the root.cljs file recompiles the root ns • saving the parent.cljc file recompiles parent and root • saving the child.cljc file recompiles child and parent, but not root • saving the grandchild.cljc file recompiles grandchild and child, but not parent nor root. Is it the expected behavior?

Geoffrey Gaillard09:02:51

Full project for reference

thheller11:02:05

cache-level only controls what cache is written to disk. watch also keeps everything in memory while running

thheller11:02:00

if you must have files that are always recompiled use :dev/always in the ns https://shadow-cljs.github.io/docs/UsersGuide.html#_lifecycle_hooks

👍 2
Galaux13:02:55

> yes, this is intended I must definitely be missing something here because I thought this was a basic shadow-cljs feature. Code changes have always been reflected in the browser right away on my ClojureScript/Shadow-CLJS projects.

Galaux13:02:55

I've experienced some very similar problem with a react-native/expo project though https://app.slack.com/client/T03RZGPFR/C6N245JGG/thread/C6N245JGG-1676365851.448239

Galaux13:02:58

@U2DART3HA Your shadow-cljs.edn references an :init-fn root/start! which doesn't exist in root.cljs

Galaux14:02:11

>> yes, this is intended > I must definitely be missing something here because I thought this was a basic shadow-cljs feature. Code changes have always been reflected in the browser right away on my ClojureScript/Shadow-CLJS projects. @U05224H0W can you please clarify this ↑ ?

Geoffrey Gaillard14:02:57

> Your shadow-cljs.edn references an :init-fn root/start! You are right this is a mistake. Sorry for the confusion.

Galaux14:02:31

No problem. If you have a minimal project you can share on github, I could try to have a look and see if I spot something.

👍 2
Galaux14:02:33

@U05224H0W In a shadow-cljs with :target :browser code changes anywhere in the sources are rendered right away in the browser (provided you correctly used (defn ^:dev/after-load mount-root …)

thheller14:02:09

read https://code.thheller.com/blog/shadow-cljs/2019/08/25/hot-reload-in-clojurescript.html for more details. as far as shadow-cljs in concerned it is finish when it calls the :dev/after-load hook. it knows nothing about rendering or even react.

thheller14:02:43

there seems to be an issue in expo/react-native that just stops this rendering process if only something nested changed but not the root

thheller14:02:58

for that you can set :devtools {:reload-strategy :full} in your build config

thheller14:02:29

then it reloads everything up to the root, not recompile though.

Galaux14:02:59

Yes … that's the same link I explained I had read in my previous question.

Galaux14:02:49

As explained, I tried :devtools {:reload-strategy :full} but with no effect.

thheller14:02:21

did you set it in the correct place? not uncommon it ends up in the wrong place and do nothing. could also be other things of course. without seeing what you are doing in your code its really hard to give specific advice

Galaux14:02:28

I posted a link to a minimal repo

Galaux14:02:01

I hadn't pushed the reload-strategy … pushing right now

thheller14:02:52

push where? do you have a link for me?

Galaux15:02:29

Yes I do … I'm just in the process of looking it up

Galaux15:02:52

And now it works … obviously. I double-checked it 10' ago and it failed. 😓

thheller15:02:29

not uncommon for this config to slip one level up and thus in the wrong place

thheller15:02:09

I'd still like to know why its necessary because it shouldn't be, but don't have time to look into it currently

Geoffrey Gaillard16:02:33

I'm just confused and didn't understand the behavior. Thank you for your answer :)

Braden Shepherdson13:02:24

does anyone have a working example of incorporating a shadow-cljs dev build into a webpack dev build such that the final JS has (a) source maps for CLJS and (b) working preloads so the CLJS devtools work? I'm using deps.edn for deps management and :npm-module output, if it matters. neither are working for me and I wonder if something in the webpack configuration is breaking it.

thheller13:02:59

preloads you inject yourself from the JS side of things

thheller13:02:10

what are you building for? browser or vscode stuff? node?

Braden Shepherdson13:02:56

browser. this is for Metabase, if you want to see the webpack.config.js https://github.com/metabase/metabase/blob/master/webpack.config.js

thheller13:02:43

yikes that is a chunky config 😛

Braden Shepherdson13:02:25

yeah, I'm no webpack expert so I'm floundering . the CLJS output has separate source maps for each file. I'm a little suspicious of https://github.com/metabase/metabase/blob/master/webpack.config.js#L311 since it looks like it's expecting inline source maps or per-module ones, and in either case missing the separate per-file maps on the CLJS.

thheller13:02:56

yeah did you try either variant? not all things read input source maps, might require extra config

Braden Shepherdson13:02:16

I didn't know about that BETTER_SOURCE_MAPS flag until now, I'm trying that.

Braden Shepherdson13:02:20

source-map-loader did the trick for the source maps. if the shadow-cljs :preload is expected not to work with webpack wrapping it, I'll look into how to get cljs-devtools through webpack. thanks!

thheller14:02:20

it is supposed to work, but you need to load it

thheller14:02:35

npm-module has no clearly defined entries, so somewhere in your JS parts you add if (process.env.NODE_ENV === "development") { require("cljs/shadow.cljs.devtools.client.browser"); require("cljs/shadow.cljs.devtools.client.console"); }

Braden Shepherdson16:02:59

Metabase already had a dev.js loaded in dev only; it was easy enough to hook in a new namespace that does (devtools.core/install!). thanks for your help!

Braden Shepherdson17:02:36

is there a :dev {:entries [...]} that merges with the main :entries? anything else like that? I have some namespaces that are only required in dev mode.

chrisetheridge17:02:42

you can do something like this, to overwrite the entries:

:dev     {:modules {:module-a {:entries [module-a.core
                                            module-a.dev]}}}

lilactown17:02:18

:preloads is what I typically use for dev-only namespaces

Braden Shepherdson17:02:04

yeah, :preloads does the right thing except that this output is getting fed to a webpack build. also they don't necessarily agree on dev vs. release builds.

lilactown17:02:54

hmm, not sure about webpack. why does that complicate things?

Braden Shepherdson17:02:53

I think the real problem I'm having is that the scripts are doing a release CLJS build, then a dev webpack build. in dev mode the JS includes a dev-only CLJS namespace, which was excluded because it's a release CLJS build, and so it fails at load time. this is a catch-22, and I'll probably have to fix that script so both agree on dev vs. release modes.

lilactown17:02:10

yeah, why is the script doing a release CLJS build at dev time? the compile time must be awful :face_with_peeking_eye:

Braden Shepherdson17:02:24

you overestimate how much CLJS is currentl involved 🙂