Fork me on GitHub
#shadow-cljs
<
2020-09-04
>
grav07:09:33

When I want to hack on my node app, I first start up Shadow in watch mode. Then I need to wait a bit until Shadow is done compiling, before starting the node process. Can I automate this in some way?

Chris McCormick07:09:15

@grav you can try something like this:

srv=build/server.js
# run the server under node
( rm -f ${srv}; while [ 1 ]; do if [ -f ${srv} ]; then node ${srv}; else sleep 1; fi; done ) &
# watch-and-compile the server
( npx shadow-cljs watch server ) &
here the node script artifact being built is build/server.js

grav07:09:03

Ah, good idea. So simply remove the build artifact and then wait for it to show up!

👍 3
Chris McCormick07:09:06

at the end of the script i have a wait and run everything as background tasks. at the start of the script i have this:

trap killgroup SIGINT

killgroup(){
  echo killing...
  kill 0
}
which kills everything launched in the script when ctrl-C is run

Chris McCormick07:09:19

probably i should document this somewhere

grav07:09:35

Great hack! Thanks a bunch @chris358 🙂

👌 3
thheller07:09:57

or use shadow-cljs node-repl and go from there 😉

grav08:09:27

@thheller So you mean use Clojure instead of Bash? Sounds tempting :-) I haven't used the shadow api much, apart from (shadow/watch :my-app). But that doesn't seem to work in a node-repl? Am I mis-reading https://shadow-cljs.github.io/docs/UsersGuide.html#node-repl?

thheller08:09:23

I do not know what you read from that

thheller08:09:21

you just get a blank CLJS REPL that isn't tied to your :my-app build but can still just (require '[ :as x]) and (x/main "foo" "bar") or so (emulating a regular :node-script build for example)

thheller08:09:00

node-repl just manages the node process so you don't have to use hacks to wait for files to appear or so

thheller08:09:14

just gives you the regular clojure-like REPL experience

hoppy11:09:23

probably doing something horribly wrong, but this seemed like it used to work.

hoppy11:09:04

now getting TypeError: ia.format is not a function in release, but works in repl. Obviously getting minified away. Any good way to avoid?

thheller11:09:12

@hoppy you were probably relying on some of your :preloads loading goog.string.format

thheller11:09:25

just add it to your :require in the ns

thheller11:09:59

format is actually it its own "namespace". looks a bit weird but works

hoppy12:09:48

ok, this works. I'm not sure I understand why, or whether I need to.

hoppy12:09:56

but thanks

thheller12:09:48

dont remove the first one

thheller12:09:07

(ns my-app.core
  (:require [goog.string :as gstring]
            [goog.string.format]))

thheller12:09:13

I know its weird .. blame the closure library

thheller12:09:46

you need to because goog.string and goog.string.format format are basically 2 namespaces

thheller12:09:57

but for some reason goog.string.format is not actually a namespace, only a function

thheller12:09:20

but it is in its own file so it needs to be required properly

hoppy12:09:28

neato 😜

hoppy12:09:06

you are probably right though, I dug that code out of a different working project, so it was probably osmosis of some sort.

hoppy12:09:12

thanks again for the help

thheller12:09:54

yeah it works by accident if goog.string.format was required anywhere else but its not something you should rely on so the :require fixes that

Jakub HolĂ˝ (HolyJak)15:09:49

Hello! When I make a simple change to my app, it takes Shadow 3-7 seconds to recompile the change, after which the app re-renders. Is that duration normal? Or do I use too many libraries or is the changed UI namespace too large? What can I do to speed it up, so that I can change the code (add a new dom element, change button label, ...) and see the change "at once"? Thank you!!!

wilkerlucio15:09:11

IME keeping files small makes a good difference for compilation times, so it potentially has less things to compile

wilkerlucio15:09:14

3-7 seconds seems a very high time for me, in the biggest project I worked on (30k+ LOC), we were still getting compilations in 500ms avg (except when touching some of the big files, there it could go up to 3 seconds, but rarely more than that)

Jakub HolĂ˝ (HolyJak)16:09:25

Thanks! Perhaps something is wrong with my setup, I will clean up everything and upgrade shadow to latest.

thheller16:09:11

@holyjak that seems excessive and shouldn't be that slow. complex macros can significantly impact recompile speeds. maybe try running with shadow-cljs watch app --verbose or use the UI to see where it spends its time

❤️ 3
Jakub HolĂ˝ (HolyJak)17:09:20

Here is the verbose log:

[:main] Compiling ...
<- Resolving Module: :main (171 ms)
<- Compile CLJS: minbedrift/ui.cljc (118 ms)
<- Compile CLJS: minbedrift/ui/kostnadsdeling/ui.cljc (1460 ms)
<- Cache write: minbedrift/ui.cljc (852 ms)
<- Cache write: minbedrift/ui/kostnadsdeling/ui.cljc (1370 ms)
<- build target: :browser stage: :compile-finish (312 ms)
<- Flushing unoptimized modules (2066 ms)
<- build target: :browser stage: :flush (2465 ms)
[:main] Build completed. (1076 files, 2 compiled, 0 warnings, 6.64s)
I think I saw much better compile times on this app before summer so something in the environment must have changed...

thheller19:09:12

well thats defienitely slow. what does minbedrift/ui/kostnadsdeling/ui.cljc do? macro heavy stuff? maybe including huge edn data?

thheller19:09:08

Cache write: minbedrift/ui.cljc (852 ms) is also quite slow

thheller19:09:13

how big are these files?

Jakub HolĂ˝ (HolyJak)18:09:28

No. no big EDN. kostnadsdeling/ui has 593 lines, 31KB, and 13 direct macro calls, namely Fulcro's defsc . minbedrift/ui has 3KB and 75 lines (and includes the kostnadsdeling.ui namespace and others).

Jakub HolĂ˝ (HolyJak)18:09:05

After really upgrading to 2.11.1 I get

<- Cache write: minbedrift/ui.cljc (709 ms)
<- Compile CLJS: minbedrift/ui/kostnadsdeling/ui.cljc (1339 ms)
<- Cache write: minbedrift/ui/kostnadsdeling/ui.cljc (552 ms)
after a trivial code change

thheller18:09:00

source file size doesn't necessarily mean much if there is a macro in it expanding to something huge

thheller18:09:12

check the generated .js file for the size

thheller18:09:30

it might also just be something in your system intefering with file writing

thheller18:09:41

anti virus or that kind of stuff is often the cause

thheller18:09:51

scanning all newly written files making everything slow

👀 3
thheller18:09:42

I'm not on macos but on windows the windows defender thing is causing such issues and performance goes up significantly if the project dir is just ignored

Jakub HolĂ˝ (HolyJak)16:09:07

Thanks, I will try that!

Jakub HolĂ˝ (HolyJak)17:09:38

I guess my shadow issues are related to the following problem logged in the browser console, which I have not seen before (on a project I haven't used for a 2-3 months): > failed to parse websocket message {:type :repl/init, :repl-state {:shadow.cljs.repl/repl-state true, :current-ns cljs.user, :repl-sources [...], :repl-actions []}} #error {:message "Invalid reader tag: :type. Reader tags must be symbols.", :data {:type :reader-exception, :ex-kind :reader-error}} Any idea what could be wrong / where to look? I have just upgraded to shadow 2.11.1, deleted node_modules and .shadow-cljs, and installed/started from scratch.

thheller19:09:22

@holyjak uhm that doesn't look like 2.11.1? do you use project.clj or deps.edn and didn't upgrade there?

😅 3
Jakub HolĂ˝ (HolyJak)19:09:13

thank you! What about package.json? Does the version been manually synced between this and deps?

thheller19:09:46

if you use deps.edn then you need to update deps.edn

thheller19:09:15

the npm version in package.json should be somewhat close since things may break if they are too far apart

👍 3