Fork me on GitHub
#shadow-cljs
<
2020-06-13
>
mokr14:06:01

Hi, I’m looking for a quick hint in case this sounds familiar: My reloading works in the sense that terminal states “Build completed. (415 files, 2 compiled, 0 warnings, 0.66s)“, HUD in browser informs that reload occurred, but nothing actually changed (what I did was adding a Reagent [:h1 “foo”] element to page). Browser console stated “shadow-cljs: reloading code but no :after-load hooks are configured!“, but in general there’s nothing I want to do after load. What am I missing here? :thinking_face: Background: I’m moving a somewhat large project to shadow-cljs. It’s a “re-frame project” based on a Luminus template from 2017, and it has been using lein-figwheel up until now. I just went for the transition and it was a lot smoother than I feared, and it even pointed out quite a few bug along the way. Any ideas?

mokr15:06:28

Code is served by the Immutant based web server created by the mentioned Luminus template. I see that when I change the config in shadow-cljs.edn, my Reagent/Hiccup are propagated to browser.

thheller15:06:19

@mokr you need to actually trigger the re-render yourself. thats what the hooks are for. see https://code.thheller.com/blog/shadow-cljs/2019/08/25/hot-reload-in-clojurescript.html

thheller15:06:35

I believe in figwheel its the :on-jsload option in your config

mokr15:06:13

Thanks, @thheller this is the kind of pointer I was looking for. Now I need to do some more reading.

mokr15:06:43

I’m actually in the process of reading the complete docs, and was reading that chapter just now. I think the main problem for me is that I have “outsourced” quite a bit of the setup/plumbing to Luminus. That has been serving me very well, but when I now sit down and want to do shadow-cljs from scratch I miss some details, I guess. Anyway, thanks again.

thheller15:06:22

figwheel works the exact same. you tell it what it should call when its done loading and it does.

thheller15:06:46

just look for :on-jsload in your config. you maybe never noticed it when your template generated it 😛

mokr15:06:07

Yeah, I see that now, as I noticed the :on-jsload in my config.

thheller15:06:14

but yeah seems like a good idea to understand your setup fully 🙂

mokr15:06:26

I think that is always a benefit, but as a on-man-show I had to prioritise other tasks. I believe that was the right thing to do at the time, but it does bother me to not understand better why it works.

mokr15:06:22

BTW: Is shadow-cljs working well in Docker? Issues with reload time for lein-figwheel in docker is actually what pushed my to finally start on the transition. Docker as a DEV environment, that it.

thheller15:06:05

no clue. never tried it. 😛

mokr15:06:33

Ok, I guess I will find out soon enough. It’s not a dealbreaker, at all, but it would be nice to be able to run dev in the same environment as production.

thheller15:06:52

I certainly hope you are not running shadow-cljs in production

mokr15:06:35

It would just feel nice to be able to fire up a working dev environment based on a docker-compose stack, and run the production code in a kind of pre-prod sense locally.

thheller15:06:51

I know that file-watching used to be a problem and that the default didn't work. so you had to use the polling watcher instead which is quite a bit slower.

thheller15:06:07

no clue if that is still current though. was like 2 years ago the last time someone asked

mokr15:06:02

That is exactly what I was spending my time on yesterday. Still an issue on MacOS as far as I can see.

thheller15:06:23

:fs-watch {:watcher :polling} in shadow-cljs.edn will enable the polling watch

mokr15:06:20

Nice, thanks. But what kind of user experience should I expect from this? What’s the drawback?

thheller15:06:26

Feb 26, 2018 been a while 😛

thheller15:06:58

I have no clue. I never tried it. I barely ever use docker.

mokr15:06:11

In a sense I would say you are missing out on something quite useful, but I don’t know what you are doing apart from shadow-cljs 😀

thheller15:06:40

oh I looked into it a while ago and it is just annoying to me 😛

thheller15:06:48

it certainly does have its uses ... just don't see any for local development 😜

mokr15:06:21

Oh, for me it was quite the opposite. At least I did see something that would fit in my “toolbox” and solve real problems at work.

thheller15:06:42

yeah if you want to run a database or so sure

thheller15:06:38

like you said .. emulating a server production env is great

thheller15:06:57

but shadow-cljs is not part of that stack so I have no interest in putting it into docker 😛

thheller16:06:28

treat the output just like your production env. static files served by some webserver. thats great.

thheller16:06:52

doesn't mean shadow-cljs also has to run in that env

mokr16:06:01

The local dev thing was driven mostly by frustration that “lein new luminus myproject +re-frame ….” stopped working locally on my Mac. For shadow-cljs dev the great thing would be that everything is wrapped up in something that works. No local setup apart from Docker.

thheller16:06:12

sure if that works for you go ahead and do it. I know its not for me.

mokr16:06:24

As it looks right now, it won’t be my go to solution either. CPU usage and delays will not be as good as I would want. But, I think I will still try it out jut for fun. 😊

mokr16:06:47

While we are at it; What about the Clojure side of things? I’m looking into deps.edn, but I haven’t decided what to do about handling dependencies, running the Clojure based backend in dev and generating the executable jar used in prod. Any tips?

mokr16:06:28

And just to confirm; Adding ^:dev/after-load to the function called by figwheel’s :on-jsload solved my initial issue. Thanks for taking the time @thheller, I really appreciate it! 😊 I’m confident that I will be in a way better position when this transition is done. My previous experience with shadow-cljs + D3.js code in plain JS was really pleasant, so I can probably reduce the complexity of the codebase going forward (D3 code is currently cljs)

thheller17:06:23

CLJ stuff I still use lein. works well for me, does everything I need.

Gleb Posobin20:06:26

I am building a chrome extension with shadow, and it for some reason adds one of the background scripts into the content_scripts entry in manifest.json, and I can't understand why. That script's ns appears in requires only in two other namespaces, neither of which are content scripts: one is the main background ns, the other is the options page for the extension, neither of them is require'd in any other namespace and they don't appear in the content_scripts list in manifset.json. mount/start for some reason picks up on the states defined in that background namespace and tries to start them when starting the content script. Is there a way to determine why it is being added?

thheller20:06:24

well its your ns :require controlling all of this but no there is easy visualization or so for this

thheller20:06:57

been meaning to replace the old variant I had for this once but didn't get to it yet

Gleb Posobin20:06:15

It is also the fourth entry from the bottom of the content_scripts list. I assume the files there are in topological order there (?), and the ones after it are shadow.module.bg-shared.append.js, ampie.content_script.content.js (my content script ns) and shadow.module.content-script.append.js, that background script is referenced in neither of them.

thheller20:06:09

this is all a bit too abstract for me to follow

thheller20:06:28

note that ALL dependencies count when determining where something ends up. so you content scripts might not require something from the background directly

thheller20:06:41

but another ns the content script uses might?

Gleb Posobin20:06:51

I'll double check, but the files that require that ns are themselves not included in content_scripts list.

thheller20:06:45

I honestly can't remember much about the chrome extension stuff

Gleb Posobin20:06:53

I removed the reference to it from the ns that is compiled as :chrome/single-file and that entry disappeared from the content_scripts.

Gleb Posobin20:06:23

So all the dependencies of single-file targets are added to content_scripts?

thheller20:06:56

single-file is standalone yes

thheller20:06:15

this is all based on :modules and sharing as much code as possible

Gleb Posobin20:06:02

What do you mean by sharing as much code as possible?

Gleb Posobin20:06:58

So the thing seems to be: ns in question is required in a background script and in a single-file script. If I remove the require from either one of those places, it disappears from content_scripts list, otherwise it is added there (unnecessarily, since it isn't required in any content scripts even indirectly). I created a new ns and required it in those two namespaces, the same behaviour repeated.

Gleb Posobin21:06:02

So shadow is trying to put the namespaces that appear as dependencies several times into the content_scripts list?

thheller21:06:36

I cannot help if you don't share details

thheller21:06:52

I need a reference of some kind. this is all too abstract.

thheller21:06:12

I also honestly can't remember much of the details of the chrome ext stuff

Gleb Posobin21:06:15

Ok, I'll try to make an example later.