Fork me on GitHub
#shadow-cljs
<
2018-10-24
>
richiardiandrea01:10:14

I am noticing weird things too when reloading and I thought it was on my code base. I will try to repro after the update

bbss04:10:01

is there a way to use node_modules that are npm linked? It seems shadow-cljs doesn't pick them up.

emil0r07:10:06

@thheller getting this error

The required namespace "konserve.filestore" is not available, it was required by "infinitor/collector/database.cljs".
"konserve/filestore.clj" was found on the classpath. Should this be a .cljs file?
Looking in the repo for konserve they have one .clj file and one .cljs file. Is this a bug in shadow-cljs or should I look elsewhere?

thheller08:10:39

@emil0r looking at the repo isn't always the correct answer. looking at the .jar is. and that doesn't include the filestore.cljs. looks like that was created after the last release.

thheller08:10:22

@bbss how so? it should be working as long as node_modules/the-thing/... exists. the-thing is allowed to be a link. maybe need to upgrade if you get a complaint about not being allowed to use sources outside the project. that was fixed.

bbss08:10:21

ah, my local global version might be out of date. Cheers!

bbss10:10:41

I'm seeing linear growth in compilation times:

[:main] Build completed. (1197 files, 3 compiled, 0 warnings, 1.62s)
------ WARNING #1 --------------------------------------------------------------
point_cloud_layer_fragment_glsl assigned a value more than once.
--------------------------------------------------------------------------------
[:main] Build completed. (1197 files, 3 compiled, 0 warnings, 2.72s)
[:main] Build completed. (1197 files, 3 compiled, 0 warnings, 3.80s)
[:main] Build completed. (1197 files, 3 compiled, 0 warnings, 6.44s)
[:main] Build completed. (1197 files, 3 compiled, 0 warnings, 12.04s)
[:main] Build completed. (1197 files, 3 compiled, 0 warnings, 23.20s)
[:main] Build completed. (1197 files, 3 compiled, 0 warnings, 57.57s)
;;after shadow-cljs restart
[:main] Build completed. (1197 files, 1040 compiled, 0 warnings, 112.28s)

bbss10:10:58

however after restart + rm -rf .shadow-cljs the recompilation is fast again

thheller10:10:16

which version are you on? there was a bug like that a while ago

bbss10:10:41

Updating before asking my next question 😅

thheller10:10:51

hmm no that definitely had the fix for that problem

thheller10:10:10

if you see this again please run with --verbose

thheller10:10:16

otherwise impossible to tell where the time is going

bbss10:10:20

okay, will do

thheller10:10:46

if you have side-effecting macros I would check those first

bbss10:10:22

Not that I'm aware of.

thheller10:10:26

the cache issue where compiles got slower over time was fixed in 2.4.20 so must be something else

thheller10:10:49

they also didn't get slower but that much so quickly 😉

thheller14:10:08

> ... hangs a long time here....

thheller14:10:04

where? the point of the log is to first log when something starts and then again when something completes

thheller14:10:17

so there should be a <- msg with a high ms number?

bbss14:10:03

that's where it hangs. exactly there

thheller14:10:30

hmm thats odd .. there is no pending stuff unless you removed some lines?

thheller14:10:47

any -> without a matching <-?

thheller14:10:16

> <- Closure JS Cache read: 4 JS files (2427 ms)

thheller14:10:22

this is suspiciously slow

thheller14:10:58

please check how large .shadow-cljs/builds/main/dev/shadow-js/index.json.transit is?

thheller14:10:27

and .shadow-cljs/builds/main/dev/closure-js/index.json.transit

bbss14:10:02

-rw-r--r-- 1 baruchberger staff 155600 Oct 24 22:35 .shadow-cljs/builds/main/dev/shadow-js/index.json.transit -rw-r--r-- 1 baruchberger staff 298854289 Oct 24 22:55 .shadow-cljs/builds/main/dev/closure-js/index.json.transit

thheller14:10:11

what the heck 😛

bbss14:10:06

does transit somehow cache requests from my app?

bbss14:10:19

No clue why it would be that big

thheller14:10:27

no that is compiler cache data

thheller14:10:50

do you import any .js files directly?

thheller14:10:04

are they this large?

bbss14:10:23

Hmm, I don't think so.

bbss14:10:49

The files themselves are small, maybe their deps?

thheller14:10:14

check the output directory .shadow-cljs/builds/main/dev/closure-js

thheller14:10:18

whats the largest file?

bbss14:10:34

that one, by far

thheller14:10:55

yeah thats clear since it basically contains all the others

bbss14:10:00

-rw-r--r--  1 baruchberger  staff  298854289 Oct 24 22:55 index.json.transit
-rw-r--r--  1 baruchberger  staff       3958 Oct 24 19:43 module$gsv$api$partition.js
-rw-r--r--  1 baruchberger  staff      20392 Oct 24 22:53 module$gsv$ui$custom_point_cloud.js
-rw-r--r--  1 baruchberger  staff       5023 Oct 24 19:43 module$gsv$ui$point_cloud_layer_fragment_glsl.js
-rw-r--r--  1 baruchberger  staff       7160 Oct 24 19:43 module$gsv$ui$point_cloud_layer_vertex_glsl.js

thheller14:10:30

so it looks like closure is doing crazy stuff to one of your inputs

thheller14:10:35

it should never get this large

bbss14:10:26

the only thing I can imagine somehow, this morning I tried to use shadow-cljs to build a npm package, on a different project, it npm packs the directory (100mb) in the process.

bbss14:10:33

but it's a different project entirely.

thheller14:10:46

it makes no sense for the file to be that big .. its just an index ...

thheller14:10:53

can you send it to me?

thheller14:10:36

zipped please 😛

bbss14:10:39

Sorry I just deleted it. When it happens again I will.

bbss14:10:58

Judging by how it went previously that will take around 20 minutes..

thheller14:10:08

gah make a copy next time please

thheller14:10:18

impossible to tell whats going on if you delete the evidence 😛

thheller14:10:04

btw the :module-move messages are gone in the latest version

bbss14:10:36

I've pulled the latest into my shadow-cljs repo, but what was the command to install it locally again?

thheller14:10:02

why do you have a local repo?

thheller14:10:11

lein install

bbss14:10:57

I have a local repl because earlier you pushed a fix for something and I wanted to have it quick.

thheller14:10:15

its all released now 😉

thheller14:10:48

if you run lein install you must run the build-all.sh first

thheller14:10:03

otherwise some files will be missing

bbss14:10:28

Okay, will do after I reproduce.

thheller14:10:59

just observe the cache index on each compile. it should be almost constant in size depending on the amount of JS files used

thheller14:10:37

even 1mb is probably too big already

bbss14:10:18

-rw-r--r--    1 baruchberger  staff   10699 Oct 24 23:21 start.index.json.transit
->
-rw-r--r--  1 baruchberger  staff  26659 Oct 24 23:27 index.json.transit
Enough of a growth increase? or is this expected?

thheller14:10:31

no thats enough already

thheller14:10:40

unless you added many js files

bbss14:10:41

Do you want me to send them?

thheller14:10:48

yes that would help lots

bbss14:10:50

No added none, just editted a bit.

bbss14:10:02

Where to send?

thheller14:10:04

edits should definitely not affect the size

thheller14:10:21

ok found the problem I think

bbss14:10:31

so quick 🙂

thheller14:10:36

its pretty obvious if you look at the data

thheller14:10:41

the index is basically just a map that tracks whatever compiler settings were active and so on

thheller14:10:18

it tracks which polyfills closure injected

thheller14:10:25

thats supposed to be a set

thheller14:10:27

:injected-libs ("es6/util/inherits"
                 "es6/util/setprototypeof"
                 "util/objectcreate"
                 "es6/util/arrayfromiterable"
                 "es6/util/arrayfromiterator"
                 "es6/util/makeiterator"
                 "es6/symbol"
                 "es6/object/assign"
                 "util/polyfill"
                 "util/global"
                 "util/defineproperty"

thheller14:10:59

but it ends up as a list. so it basically doubles in size on each compile since it re-adds everything

bbss14:10:33

that's why it was so linear in time increase 🙂

thheller14:10:19

now only to figure out where it becomes a list ...

bbss14:10:04

Alright, no rush from my side. I can live with a rm + restart once in a while.

thheller14:10:26

no need for restart. you can just delete the index file

bbss14:10:40

even better :thumbsup:

thheller15:10:23

wow doh ...

thheller15:10:34

injected-libs
        (-> (.get injected-libraries-field cc)
            (keys)
            (into #{})

thheller15:10:02

-> instead of ->> ...

bbss15:10:03

1 char bug ㅋㅋㅋ

thheller15:10:02

TIL: (clojure.set/union #{} '(1 2 3)) => (1 2 3)

bbss15:10:02

Hmm, that is surprising indeed.

thheller15:10:23

set/union has so many weird behaviours ... should just use into ...

TeMPOraL15:10:09

dev> (clojure.set/union #{1 2 3} '(1 2 3))
#{1 3 2}
dev> (clojure.set/union #{1 2 3} '(1 2 3 4))
(2 3 1 1 2 3 4)

TeMPOraL15:10:24

source explains it all:

TeMPOraL15:10:26

dev> (source clojure.set/union)
(defn union
  "Return a set that is the union of the input sets"
  {:added "1.0"}
  ([] #{})
  ([s1] s1)
  ([s1 s2]
     (if (< (count s1) (count s2))
       (reduce conj s2 s1)
       (reduce conj s1 s2)))
  ([s1 s2 & sets]
     (let [bubbled-sets (bubble-max-key count (conj sets s2 s1))]
       (reduce into (first bubbled-sets) (rest bubbled-sets)))))

bbss15:10:02

Hmm, I see the implementation is very elegant. But a few warnings on non-sets would be nice.

thheller15:10:29

@bbss fixed in 2.6.17

bbss15:10:34

Thank you!

jerome16:10:26

I'm having trouble mapping react to preact-compat when targeting :npm-module to build the leaves (view components) of an existing JS preact app in CLJS. Would you all expect this to work for my shadow-cljs.edn?

{:source-paths ["src"]
 :dependencies [[cljs-css-modules "0.2.1"]
                [reagent "0.8.1"]]
 :builds {:npm {:target :npm-module
                :output-dir "build/cljs"
                :compiler-options {:infer-externs :auto}
                :js-options {:resolve {"react" {:target :npm
                                                :require "preact-compat"}
                                       "react-dom" {:target :npm
                                                    :require "preact-compat"}}}}}}
When I npx shadow-cljs compile npm I get
[:npm] Build failure:
The required namespace "react" is not available, it was required by "reagent/core.cljs".
The only way I've found to move forward is to create symlinks from node_modules/[react|react-dom] to node_modules/preact-compat

thheller16:10:34

@jeromedane :resolve is not supported for :npm-module or rather it is very limited

👌 4
thheller16:10:31

it only works reliably for :browser really. for :npm-module you really need to configure it in whatever you are targetting

jerome16:10:32

We might want to reflect that in the documentation for :resolve?

thheller16:10:37

eg. webpack or node

jerome16:10:21

Ah, I see. Thanks. Suggested add > It is therefore not recommended to be used with targets that use require directly (eg. :node-script[, :npm-module]) for those of us that are a little thicker than most. Thank you!! ❤️

shaunlebron18:10:50

@gklijs asked a question about loading .wasm files in cljs

claudiu18:10:48

think this is a job for a smart router. if you want this custom logic. got something like this built with fulcro

hmaurer18:10:30

@U3LP7DWPR the loading indicator isn’t the important bit though; that’s easily doable with fulcro right now; what I meant is that with suspense you could trigger data-loading at the component level

gklijs18:10:46

Thanks, I now have some wasm included in npm, will give shadow-cljs a try

richiardiandrea18:10:00

in the latest shadow, whever I do a require in the REPL I get:

another.ns> (require '[policy-fn.env :as env])
Circular dependency detected: policy-fn.env -> policy-fn.env
 (require '[policy-fn.env :as env])

richiardiandrea18:10:44

only custom namespaces, no core namespace like clojure.string

richiardiandrea18:10:06

actually, let me differentiate more

richiardiandrea18:10:39

it is a namespace that has been added to the path but at runtime, while the JVM was running

richiardiandrea18:10:40

I restarted the JVM and now I receive a bunch of [:did-not-find ...]

richiardiandrea18:10:50

compilation is successful

richiardiandrea18:10:50

for this file the watcher does not pick up the changes

mynomoto19:10:25

@thheller about the code you were fixing this morning why not set instead of (into #{})

mynomoto19:10:59

Works for -> and ->>

thheller20:10:39

Its just a habit to use into but yes set would have prevented this problem. Kinda still using into because it used to be faster ...

lilactown19:10:29

was there a change made to the way that module splitting works?

lilactown19:10:56

when I do a release build, I see this message now:

Module Entry "cambia.web.experience.dashboard.components.survey-prompt.client" was moved out of module ":survey-prompt".
It was moved to ":main" and used by #{:onboarding :survey-prompt}.
and the bundle is not created

lilactown19:10:14

it looks like there are cross-references between the two modules

lilactown19:10:34

but this worked in a previous version

thheller20:10:17

@lilactown yes I added that as a hard error because otherwise it goes by unnoticed

thheller20:10:36

you specified that namespace as as :entries for one of your modules

thheller20:10:48

but another module directly required it so it was never in that module

thheller20:10:08

so effectively making the :survey-prompt module useless

lilactown20:10:25

It looks like adding : survey-prompt to the dependencies of :onboarding fixed it

thheller20:10:02

if that makes sense for your module structure then that is the correct fix yes

thheller20:10:35

that error message probably will get more details at some point

thheller20:10:03

but the previous behavior with no errors was worse 🙂

lilactown20:10:52

Heh. Well luckily for us it didn't change the behavior at all while it was wrong

thheller20:10:02

well it changed your modules. the code was moved to :main previously as well

thheller20:10:19

so you thought you were splitting but actually everyone was always loading it

thheller20:10:38

making :main larger that it would otherwise be

thheller20:10:50

probably not by much if its just a few components but still

lilactown20:10:31

Yeah. It hadn't affected us yet because ATM we always load those modules

gklijs20:10:14

Using the shadow-cljs - browser quickstart should it be possible to just do an npm install to use an npm module. I tried, https://github.com/gklijs/shadow-gol-3d (last commit, rest is copy) but it keeps saying

The required JS dependency "game-of-life-3d" is not available, it was required by "gol/main.cljs".

Searched in:/Users/gerardklijs/Workspace/shadow-gol-3d/node_modules

You probably need to run:
  npm install game-of-life-3d
but when I look in node_modules it's there

thheller20:10:01

@gklijs there is no support for .wasm yet so that module won't load

gklijs20:10:46

ok, that too bad

thheller20:10:57

but you found a bad incorrect error message for packages that don't have a main but only module

thheller20:10:15

that could be fixed but then it would fail when trying to load the .wasm file

thheller20:10:25

so not much better

gklijs20:10:45

no.. It's not really well supported yet. Even with webpack I could not get a production build. I could take the compiled javascript and serve it with webpack probably, but then I lose easy reloading.

thheller20:10:11

I presume the .js file is Rust output?

thheller20:10:18

thats really where the problem is

thheller20:10:06

but thanks for the example. I can use that to test some stuff

gklijs20:10:07

yes, almost the default wasm-pack output, only added some utils methods at the end

thheller20:10:50

I never used the Rust stuff before so no idea how that part works

gklijs20:10:15

Kind of surprised how hard it's with clojurescript, did get it to work with Elm.

thheller20:10:47

what did you do in elm?

gklijs20:10:37

From rust it's pretty easy to create some wasm module, also there's a lot of js/wasm interop work done.

gklijs20:10:00

So far in Elm I just had the basics working, but I could load and start the wasm part, and get info back through a port.

thheller21:10:13

geez the generate file is just weird

richiardiandrea21:10:20

@thheller I have a Q...what can be the cause [:did-not-find policy-fn.api.query-events] error when connecting to nrepl? it does not happen in socket REPL but it does in nrepl, I switch a couple of versions of shadow, now on 2.6.10

richiardiandrea21:10:42

then a REPL command timed out. follows

thheller21:10:54

in-ns before require or ns

richiardiandrea21:10:55

oh but has that changed? I never needed that

thheller21:10:10

basically in-ns before the policy-fn.api.query-events has been compiled

thheller21:10:51

still need to check how CLJS behaves in that case. I just don't know what to do

thheller21:10:08

no that has not changed. has always been that way

richiardiandrea21:10:37

oh ok, so there must be something on the cider side

thheller21:10:09

no clue what cider does

thheller21:10:45

@gklijs is it possible to tune the wasm that gets generated? right now the .js files imports the .wasm and the .wasm imports the .js file right back

thheller21:10:14

thats kind of annoying to deal with since you can't process the .js in any meaningful way 😛

thheller21:10:31

the browser must also be able to load it

richiardiandrea21:10:32

@thheller if you can help me on the shadow side I can debug what broken

richiardiandrea21:10:41

cider does this:

(cider-nrepl-request:eval (format "(in-ns '%s)" ns)
                                (cider-repl-switch-ns-handler connection))

thheller21:10:14

@richiardiandrea in-ns is fine but what is happening BEFORE that? where is the require or so?

thheller21:10:52

which REPL are you connected to? your app? plain node-repl?

richiardiandrea21:10:19

it is a select-nrepl

gklijs21:10:39

@thheller I don't think so, it's probably also why you need to load asynchronously

gklijs21:10:08

There's some sort of chicken and egg problem there

thheller21:10:20

right now this is part of the code

thheller21:10:22

(import "./game_of_life_3d" "__wbg_time_ff03c978915ebe44" (func $./game_of_life_3d.__wbg_time_ff03c978915ebe44 (type $t2)))
  (import "./game_of_life_3d" "__wbg_timeEnd_5ba22134470392e6" (func $./game_of_life_3d.__wbg_timeEnd_5ba22134470392e6 (type $t2)))
  (import "./game_of_life_3d" "__wbg_random_86efc8986c8a8805" (func $./game_of_life_3d.__wbg_random_86efc8986c8a8805 (type $t3)))
  (import "./game_of_life_3d" "__wbindgen_throw" (func $./game_of_life_3d.__wbindgen_throw (type $t2)))

thheller21:10:46

so no matter what it will try to import the JS file relative to the path of the wasm

thheller21:10:52

thats just always going to break

thheller21:10:28

well it'll work if you leave the code alone and just use it via <script type="module" ...>

thheller21:10:50

but typically you can pass in an import import

thheller21:10:12

so you can pass in the functions instead of the wasm file trying to load them itself

gklijs21:10:34

Yes, or import it in index.ts, and load that with import("../ts/index.ts")

richiardiandrea21:10:01

@thheller this is what is sent

(-->
  id         "20"
  op         "eval"
  session    "b5cba90b-dd4f-446a-81ea-2a02be297cb2"
  time-stamp "2018-10-24 14:32:34.813926979"
  code       "(in-ns 'laputa.policy-fn.api.query-events)"
)
(<--
  id         "7"
  session    "b5cba90b-dd4f-446a-81ea-2a02be297cb2"
  time-stamp "2018-10-24 14:32:34.864485854"
  out        "[:did-not-find laputa.policy-fn.api.query-events]
"
)
(<--
  id         "20"
  session    "b5cba90b-dd4f-446a-81ea-2a02be297cb2"
  time-stamp "2018-10-24 14:32:44.826639415"
  err        "REPL command timed out.
"
)

thheller21:10:59

you didn't answer my questions

thheller21:10:08

what REPL is this? where is the require for that ns?

richiardiandrea21:10:10

right sorry 😄

thheller21:10:19

it just isn't loaded. thats all there is to it

thheller21:10:28

(in-ns 'i.do.not.exist)

richiardiandrea21:10:46

this is the form sent: (do (require '[shadow.cljs.devtools.api :as shadow]) (shadow/nrepl-select %s))

richiardiandrea21:10:01

after the clojure REPL boots up

thheller21:10:17

yes .. that is also fine. but you are still completely ignoring my question

thheller21:10:41

what REPL is this? what build :target? how is it started?

thheller21:10:53

node-repl? :browser?

thheller21:10:04

where is the require?

richiardiandrea21:10:31

let me answer all the Qs

richiardiandrea21:10:52

I start with yarn shadow-cljs watch az

richiardiandrea21:10:15

classpath resolved with deps.edn

richiardiandrea21:10:29

I launch and connect with the above

thheller21:10:32

:target :azure-app?

richiardiandrea21:10:50

after that I don't do any require

richiardiandrea21:10:07

I connect with cider and try to switch namespace

thheller21:10:09

run yarn shadow-cljs watch az --verbose

thheller21:10:01

does it compile your ns?

thheller21:10:33

did I get REPL working for the azure stuff? can't remember really

thheller21:10:54

ah node-lib. so should be fine

richiardiandrea21:10:46

@thheller it does not seem to compile that namespace for some reason

thheller21:10:07

then nothing requires it?

thheller21:10:27

whats your fn-map?

richiardiandrea21:10:41

yes I think that might be right

richiardiandrea21:10:35

ok but thanks for getting my head straight

thheller21:10:43

I think it would be much safer and less headache if cider just sent (require 'laputa.policy-fn.api.query-events) (in-ns 'laputa.policy-fn.api.query-events)

richiardiandrea21:10:00

yeah I agree with you and I will open an issue

thheller21:10:07

in-ns without require first also sucks in clojure

richiardiandrea21:10:10

it does not make sense to do anything different

thheller21:10:27

(in-ns 'foo.bar)
=> #object[clojure.lang.Namespace 0x25e67a35 "foo.bar"]
(+ 1 2)
CompilerException java.lang.RuntimeException: Unable to resolve symbol: + in this context, compiling:(C:\Users\thheller\AppData\Local\Temp\form-init11452515739617339391.clj:1:1) 

thheller21:10:29

also safer with require first if you switch into non-existent namespaces

richiardiandrea21:10:03

yep let me check with the cider folks but I totally agree

richiardiandrea21:10:37

@thheller I am opening an issue in cider but I have a small suggestion for shadow as well. What if the error messages returned [:not-required .....]? It would be clearer what you have to do next and what the problem was

thheller21:10:06

its basically no "not implemented error" because I don't know what to do

thheller21:10:16

need to check what the default CLJS repl does first

richiardiandrea21:10:43

ok cool I will open an issue then

richiardiandrea21:10:53

thanks a lot again

richiardiandrea22:10:47

ok opened and this is what happens in vanilla:

$ cljs-node-repl 
[Rebel readline] Type :repl/help for online help info
cljs.user=> (in-ns 'foo.bar)

foo.bar=> (+ 1 2)
3
foo.bar=> 

thheller22:10:20

ok so it just creates an empty ns?

thheller22:10:43

what happens if you in-ns into a ns that actually exists but was not required yet?

richiardiandrea22:10:30

uhm I would have to try on a project, will do it later ok? now I need to get stuff done for the day 😄

thheller22:10:54

I can try myself later

thheller22:10:00

or rather tommorrow 😉

richiardiandrea22:10:11

oh, also one day I think you suggested me to use shadow/repl instead shadow/select-nrepl, maybe I should PR cider

thheller22:10:41

doesn't really matter for cider given that it always uses nrepl

thheller22:10:22

as a user its nicer to type shadow/repl IMHO but for a tool it doesn't matter

richiardiandrea22:10:36

totally, good point

lilactown22:10:51

OK I have a weird thing I'm trying to do

lilactown22:10:08

(defmacro defstart! [args & body]
  `(do
     (defn ~'-start! ~args
       ~@body)
     (with-meta
       (defonce
         ~'start!
         (hecate.loader/reloadable (var ~'-start!)))
       {:export true :dev/after-load true})))

lilactown22:10:35

I'm trying to set the meta-data {:export true :dev/after-load true} from a macro. not having any success yet

lilactown23:10:23

ah.

(defmacro defstart! [args & body]
  `(do
     (defn ~'-start! ~args
       ~@body)
     (defonce
       ~(with-meta 'start! {:export true :dev/after-load true})
       (hecate.loader/reloadable (var ~'-start!)))))