Fork me on GitHub
#shadow-cljs
<
2019-08-19
>
Phil Jackson10:08:39

Hey all. When spec'ing functions, where do you call instrument in your dev environments?

Phil Jackson10:08:00

Especially so that stuff is re-instrumented when something changes.

Karol Wójcik13:08:33

@thheller Is there way to use this https://www.npmjs.com/package/webpack-bundle-analyzer with shadow-cljs or with regular cljs compilation?

thheller14:08:07

but no you can't use that with shadow-cljs

isak15:08:31

That build report is one of my favorite things in shadow, soo useful 👍:skin-tone-2:

mccraigmccraig15:08:29

it was one of the principal driving factors for us having just moved to shadow

✔️ 4
Phil Jackson15:08:02

Is that report built after advanced compilation?

tianshu17:08:14

@thheller If I have a macro and a ^:dynamic variable used for some initial setup. how can I change this variable and make sure it happen before macro expansion. will put it before the macro usage work?

tianshu17:08:37

hmm, sorry for my bad explain. assume I have a macro alert and a variblae *should-alert*

tianshu17:08:38

If I set should-alert to false, alert macro will expand to nothing. If I set should-alert to true, alert macro will expand to something.

tianshu17:08:16

since shadow-cljs use parallel compile, will the order matter?

thheller17:08:55

don't do that

tianshu17:08:39

is there a correct way for this kind of requirements

thheller17:08:57

bindings are unreliable to begin with and using that binding will break the caching

thheller17:08:39

do you want to control this via build config or how did actually set *should-alert*?

tianshu17:08:57

In my case, the *should-alert* is something like a global configuration.

isak17:08:00

Anyone able to get this to work with shadow? https://github.com/Engelberg/better-cond For me it says failed to require macro-ns "better-cond.core"

thheller17:08:12

yes but how did you set it? or how do you want to set it? build config a good place?

tianshu17:08:50

It's a bit long, so I want set it in .cljs file.

tianshu17:08:53

(set-xxx! {...})

thheller17:08:54

@isak what else does it say?

thheller17:08:33

@doglooksgood I need to complete example to be able to make any recommendations. I do not yet understand what you are trying to do.

thheller17:08:51

what does set-xxx! do?

tianshu17:08:54

There's a complete, but not too much code example

thheller17:08:47

> FileNotFoundException: Could not locate better_cond/core__init.class, better_cond/core.clj or better_cond/core.cljc on classpath

tianshu17:08:07

I want use macro to generate CSS string, one thing I have to deal with is vendors. I want configure which vendor used on which property.

thheller17:08:11

did you properly restart the shadow-cljs server instance after adding the dependency?

isak17:08:23

yea, I did

thheller17:08:09

looks like you didn't though

thheller17:08:57

when you restart the watch make sure it doesn't say connected to server ...

thheller17:08:05

otherwise you have a server instance still running

thheller17:08:23

@doglooksgood what you are trying to do is a really really really bad idea and will essentially require that cache is entirely disabled

thheller17:08:29

it will not work with caching at all.

isak17:08:31

hmm, it doesn't say that

thheller17:08:13

then please try running shadow-cljs clj-repl and then ( "better_cond/core.clj")

isak17:08:11

ok, it says nil

thheller17:08:33

then you didn't add the dependency properly

thheller17:08:40

how did you add it?

isak17:08:17

I just added [better-cond "2.1.0"] to shadow-cljs.edn :dependencies, like the rest of them

thheller17:08:42

and clj-repl didn't say connected to server?

thheller17:08:03

$ shadow-cljs clj-repl                                                               shadow-cljs - config: /mnt/c/Users/thheller/code/shadow-cljs/shadow-cljs.edn  cli version: 2.8.50  node: v10.13.0
shadow-cljs - connected to server
shadow-cljs - REPL - see (help)
To quit, type: :repl/quit
[6:0]~shadow.user=>

thheller17:08:37

ie. it doesn't say this?

isak17:08:54

It said this for me:

$ /mnt/c/src/xportal/assets/node_modules/.bin/shadow-cljs clj-repl                                                                                              shadow-cljs - config: /mnt/c/src/xportal/assets/shadow-cljs.edn  cli version: 2.8.41  node: v11.13.0                                                            shadow-cljs - server version: 2.8.41 running at                                                                                            shadow-cljs - nREPL server started on port 55813                                                                                                                shadow-cljs - REPL - see (help)                                                                                                                                 To quit, type: :repl/quit  

tianshu17:08:57

yes, I know, it is side effects. so I want a side effects free way to achieve this. there's only one another way I know is let user define a new macro, with some options passed in.

thheller17:08:09

@isak and you added the dependencies properly to /mnt/c/src/xportal/assets/shadow-cljs.edn?

thheller17:08:19

not indented incorrectly or something?

thheller17:08:35

[foo.bar "1.2.3" [better-cond ...]] something like that?

thheller17:08:10

@doglooksgood the only way I can recommend right now is moving that data into the build config

thheller17:08:32

:compiler-options {:external-config {:mcss {:the-data true}}}

isak17:08:38

yea it was correct. But now I just for run re-arranged it in the dependency list, and now i'm not getting that error - strange

thheller17:08:55

you can get that in the macro via (get-in @cljs.env/*compiler* [:options :external-config :mcss])

tianshu18:08:00

where I put this config?

thheller18:08:11

in your build config

thheller18:08:44

it is not a great solution but any change to :external-config will invalidate the cache so at least recompiles will happen

thheller18:08:12

changing dynamic bindings will not invalidate the cache otherwise

tianshu18:08:15

where can found some doc for this? you mean even I change the build config, a recompile will happen?

thheller18:08:52

there are no docs on this since it isn't recommended to do this

thheller18:08:24

but it is something that other libraries have done

thheller18:08:28

but yes shadow-cljs is setup to recognize changes in :compiler-options and trigger recompiles accordingly

thheller18:08:23

doing side-effect in macros is still bad though. you could maybe build something on top build hooks https://shadow-cljs.github.io/docs/UsersGuide.html#build-hooks

thheller18:08:30

but thats a bit more involved and would only work with shadow-cljs

tianshu18:08:31

I see, so a :external-config in compiler options.

thheller18:08:08

I gotta go right now. I'll be back in about 2 hours. maybe we can continue then if you still need help

tianshu19:08:45

@thheller I found another way, don't know if it is good or not. If put those default configuration in a file mcss.defaults.clj, and let user provides an overwrite version if he wants. is it a good idea? since shadow support this.

tianshu19:08:50

since there's only source code, it should works fine with cache.

thheller19:08:50

hmm yeah but you are still abusing the macro system for things it isn't meant to do

grav20:08:08

Is there a way of excluding shadow-cljs itself when generating the pom.xml file with shadow-cljs pom? (apart from mangling the resulting xml with xquery or something)

thheller20:08:51

why would you want to?

thheller20:08:11

it is only meant as a helper for tools like Cursive since it can't import shadow-cljs.edn projects

grav20:08:54

I’m abusing it for some other tooling. I’m trying to create a classpath for Lumo

grav20:08:39

So my strategy is currently to 1. create a pom 2. install deps via maven 3. generate a class path with maven 4. using that classpath with lumo

thheller20:08:16

seems like you should be using deps.edn for that? clj -Spom and clj -Spath?

👍 4
grav20:08:58

Yeah, maybe you’re right. I guess the reason I’m using pom.xml in the first place is because of Cursive

grav20:08:09

But that can use deps.edn.

pmooser20:08:11

I'm trying out shadow-cljs on a new project at work, and with bootstrapped cljs repl, I get intermittent errors when loading the page that only occur if we're including the bootstrap repl functionality. It looks like "sometimes" things are being loaded twice, which results in an avalanche of errors from goog.provide (I think). Does anyone have any pointers on how you would debug this ? I've compared to example projects and don't quite see what I am doing that would cause this.

thheller20:08:54

what is bootstrap repl functionality?

pmooser20:08:46

@thheller Yes, I believe I followed that. I will review the code now to verify it. What I mean when I say "bootstrap repl functionality" is that if I leave the build as-is but remove references to my repl namespace (which requires cljs.js), the errors seem to disappear.

pmooser20:08:59

I will go review that article you presented now and compare to my project - back shortly.

thheller20:08:12

without cljs.js in the build the self-hosted support won't be added?

thheller20:08:40

isn't that the main interface for everything in self-hosted?

pmooser20:08:18

@thheller Yes, I realize that. I'm just saying, the errors are particular to that NS being included. I have no idea what causes them. This hasn't happened in previous things I've done using cljsbuild instead of shadow-cljs. I'm just trying to get it resolved. So to answer your previous question, our code does follow that article - I found a couple differences (we were initializing our compiler state to an empty state instead of the default state as you did) , and we were passing some namespaces to load-in-init in the configuration for the init call, but changing these things doesn't seem to result in anything different than what I am seeing. It is a bit challenging to evaluate because it does not happen on every reload - sometimes it doesn't even happen for many reloads.

pmooser20:08:33

At this point, I've thought I fixed it multiple times, due to this intermittency, but it always seems to come back.

thheller20:08:39

cljs.js is the reason

thheller20:08:53

if that is included the necessary data is added for self-hosted support for the build

thheller20:08:22

if it isn't added the data isn't there so the bootstrap process is affected

pmooser20:08:56

How would I have a repl without including cljs.js ? It depends on what you mean by 'including' I suppose ?

thheller20:08:15

please clarify what you mean by REPL

pmooser20:08:16

I mean in my shadow-cljs.edn I have that excluded from the bootstrap build.

pmooser20:08:38

I have a namespace, let's say it's called "repl" - that namepace has a require (as your example also does) which includes things like cljs.js, cljs.env, tools.reader, etc. This namespace implements a graphical repl (using reagent) which calls "eval-str" to implement a repl.

pmooser20:08:14

That is what I mean by repl. Does that make sense now ?

pmooser20:08:40

(when I say it to identical to your example, I only meant insofar as how it calls eval)

thheller20:08:08

kind of yes. but my example USES the cljs.js namespace. so would you want to NOT include it?

pmooser20:08:21

I need to include it

thheller20:08:24

don't you need cljs.js/eval-str?

pmooser20:08:29

I only removed it to try to help diagnose what the problem is

thheller20:08:42

you removing it WOULD cause the problem?

pmooser20:08:56

Ok, I am obviously communicating really poorly --

pmooser20:08:16

I need to include it. If I include it, hundreds of errors spew intermittently upon reloading my page.

thheller20:08:45

and what are you loading on that page?

pmooser20:08:52

I only mentioned removing it (ie, commenting out requiring cljs.js and code that calls eval) to say that under those conditions, the errors don't occur (but of course my app doesn't "work" because those features have to be disabled).

thheller20:08:17

ok. to make it clear if you remove that require things WILL break. so don't remove it and lets stop talking about that.

pmooser20:08:31

I am not sure how to answer what I am loading. I am not evaluating anything by default at all. The page is a reagent page with a few buttons on it and nothing terribly interesting happening by default.

thheller20:08:45

so what is your build config?

thheller20:08:28

I am asuming that you have a build config with a :modules {:whatever { ...}}} and then loading the generated whatever.js file in the browser?

thheller20:08:48

do you maybe load that file multiple times?

thheller20:08:58

(directly from your HTML)

pmooser20:08:50

In the browser portion of the build config, I have a modules entry like this:

pmooser20:08:58

:modules          {:main {:entries [myapp.core]}}

thheller20:08:29

so how do you load the main.js file?

pmooser20:08:54

I have a script tag in the head like this:

pmooser20:08:06

<script src="/js/main.js"></script>

thheller20:08:20

good. and that is the only time /js/main.js is included?

thheller20:08:26

not a second one in the body or something

pmooser20:08:34

Yes, but I do call a main() fn in the body like this:

pmooser20:08:44

<script>myapp.core.main();</script>

pmooser20:08:51

(I assume that is OK)

thheller20:08:22

yes that is ok. not ideal but ok.

thheller20:08:47

so what does the main fn do?

pmooser20:08:50

Main in this case essentially does some loading of external resources (via http calls) and once that stuff is done, it calls this fn as its last thing:

pmooser20:08:58

(defn render-app
  []
  (let [app (.getElementById js/document "app")]
    (r/render [home-page] app)))

thheller20:08:41

so and when do the errors start happening?

pmooser20:08:20

The errors happen part-way through initialization as far as I can tell - they start spewing almost immediately upon page reload, and there are hundreds of them.

thheller20:08:32

ok are you properly dealing with the async aspects?

thheller20:08:03

eg. in my example the boot/init fn is called and it takes a callback

thheller20:08:24

it is NOT safe you use anything before that has completed its work and the callback was called

pmooser20:08:53

My callback doesn't happen to do anything there - but I'm not calling eval-str by the time these errors occur anyway.

pmooser20:08:18

Is that what you mean, that I should ensure no one can be calling eval until the init-cb occurs ? I can do that work but that isn't what is happening regardless.

pmooser20:08:56

The intermittency is what is confusing - I am trying to force it to happen now by reloading over and over but at the moment I can't get it to occur.

thheller20:08:57

I can only guess what is happening. what you are describing sounds like things are initialized multiple times

pmooser20:08:41

I 100% agree with that -

thheller20:08:43

well intermittency can be caused by async events happening in a different order

thheller20:08:56

due to timing being different and so on

pmooser20:08:01

The load errors are a signal (since they are provide complaining) but I can verify that it is definitely loading namespaces multiple times when it occurs.

thheller20:08:40

well for one you should remove your manual <script>myapp.core.main();</script> call

thheller20:08:58

move your <script src="/js/main.js"> to the bottom of your page right above your </body>

pmooser20:08:58

What's the alternative to that main call, since loading the script itself doesn't launch the app ?

pmooser20:08:15

(what I mean is, it's not like there is a call to (main) at the end of some ns or something)

thheller20:08:21

and switch your build config to :modules {:main {:init-fn myapp.core/main}}

pmooser20:08:32

Thank you, I will give that a try.

thheller20:08:40

that at least ensures that part of the code is all loaded in the correct order and initialized correctly

thheller20:08:27

but your setup seemed otherwise correct so that likely wouldn't change anything

pmooser20:08:34

OK, I'm getting a compiler error, I need to figure out what I did wrong.

thheller20:08:34

just trying to eliminate potential timing issues

pmooser20:08:09

Ok, fixed my compilation issue. Yes, I understand, and I appreciate the help.

pmooser20:08:22

I also understand why you are worried about the asynchrony.

pmooser20:08:41

I wonder if I can add some debugging code to dump a stack on load to try to see where the two calls would be originating from.

thheller20:08:57

the browser devtools network requires might provide a clue

thheller20:08:04

they show what triggered the load

pmooser20:08:22

Oh? Fantastic.

pmooser20:08:36

I will try to see if I can get some insight from that.

pmooser20:08:49

For the time being, I will commit the changes you suggested about how I invoke main - thank you for that.

pmooser20:08:05

When it occurs it again (assuming it does), I will see if I can diagnose using the network info from devtools.

pmooser20:08:07

Thank you !!

thheller20:08:47

if you use the regular REPL together with your custom self-hosted REPL things will likely go very wrong

thheller20:08:53

so that might be another cause

pmooser20:08:16

I don't tend to use those things together so I don't think that is probably it, but I am glad to know that.