Fork me on GitHub
#shadow-cljs
<
2018-03-21
>
mitchelkuijpers10:03:00

Anyone else runnig into with shadow-cljs 2.2.16:

Exception in thread "async-thread-macro-12" java.lang.NoClassDefFoundError: Could not initialize class shadow.cljs.devtools.server.reload_classpath$process_update$fn__59202
	at shadow.cljs.devtools.server.reload_classpath$process_update.invokeStatic(reload_classpath.clj:21)
	at shadow.cljs.devtools.server.reload_classpath$process_update.invoke(reload_classpath.clj:21)
	at clojure.lang.PersistentVector.reduce(PersistentVector.java:341)
	at clojure.core$reduce.invokeStatic(core.clj:6747)
	at clojure.core$reduce.invoke(core.clj:6730)
	at shadow.cljs.devtools.server.reload_classpath$process_updates.invokeStatic(reload_classpath.clj:45)
	at shadow.cljs.devtools.server.reload_classpath$process_updates.invoke(reload_classpath.clj:38)
	at shadow.cljs.devtools.server.reload_classpath$watch_loop.invokeStatic(reload_classpath.clj:75)
	at shadow.cljs.devtools.server.reload_classpath$watch_loop.invoke(reload_classpath.clj:63)
	at shadow.cljs.devtools.server.reload_classpath$start$fn__59234.invoke(reload_classpath.clj:92)
	at clojure.core.async$thread_call$fn__8239.invoke(async.clj:442)
	at clojure.lang.AFn.run(AFn.java:22)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)

thheller10:03:36

hmm never seen that before

mitchelkuijpers10:03:59

I think it's my fault

mitchelkuijpers10:03:11

a wrong tools.reader version

thheller10:03:01

it might be related to the new cljs version

thheller10:03:11

which decided it was a good idea to ship the AOT bundle as the default

thheller10:03:19

so you get their tools.reader version always

mitchelkuijpers10:03:35

No I a old tools.reader in my project.clj

thheller10:03:48

doesn't matter when the AOT version is on the classpath

mitchelkuijpers10:03:24

Well now it works after removing tools.reader 1.1.2

mitchelkuijpers10:03:25

I see cider support as been improved:

mitchelkuijpers10:03:44

Only thing that is not working anymore is file watching for some reason..

thheller10:03:46

yeah, fixed some piggieback things reported here https://github.com/clojure-emacs/cider/issues/2239

thheller10:03:08

you need to tell me about these things. I wasn't even aware this was an issue 😛

thheller10:03:01

what are those failed to parse warnings?

mitchelkuijpers10:03:14

Oh sorry, I didn't dare you were so angry the last time you started cider 😛

mitchelkuijpers10:03:28

11:38:40.868 [nREPL-worker-0] WARN  shadow.build.classpath - failed to parse javascript file: jar:file:/home/mitchel/.m2/repository/cljs-hash/cljs-hash/0.0.2/cljs-hash-0.0.2.jar!/js/sha256.js
[{:line 11, :column 9, :message "'identifier' expected"}] {  }
11:38:40.875 [nREPL-worker-0] WARN  shadow.build.classpath - failed to parse javascript file: jar:file:/home/mitchel/.m2/repository/cljs-hash/cljs-hash/0.0.2/cljs-hash-0.0.2.jar!/js/md5.js
[{:line 9, :column 9, :message "'identifier' expected"}] {  }
11:38:40.877 [nREPL-worker-0] WARN  shadow.build.classpath - failed to parse javascript file: jar:file:/home/mitchel/.m2/repository/cljs-hash/cljs-hash/0.0.2/cljs-hash-0.0.2.jar!/js/sha1.js
[{:line 9, :column 9, :message "'identifier' expected"}] {  }
11:38:41.633 [nREPL-worker-0] WARN  shadow.build.classpath - failed to parse javascript file: jar:file:/home/mitchel/.m2/repository/doo/doo/0.1.8/doo-0.1.8.jar!/runners/nashorn.js
[{:line 21, :column 39, :message "Semi-colon expected"}] {  }
11:38:42.192 [nREPL-worker-0] WARN  shadow.build.classpath - failed to parse javascript file: jar:file:/usr/lib/jvm/java-8-openjdk/lib/tools.jar!/com/sun/tools/hat/resources/hat.js

thheller10:03:42

yeah I get frustrated easily by emacs .. doesn't mean I don't want it to work 😛

thheller10:03:18

hmm I should turn off those warnings

mitchelkuijpers10:03:26

Hmm I know why watching is not working:

mitchelkuijpers10:03:55

(shadow-server/stop!)
shutting down ...
JS runtime disconnected.
Worker shutdown.
11:45:10.423 [nREPL-worker-2] WARN  shadow.cljs.devtools.server - shutdown failed ((rt/stop-all app)) {  }
java.lang.ThreadDeath: null
	at java.lang.Thread.stop(Thread.java:853)
	at clojure.tools.nrepl.middleware.interruptible_eval$interruptible_eval$fn__62024.invoke(interruptible_eval.clj:243)
	at clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__61733.invoke(middleware.clj:22)
	at user$eval74385$fn__74386$fn__74388.invoke(form-init5239952018706589785.clj:1)
	at shadow.cljs.devtools.server.nrepl$cljs_eval$fn__62323.invoke(nrepl.clj:171)
	at clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__61733.invoke(middleware.clj:22)
	at clojure.tools.nrepl.middleware.load_file$wrap_load_file$fn__62170.invoke(load_file.clj:79)
	at clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__61733.invoke(middleware.clj:22)
	at shadow.cljs.devtools.server.nrepl$cljs_load_file$fn__62334.invoke(nrepl.clj:192)
	at clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__61733.invoke(middleware.clj:22)
	at clojure.tools.nrepl.middleware.session$add_stdin$fn__62099.invoke(session.clj:238)
	at clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__61733.invoke(middleware.clj:22)
	at cider.nrepl$wrap_debug$fn__70069.invoke(nrepl.clj:161)
	at clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__61733.invoke(middleware.clj:22)
	at cider.nrepl$wrap_enlighten$fn__70077.invoke(nrepl.clj:187)
	at clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__61733.invoke(middleware.clj:22)
	at cider.nrepl$wrap_macroexpand$fn__70111.invoke(nrepl.clj:264)
	at clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__61733.invoke(middleware.clj:22)
	at cemerick.piggieback$wrap_cljs_repl$fn__62286.invoke(fake_piggieback.clj:31)
	at clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__61733.invoke(middleware.clj:22)
	at cider.nrepl$wrap_inspect$fn__70103.invoke(nrepl.clj:224)
	at clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__61733.invoke(middleware.clj:22)
	at cider.nrepl$wrap_out$fn__70127.invoke(nrepl.clj:305)
	at clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__61733.invoke(middleware.clj:22)
	at cider.nrepl$wrap_pprint$fn__70035.invoke(nrepl.clj:107)
	at clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__61733.invoke(middleware.clj:22)
	at cider.nrepl$wrap_tracker$fn__70191.invoke(nrepl.clj:450)
	at clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__61733.invoke(middleware.clj:22)
	at shadow.cljs.devtools.server.nrepl$cljs_select$fn__62315.invoke(nrepl.clj:153)
	at clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__61733.invoke(middleware.clj:22)
	at clojure.tools.nrepl.middleware.pr_values$pr_values$fn__61940.invoke(pr_values.clj:22)
	at clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__61733.invoke(middleware.clj:22)
	at cider.nrepl$wrap_test$fn__70175.invoke(nrepl.clj:415)
	at clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__61733.invoke(middleware.clj:22)
	at cider.nrepl.middleware.pprint$handle_pprint_fn.invokeStatic(pprint.clj:49)
	at cider.nrepl.middleware.pprint$handle_pprint_fn.invoke(pprint.clj:44)
	at clojure.lang.Var.invoke(Var.java:385)
	at cider.nrepl$wrap_pprint_fn$fn__70025.invoke(nrepl.clj:88)
	at clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__61733.invoke(middleware.clj:22)
	at clojure.tools.nrepl.middleware.session$session$fn__62084.invoke(session.clj:192)
	at clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__61733.invoke(middleware.clj:22)
	at clojure.tools.nrepl.server$handle_STAR_.invokeStatic(server.clj:19)
	at clojure.tools.nrepl.server$handle_STAR_.invoke(server.clj:16)
	at clojure.tools.nrepl.server$handle$fn__62185.invoke(server.clj:28)
	at clojure.core$binding_conveyor_fn$fn__5476.invoke(core.clj:2022)
	at clojure.lang.AFn.call(AFn.java:18)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)

thheller10:03:05

hmm what the heck?

thheller10:03:19

are you connected to the shadow-cljs nrepl or still via lein?

thheller10:03:40

why are you calling stop!?

mitchelkuijpers10:03:12

Because I did (shadow/watch :app) but it wasn't recompiling

thheller10:03:29

try reload! instead

thheller10:03:50

it might still fail though

mitchelkuijpers10:03:07

I will try hold on

thheller10:03:11

no idea whats going on

mitchelkuijpers10:03:23

Now i have this again:

Exception in thread "async-thread-macro-15" java.lang.NoClassDefFoundError: Could not initialize class shadow.cljs.devtools.server.reload_classpath$process_update$fn__59438
	at shadow.cljs.devtools.server.reload_classpath$process_update.invokeStatic(reload_classpath.clj:21)
	at shadow.cljs.devtools.server.reload_classpath$process_update.invoke(reload_classpath.clj:21)
	at clojure.lang.PersistentVector.reduce(PersistentVector.java:341)
	at clojure.core$reduce.invokeStatic(core.clj:6747)
	at clojure.core$reduce.invoke(core.clj:6730)
	at shadow.cljs.devtools.server.reload_classpath$process_updates.invokeStatic(reload_classpath.clj:45)
	at shadow.cljs.devtools.server.reload_classpath$process_updates.invoke(reload_classpath.clj:38)
	at shadow.cljs.devtools.server.reload_classpath$watch_loop.invokeStatic(reload_classpath.clj:75)
	at shadow.cljs.devtools.server.reload_classpath$watch_loop.invoke(reload_classpath.clj:63)
	at shadow.cljs.devtools.server.reload_classpath$start$fn__59470.invoke(reload_classpath.clj:92)
	at clojure.core.async$thread_call$fn__8239.invoke(async.clj:442)
	at clojure.lang.AFn.run(AFn.java:22)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)

mitchelkuijpers10:03:32

which is probably the error that causes this

mitchelkuijpers10:03:44

when doing (shadow/watch :app)

thheller10:03:55

can you try adding a custom cljs version please?

thheller10:03:12

[org.clojure/clojurescript "1.10.145" :classifier "slim"]

thheller10:03:27

wonder if that changes anything

thheller10:03:53

don't forget lein clean as usual. doesn't affect shadow-cljs but I don't know what lein may have done

thheller10:03:06

do you get the error immediately on startup or only after changing a file?

mitchelkuijpers10:03:34

I get it after stopping and starting the server again and then running (shadow/watch :app)

mitchelkuijpers10:03:29

I am running this to start it btw:

(do (shadow.cljs.devtools.server/start!) (shadow.cljs.devtools.api/watch :app) (shadow.cljs.devtools.api/nrepl-select :app))

thheller10:03:02

that is fine

mitchelkuijpers10:03:27

Could a circular dependency break shadow-cljs? Just thinking out loud here

thheller10:03:03

circular how? cljs? no

thheller10:03:43

so to break it you call (shadow.cljs.devtools.server/stop!) and then the start above again?

mitchelkuijpers10:03:01

cljs.user> :cljs/quit
:cljs/quit
user> (shadow-server/reload!)
Worker shutdown.
shadow-cljs - HTTP server for :devcards available at 
:shadow.cljs.devtools.server/restarted
user> Exception in thread "async-thread-macro-4" java.lang.NoClassDefFoundError: Could not initialize class shadow.cljs.devtools.server.reload_classpath$process_update$fn__65735
	at shadow.cljs.devtools.server.reload_classpath$process_update.invokeStatic(reload_classpath.clj:21)
	at shadow.cljs.devtools.server.reload_classpath$process_update.invoke(reload_classpath.clj:21)
	at clojure.lang.PersistentVector.reduce(PersistentVector.java:341)
	at clojure.core$reduce.invokeStatic(core.clj:6747)
	at clojure.core$reduce.invoke(core.clj:6730)
	at shadow.cljs.devtools.server.reload_classpath$process_updates.invokeStatic(reload_classpath.clj:45)
	at shadow.cljs.devtools.server.reload_classpath$process_updates.invoke(reload_classpath.clj:38)
	at shadow.cljs.devtools.server.reload_classpath$watch_loop.invokeStatic(reload_classpath.clj:75)
	at shadow.cljs.devtools.server.reload_classpath$watch_loop.invoke(reload_classpath.clj:63)
	at shadow.cljs.devtools.server.reload_classpath$start$fn__65767.invoke(reload_classpath.clj:92)
	at clojure.core.async$thread_call$fn__9069.invoke(async.clj:442)
	at clojure.lang.AFn.run(AFn.java:22)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)

thheller10:03:12

I do that several hundred times when working on shadow-cljs itself yet I have never seen that error

mitchelkuijpers10:03:16

the error happens on the file change after reload!

thheller10:03:48

hmm do you use tools.namespace?

thheller10:03:27

but not during this process?

mitchelkuijpers10:03:38

Hmm yes I have run go

mitchelkuijpers10:03:02

That would make sense that it breaks it

thheller10:03:34

I don't know why it would though. maybe its something related to the nrepl change I did

mitchelkuijpers10:03:42

Maybe i should start running it externally

mitchelkuijpers10:03:55

Let me try that out to see if that breaks

thheller11:03:13

well I have shadow-cljs embedded in lein to develop it so it should work just fine

thheller11:03:51

can you try just restarting it directly from the REPL without calling the tools.namespace stuff?

thheller11:03:18

just trying to isolate if it might be trouble in your deps

mitchelkuijpers11:03:29

Hold on wil restart it first

thheller11:03:44

throw in a lein clean for safety

mitchelkuijpers11:03:40

I'll also run a lein deps tree

mitchelkuijpers11:03:33

hmm core async conflict might be related?

thheller11:03:16

hmm shouldn't be no

thheller11:03:26

didn't see anything from it on the stacktraces yet

mitchelkuijpers11:03:38

I just restarted

mitchelkuijpers11:03:42

en changed a file

mitchelkuijpers11:03:45

and nothing happens

mitchelkuijpers11:03:53

it does not reload

thheller11:03:33

still the same error?

thheller11:03:26

the core.async thread macro hasn't changed in forever so that shouldn't matter

thheller11:03:49

I have no clue. it might be the piggieback change I did because that messes with the *ns* binding which is a bit scary

thheller11:03:59

but piggieback does that so it should be fine

mitchelkuijpers11:03:32

Very weird the only thing is broken is the watching and recompiling

mitchelkuijpers11:03:37

the repl works like a charm

thheller11:03:54

I don't get why that would be broken. I didn't touch that.

thheller11:03:08

and why does it fail loading the class in the first place

thheller11:03:19

such a weird error

thheller11:03:31

wait does the reloading also not work if you just started it clean without stop! or reload! first?

thheller11:03:34

which version were you on before upgrading?

thheller11:03:53

I don't get why it fails on reload-classpath. I didn't touch that in forever

mitchelkuijpers11:03:53

Only other conflicts with jars that I find is jackson-core but I cannot imagine that breaking anything

thheller11:03:07

yeah doubtful

thheller11:03:21

wait do you AOT compile maybe?

mitchelkuijpers11:03:44

Would it help if I put shadow-cljs in verbose mode somehow?

thheller11:03:37

probably not. there is not additional logging in that place.

thheller11:03:28

I have never seen this error in several years of clojure. I don't understand why you'd get NoClassDefFoundError. clojure is supposed to create the class before loading it.

mitchelkuijpers11:03:30

Hmm I do a set-refesh-dirs

mitchelkuijpers11:03:33

And now it works

mitchelkuijpers11:03:42

When I removed that call

mitchelkuijpers11:03:19

I had this:

(set-refresh-dirs "dev/server" "src/main" "test" "src/cards")
from
[clojure.tools.namespace.repl :as tools-ns :refer [set-refresh-dirs]]

mitchelkuijpers11:03:31

removal works.. I still had this from the fulcro template

tony.kay19:03:51

The set-refresh-dirs was there because figwheel would copy cljc files into resources, and then server refresh will accidentally find them and cause problems. Shadow doesn’t do that, so it probably isn’t helping anything.

thheller11:03:22

I wonder why that would affect anything. will take a look at tools.namespace

mitchelkuijpers11:03:41

I'll see if it stays fixed

mitchelkuijpers11:03:26

Thank you for listening @thheller

mitchelkuijpers12:03:23

It also keeps working after resets

thheller12:03:40

good to know

mitchelkuijpers16:03:10

@thheller Now I am running into: java.lang.NoClassDefFoundError: Could not initialize class shadow.build.warnings$get_source_excerpts$iter__60601__60605$fn__60606$fn__60607$fn__60609

mitchelkuijpers16:03:30

Really weird that I am getting NoClassDefFoundError

thheller17:03:07

> val_waeselynck [17:28] @thheller I tend to have this sort of error after I uberjar my project while my code is running. I think this changes the class files in some way to messes up the REPL.

thheller17:03:21

do you do anything like that?

thheller17:03:18

but the shadow-cljs classes should never be written to disk anyways

thheller17:03:37

I backed out of shipping AOT code because of errors like this

thheller17:03:54

but I can't explain where this is coming from. which clojure version are you using?

mitchelkuijpers17:03:50

I am now running it separately with the shadow-cljs command

thheller17:03:19

did your clojure process use any classloader trickery?

thheller17:03:32

immutant or some other container?

mitchelkuijpers18:03:23

No nothing like that

hlolli20:03:24

cool, Im guessing you didn't set :devtools ?

:devtools {:http-root "public"
:http-port 8088
;; :http-handler dev.server/handler
:after-load visitor.main/init}
this is my current project, the after load would be my react init function.

jmckitrick20:03:35

Maybe it’s too old.. I’ll update it

hlolli20:03:47

"devDependencies": {
    "shadow-cljs": "^2.0.115"
  }
yup too old I think 🙂

jmckitrick20:03:30

I see that now lol

jmckitrick20:03:50

There it is!

jmckitrick20:03:03

Ohh, nice spinner

jmckitrick20:03:32

Wow, I might switch from lein/cljsbuild to boot/shadow in the same week, lol.

hlolli20:03:47

yup, I'm like a broken record repeating this tip, but you can basically start shadow-cljs watch and then start the backend to serve the output directory, you'll get the hot reload weather or not you're conencted to the localhost port given in the :devtools.

hlolli20:03:07

(and the hud)

jmckitrick20:03:10

I assume it plays nicely with boot as well?

hlolli20:03:00

yes, if you keep the clojure seperated from the clojurescript, then it would also work well with python, node or any backend.

hlolli20:03:00

some folks are mixing lein and shadow in some fancy way, have no idea if that works with boot, and what the gain is from doing that.

thheller20:03:09

@jmckitrick I know very little about boot and haven't done many tests. I know that it interferes a little with shadow-cljs related to caching and things. everything should work in theory but I really don't know.

thheller20:03:53

happy to look at problems it you find any though

jmckitrick20:03:05

I greatly appreciate the offer! We’re doing the first official clojure products at work, and I’ll be on the hot seat for any issues we run into along the way 😧

thheller20:03:58

the smoothest option is to just keep the CLJ and CLJS worlds separate. they don't benefit at all when you combine them and just cause headaches if your CLJS deps interfere with CLJ deps

jmckitrick21:03:17

Interesting. ok, duly noted.

jmckitrick21:03:53

Should I be surprised if the binary is much smaller than that produced by cljs-build?

thheller21:03:03

not really. people frequently report this.

thheller21:03:28

the config sets a couple of optmizations that you maybe didn't set when using cljsbuild

thheller21:03:38

and cljsjs is pretty ineffecient as well

jmckitrick21:03:56

I might be sold, then. I’m going to spend the day tomorrow digging in deeper. So much for generative testing day, lol.

justinlee22:03:42

I’ve updated my guide on how to use javascript in cljs. My goal here is to have something to point people to when they ask about this on slack. I’d appreciate a read before I start sending it to folks just to make sure I’m not mischaracterizing something. https://gist.github.com/jmlsf/f41b46c43a31224f46a41b361356f04d

jmckitrick22:03:02

@thheller doesnt it incur extra overhead to separate front and back ends? In other words how do I serve up the front end page and assets separately from the backend? I assume I need to run Express?

jmckitrick22:03:56

@lee.justin.m you probably know the answer as well

justinlee22:03:49

during development you just serve the front end from the shadow-cljs development server

justinlee22:03:19

during production, you’ll compile the front end to a javascript bundle and then serve it as if it were a static resource from the backend

justinlee22:03:59

the only annoying thing is that you have a cors issue during development

jmckitrick22:03:44

So I can’t really keep the code entirely separate, then, right? The payload still needs to end up in the js directory of the server project

justinlee22:03:27

I was assuming you’ve got a SPA front end that connects via some kind of API that is running on clojure.

thheller22:03:57

I wouldn't separate the code because you might want to share some code from the client and server

justinlee22:03:18

If you are running a templated backend then the “keep it separate” advice might be more complicated.

thheller22:03:25

if you compile your code to say public/js and configure your server to serve static files from public you are all set

justinlee22:03:57

Or if you’re doing something like server side rendering, that might call for something different.

thheller22:03:00

or the usual resources/public/js if you want to serve resources instead of files

thheller22:03:11

@lee.justin.m reading over your gist

thheller22:03:52

> The "double bundle" approach: same as (3)

thheller22:03:20

shouldn't that be like (1)? you don't need to tell the compiler about the double bundle at all in theory

thheller22:03:46

> "shoudl" typo

thheller22:03:20

> I do not reccommend either of these approaches for now:

thheller22:03:23

you do recommend #2 😉

justinlee22:03:49

I think it should say like (1) or (3) because you can do it either way (the two blog posts I link to do either either way)

thheller23:03:00

one extra thing that shadow-cljs does that the default cljs externs inference doesn't do

thheller23:03:23

since shadow-cljs fully processes all .js files it extracts some extra externs infos from them

thheller23:03:30

might be worth mentioning

thheller23:03:30

> Shadow-cljs's import syntax

thheller23:03:03

that makes it sound like string requires are shadow-cljs only. they are not. if :npm-deps ever works out it should work identically in CLJS

justinlee23:03:59

Accurate? > Use shadow-cljs automated externs inference. Shadow-cljs will give you warnings when it can’t figure things out and you can just provide a type hint. Because shadow processes all of your JavaScript libraries, Shadow can infer externs from them, which is a real advantage over some other approaches relying on the built-in compiler’s extern inference.

justinlee23:03:27

damnit i edited this so much that some stuff is out of order now 🙂

thheller23:03:29

in theory if externs inference for CLJS was perfect that would be enough. the extra JS processing just makes it a bit more reliable for now

justinlee23:03:44

is it true you can use figwheel with shadow if you want to?

justinlee23:03:04

okay fixing that

thheller23:03:27

in your example config. remove clojure/clojurescript deps, they are provided. :http-handler push-state is the default now so you can remove that as well

thheller23:03:04

>Note the :after-load entry point: this is what shadow-cljs will call when it hot reloads new code.

thheller23:03:40

Note the :after-load symbol, this is what shadow-cljs will call after hot reloading code finishes.

thheller23:03:43

or something like that

thheller23:03:56

the "after" is key here, as before also exists

thheller23:03:07

"when" is too ambiguous I think

justinlee23:03:48

you know i’m going to get rid of all that. it’s getting off topic

justinlee23:03:09

i just want to inform people about why shadow works better for imports

justinlee23:03:24

A quickstart guide should be separate.

thheller23:03:36

I wouldn't bash cljsjs so heavily. It works pretty darn well IFF you are only using a very small amount of it. say if you are only using React it is pretty darn good for that.

thheller23:03:49

problem is that it really doesn't scale well past say 3 packages

justinlee23:03:53

It was a freaking nightmare for me 🙂

thheller23:03:32

yeah probably starts breaking at 2 already

justinlee23:03:39

It’s so complicated! Here, learn this barely documented externs syntax! Here, learn boot!

thheller23:03:46

but I used it for a very long time when I just wanted react is it worked well for that

justinlee23:03:06

Well the real point of this document is for people who use lots of react libraries

thheller23:03:11

yeah making custom cljsjs packages is horrible. I wouldn't want to do that either

justinlee23:03:15

And it doesn’t work for that at all

justinlee23:03:10

I’ll look for places to tone it down. I don’t want to be mean to people who spent their free time on something.

thheller23:03:12

> Can use standard CDN distros?

thheller23:03:24

shadow-cljs: yes

justinlee23:03:09

oh shit that’s pretty cool!

thheller23:03:38

pretty good overview of the current options overall

thheller23:03:30

you could also mention that shadow-cljs actually allows full 100% interop (ns demo.bar (:require ["./foo" :as foo])) would load demo/foo.js from the classpath

thheller23:03:30

and that JS can actually require CLJS via import cljs from "goog:cljs.core"; cljs.assoc(nil, "foo", 1)

thheller23:03:12

this is not 100% perfect yet but it is a goal of mine to support compilation of JS projects that just want to start using CLJS without having to rewrite everything

thheller23:03:30

so just start by introducing things gradually one file at a time or so 😉

thheller23:03:59

thats definitely something CLJS can't do 😉

thheller23:03:02

in theory I could add support for https://www.webjars.org/ which also mirrors npm

justinlee23:03:45

Okay I added these two points. It’s a little OT but I agree it’s worth mentioning. * Shadow-cljs actually lets you load any JavaScript file on the classpath. So, (ns demo.bar (:require ["./foo" :as foo])) would load demo/foo.js from the classpath. [This is experimental.](https://shadow-cljs.github.io/docs/UsersGuide.html#_requiring_js) * It also allows interop in the other direction, [by embedding cljs in an existing JavaScript app](https://shadow-cljs.github.io/docs/UsersGuide.html#target-npm-module).

thheller23:03:15

npm-module isn't related to that

thheller23:03:45

well it kind of is but its a different thing altogether

thheller23:03:02

since webpack or whatever is doing the packaging then

thheller23:03:18

shadow-cljs just spits out webpack compatible code basically

thheller23:03:44

its complicated 😛

justinlee23:03:44

what’s the relevant section of the manual?

thheller23:03:02

dealing with js files I linked above

thheller23:03:36

hmm thats still missing an example for how the JS could talk to CLJS

thheller23:03:38

oh hehe yes. guess I did mention it.

thheller23:03:19

oh doh , { keyword } this doesn't work anymore with the latest closure compiler

thheller23:03:36

only cljs.keyword but the direct refer was broken by them 😞

thheller23:03:09

or does it? I'm confused

thheller23:03:18

too tired. I need sleep.

justinlee23:03:38

go to sleep. 🙂 thanks so much for your help. i feel better about this document now.

thheller23:03:51

thanks for writing it. sounds a bit like one giant ad for shadow-cljs. I like it 😉

justinlee23:03:07

i view it as essential guidance for any js->cljs transition 🙂

thheller23:03:17

alright I'm off to bed. gn8