Fork me on GitHub
#shadow-cljs
<
2018-01-21
>
mhuebert16:01:48

:infer-externs :auto with occasional ^js typehints works really well. I use a lot of JS libs, and it’s become extremely rare to hit a problem. JS interop with :advanced compilation used to be my #1 complaint with writing real-world clojurescript — frequent, painful, manual hunting of obscure bugs, interrupted by multiple-minute recompile times — and that whole experience is just gone now. I see an immediate warning whenever something should be hinted, I add a ^js somewhere, and just keep coding.

hlolli17:01:51

I'm trying to add a foreign js lib

:builds {:app {:js-options {:resolve {"libcsound" {:target :file
                    :file "resources/libcsound.js"}}}
(:require ["libcsound"]))
The required JS dependency "libcsound" is not available, it was required by "csound_wasm/core.cljs"
Something I'm not doing right, tried :target :npm and :require instead of :file. Same error.

thheller19:01:10

@hlolli what is the :target?

thheller19:01:43

:resolve currently only works when using :shadow as js provider (eg. for :browser)

hlolli19:01:57

:node-library

thheller19:01:04

:node-library just directly delegates to node require so we can't influence what that does directly

thheller19:01:19

you might be able to include it with a relative path

thheller19:01:46

(:require ["./libcsound" :as x]) with the file just next to the .cljs file

thheller19:01:15

hmm nah that probably won't work either

thheller19:01:48

spent so much time on the browser stuff I never really got to any of the node things

hlolli19:01:58

ok that's no problem, I fall back to js/require works fine 🙂

thheller19:01:10

ah no relative might work

thheller19:01:55

although it will likely try to compile with with closure which will most likely blow up

thheller19:01:05

so yeah js/require might be the safest option

hlolli19:01:30

ok, yes I think the relative works relative to the cljs source file "../../../" pattern

hlolli19:01:43

I stay with js/require !

thheller19:01:28

I opened this a while ago but didn’t get to it yet since I’m not sure how to resolve it properly. https://github.com/thheller/shadow-cljs/issues/131

hlolli20:01:33

of curiousity, you think that a node-library will perform better or worse in cljs-land when the compiled js-file is required or the original cljs source code is requried?

lilactown20:01:59

btw @thheller you have been an awesome help over the last few days. really appreciate you taking the time to help through some of these issues I’m having

thheller20:01:20

@hlolli not sure I understand the question? cljs source code?

thheller20:01:58

@lilactown np. a few people have been using shadow-cljs with macchiato already and I still want to look at the template and create one for shadow-cljs

lilactown20:01:06

wonderful. this confirms my suspicions about how figwheel reloads vs. shadow-cljs

thheller20:01:46

the only problem was that macchiato does not properly declare the npm packages it depends on

thheller20:01:04

and it uses the old style js/require calls so you only get those errors at runtime

thheller20:01:25

if it complains about cannot find module ’cookies` just npm install cookies

thheller20:01:37

can’t remember which packages were needed exactly

lilactown20:01:52

ah yeah. ran into one dep that the cuerdas library needed, but other than that I’ve been able to run it just fine. just working on hot loading

hlolli20:01:44

Im creating a node-module in cljs code for js users, but I can theoretically use that library im creating in cljs as well. Then I'm just wondering if it's worth releasing .jar and npm package, or is npm package fast enough that it wont make a difference.

thheller20:01:21

its definitely better to use CLJS code directly instead of the compiled output

lilactown20:01:21

question, since I’m not familiar with what-all-does-what yet: macchiato uses mount to “manage state” (still not exactly clear on what that means in context). would it make sense to use mount to manage the web server?

lilactown20:01:54

e.g. instead of storing a reference to the http/server obj in an atom, setup mount to manage start/stoping

Jakub Holý (HolyJak)14:01:05

yes. we use luminus-generated cljure server code and that is how it uses mount

thheller20:01:06

no idea what mount does either sorry

lilactown20:01:21

😂 ok, I’ll just use an atom for now

thheller20:01:35

from the template it looks like figwheel doesn’t bother with restarting the server at all

thheller20:01:56

which might work but node it notorious for keeping some state in some function closures somewhere

thheller20:01:01

that state wouldn’t get reloaded properly

lilactown20:01:11

yeah I’m pretty confused about that actually

lilactown20:01:11

when I tried to just drop in the core/server fn to :after-load, it complained that a server was still running on the port

lilactown20:01:15

but the code did reload

lilactown20:01:08

so I kind of assumed that figwheel was doing some kind of figgy magic to reload the server, but I really don’t know

thheller20:01:19

I can’t find any reference in the template to any figwheel reload hook

thheller20:01:39

so its probably just dumping in new code and hope that it works ok?

lilactown20:01:15

yeah ¯\(ツ)

lilactown20:01:42

I think I actually would rather not restart the HTTP server, since that might clear out my session state

lilactown20:01:55

but maybe the mount magic handles that…

thheller20:01:31

you don’t have to call stop/start, its just a recommendation

Alex H20:01:45

@lilactown fwiw, I use mount on the backend side exactly for that

Alex H20:01:09

@lilactown 3 components - http server (with immutant), an nrepl server, and a hikariCP instance for the database

Alex H20:01:47

@lilactown you can get it to not do anything on a namespace reload, for example - or you can tell it to stop and start the server - depending on what you want

Alex H20:01:41

(to be clear, that's with clj, not cljs on the backend, though)

Alex H20:01:25

but mount should behave about the same

lilactown20:01:12

I’ll probably set mount up to keep track of the HTTP server as well then

lilactown20:01:45

it does look like it clears out my session state when I restart the HTTP server, though. which means I don’t want to restart on each hot reload

Alex H20:01:22

(defstate ^{:on-reload :noop} ....) should do what you want

thheller20:01:10

not sure where the session state is kept but you can probably store it somewhere and re-attach on restart

thheller20:01:39

but should be fine to just not restart the http server if that works for figwheel

thheller20:01:18

if you dont’ want to use the the :before-load and :after-load callbacks just set :autoload true

lilactown20:01:37

I’m not able to see my changes to e.g. routes.cljs when I set :autoload true

thheller20:01:46

does it work in fighweel?

thheller20:01:16

(def routes
  ["/" {:get home}]

thheller20:01:02

how do you add a route?

thheller20:01:48

so the server.core keeps a reference to the router. :handler (wrap-defaults router) this won’t be reloaded.

lilactown21:01:58

:thinking_face: I wonder how figwheel is reloading it then

thheller21:01:24

trying to figure that out right now 🙂

thheller21:01:40

I think its this call (mount/in-cljc-mode)

thheller21:01:36

hmm nope that does nothing

lilactown21:01:29

I think it’s re-running the require’s at the top of app.cljs

lilactown21:01:57

I say, with all the authority of someone who’s done CLJS for 3 weeks

thheller21:01:35

^:figwheel-always seems to be used to force reload the .app ns always

thheller21:01:47

but it doesn’t do anything, the requires won’t be done again

lilactown21:01:17

OK, how could we set it up so that server.core doesn’t keep a reference to router?

thheller21:01:49

still trying to figure out what figwheel does that I don’t

thheller21:01:48

oh wait you set :autoload true in the build config. that still needs to be in :devtools {:autoload true}

thheller21:01:01

it appears to work otherwise

lilactown21:01:20

you’re right. it works just like figwheel when I make that change

lilactown21:01:39

thanks for going with me on this wild goosechase 😅