Fork me on GitHub
#shadow-cljs
<
2019-12-07
>
deas08:12:14

Still hoping I'll get away without getting into the details of shadow-cljs, so here is one more ... 😉

deas08:12:27

shadow-cljs compile/`watch`give me a somewhat huge (12MB) module. That appears a bit odd for :none optimization. However, the cljs-runtime folder is 25MB and looks expected to me. Guess it all still somehow makes sense and there may be some desired redundancy. Could anyone please briefly explain how come the module may get that big?

p-himik10:12:46

If you don't use all that code, there's definitely some tight coupling that prevents it from being DCE'ed. Also multimethods in libraries that are imported but not used prevent DCE. Maybe some other things I'm not aware of.

deas10:12:31

Just looking at compile/ watchso I assume this is :none and hence, no DCE involved. The release build appears fine and just as expected. Will check build-report.

thheller11:12:55

that has since become the default. if you'd rather use the "old" style of loading many separate files you can set :devtools {:loader-mode :script}

thheller11:12:14

but this "huge" 12MB file is typically quite a bit faster to load

👍 4
deas11:12:37

@thheller Somehow felt that what I see is working as intended. And loading the "big" bundle is indeed fast - likely faster than loading hundreds of small files. Thanks for clarification.

thheller11:12:51

its easy to test out. just add the config bit I posted to the build while watch is running an reload the page

thheller11:12:49

see what feels best 😛 it kinda depends on how many files you load. if you use the built-in http server and enable caching both variants are pretty close on fast desktops

thheller11:12:26

no need to restart the watch between config tweaks

deas11:12:23

Hehe, was pleasantly surprised to see shadow watching build configuration as well. 😃 And :loader-mode :script indeed changes the size of the module as you pointed out. Again, thanks.

royalaid09:12:23

So a fresh recompile and it still complains BUT this time it is different

mhuebert12:12:36

I think I’ve got a minimal repro of @royalaid’s issue, https://github.com/mhuebert/repro-shadow-Symbol

👍 4
thheller12:12:04

:compiler-options {:output-wrapper false} seems to fix that?

thheller12:12:30

it is a weird scoping issue regarding the $jscomp variable

thheller12:12:25

its weird that my fix for that doesn't work though

mhuebert12:12:28

yeah, in the non-minimal build, :output-wrapper is necessary (setting to false causes some other error)

thheller12:12:30

very strange

thheller12:12:36

var $jscomp = {};
...
var $APP = {};
(function() {
  var $jscomp = $jscomp || {};

thheller12:12:51

I'm declaring it outside the output-wrapper so it should be a global

thheller12:12:59

but for some reason it isnt

thheller12:12:07

did they change the behavior of var? I could have sworn this was supposed to work with var. let or const wouldn't.

thheller12:12:52

if I remove the second var $jscomp it works fine but no clue how to get the closure compiler to do that

mhuebert12:12:27

i have deja vu because I ran into this exact same var issue a few months ago but can’t remember the context

thheller12:12:23

I did change the :output-wrapper default to true so if you didn't set that manually before you wouldn't run into this

thheller12:12:33

(it was only the default for single-module builds)

thheller12:12:29

:compiler-options {:output-feature-set :es6} also works if you can live with that

orestis12:12:32

AFK right now - but IIRC I tried a minimal reproduction of the above behavior and it doesn’t work. I can’t point to why (JavaScript scoping is weird) but in the issue I created, the workaround works.

orestis12:12:04

I think it’s something with hoisting

thheller12:12:16

right window.$jscomp might be better

thheller12:12:33

I'll try to figure out what is going on exactly. should be easier given that I have a reproducible case now.

orestis12:12:10

I made an experiment with just a global var and an iife, to see what can be done. Very easy to try things out.

royalaid12:12:59

@thheller if something is up with how var is working it might explain the spec issue I and BadAlgorithm see on github

royalaid12:12:51

The var is defined here, in react.js

royalaid12:12:34

and then is referred here in app-root.js but is somehow undefined

royalaid12:12:45

yeah for some strange reason the code that should be setting up the start of the $cljs$spec$alpha$$ object just gives back

royalaid13:12:11

This is just after evaluating the above var

royalaid13:12:14

Should it just be an empty object?

thheller13:12:27

it shouldn't exist at all ... nothing should be referencing that?

thheller13:12:13

doesn't really matter that it exists though. it shouldn't be used for anything

thheller13:12:13

do a quick search for $cljs$spec$alpha$$. that should have zero references

royalaid13:12:48

so then that still leaves the question as to why `

$cljs$spec$alpha$t_cljs$0spec$0alpha35496$$
is just defined and never assigned a value 😕

thheller13:12:13

it might have been removed by DCE?

thheller13:12:03

those types of vars are usually reify calls

royalaid13:12:10

Nvm, I am stumbling around and finding it now

thheller13:12:10

make sure it isn't moved to the other file though. it is typical for the closure compiler to "forward declare" something and then actually declare it later

thheller13:12:50

right yeah thats a reify call

royalaid13:12:09

so then this just isn’t called before it is used?

royalaid13:12:23

or at least that could be one reason why?

thheller13:12:45

I mean I don't know but I doubt it?

thheller13:12:37

this isn't CLJS where you have to define stuff before you use it. so as long as its declared somewhere in the file it won't matter 😛

royalaid13:12:13

Still the vm says its undefined in that second script

royalaid13:12:25

we see the definition in the first one

royalaid13:12:41

and the calls to populate the object

thheller13:12:09

how do you load the modules? are you sure its in the correct order? and not using async which would lead to race conditions? you can use defer?

thheller13:12:05

<script src="a.js" async> <script src="b.js" async>? this will load scripts in undefined order (based on whichever loads faster)

awb9913:12:31

Hi! My self hosted clojure that uses shadow cljs broke after upgrading from 2.8.40 to 2.8.80. Now the self hosted engine does not load certain dependencies anymore. Right now it looks like anything that depends on react no longer loads.

thheller13:12:15

@hoertlehner if you use deps.edn/project.clj I'm gonna guess its a closure-compiler/closure-library dependency conflict

awb9913:12:02

Only package json and shadow edn

thheller13:12:14

and what is the error?

awb9913:12:24

At least to generate the bundles

royalaid13:12:35

defer isn’t an option as the init script for the app depends on the modules under it

awb9913:12:42

It cannot load libraries

thheller13:12:36

don't know what that means

awb9913:12:03

Module not provided : 0

awb9913:12:12

Module not provided : 5

awb9913:12:25

This is in the browser console

thheller13:12:26

ok that means that the generated code is not loaded

thheller13:12:53

you can set :js-options {:minimize-require false} if you want to know what those numbers stand for

awb9913:12:27

Good trick

awb9913:12:50

I solved it by usinf silver searcher

thheller13:12:52

it doesn't change anything. it just gives you the long module name instead of a number

awb9913:12:55

To find the requires

thheller13:12:15

but yeah those files you found there weren't loaded

awb9913:12:19

Being able to see names and not numbers is already helpful

thheller13:12:05

I can only repeat what I warned about many times before .. this stuff isn't built for what you are trying to use it for 😛

awb9913:12:27

As I see it this files have been generated and are being served in tbe web server

thheller13:12:58

then check shadow$provide in the browser console

thheller13:12:04

it should have a 0 entry then

awb9913:12:50

Shadow.provide[0]?

thheller13:12:16

no. shadow$provide. you have the code right there 😛

thheller13:12:46

if its empty then EITHER it has not been loaded yet or used already

thheller13:12:14

if it has been used it is in shadow.js.files

awb9913:12:38

So it has been used then

thheller13:12:42

do you mix bootstrap builds? there should either be numbers only or strings only

thheller13:12:19

and again ... mixing bootstrap builds is not possible, they will clash.

thheller13:12:12

then I don't know what you are doing 😛

thheller13:12:30

gotta go buy some food. bbl.

🍝 4
dotemacs14:12:22

Hello, I heard about shadow.cljs and slep on it for the longest time. Started using it recently and I’m just so happy with it, that I’m ranting and raving to everybody who’ll listen about how good it is! Thank you Thomas (& contributors) for such a great tool. One thing that I’ve stumbled upon, which now I can’t find a link to, is a discussion that was had here on Slack at some point in the past, when used with react-native project, with Android simulator, the REPL connection just goes stale. The advice here was to run repl-runtime-clear. My question is: what is the recommended way to do it? Bellow I’ll describe my setup and the approach, in some very obvious details, just in case. I use the REPL via CIDER with nREPL. In my shadow-cljs.edn I have a following setup:

...
 :nrepl {:port 3333}

 :builds
 {:app
  {:target :react-native
   :init-fn 
   :output-dir "react-native/app"
   :js-options {:js-package-dirs ["react-native/node_modules"]}
   :devtools {:repl-init-ns 
...
Once I start the REPL I specify shadow as the REPL type and :app as the build. This starts the REPL and starts the build, which once complete goes in the above specified ns . When the REPL goes stale, where I can’t even eval something like '2, I then do:
> :repl/quit
user> (require '[shadow.cljs.devtools.api])
user> (shadow.cljs.devtools.api/repl-runtime-clear)
user> (shadow.cljs.devtools.api/repl :app)
cljs.user>
At this point, I’ve recovered the REPL and can plough on as expected. Is this the recommended flow to clear the stale REPL session? If the answer is yes, what’s the way to create aliases that can be picked up, so that I don’t have to manually type up the full (require '[shadow.cljs.devtools.api])? Say like in leiningen projects where you can create dev/user.clj file where you can have the desired requires. And another, minor thing, once I’ve done the above, the ns I’m in, as shown by the prompt is cljs.user. But as soon as I enter something at the REPL, then the prompt changes to what I’ve set in my :devtools {:repl-init-ns config. Is there a config that I could set so that the REPL prompt can be updated automagically? Thanks

thheller15:12:01

@dotemacs I wish that repl-runtime-clear wasn't necessary at all but I haven't found a good way to solve that problem yet. your workflow seems fine. you can create a user.clj if you want.

thheller15:12:29

the REPL showing the wrong ns is your editor. can't do much about that.

dotemacs17:12:26

@thheller oh please don’t take it as criticism, I’m very grateful for your work on shadow.cljs! About adding of user.clj what is the recommended convention: • apart from having src under :source-paths , would you create something like dev/user.clj ? • or would you just put user.clj under src directory? • or is there some other way? What is the “shadow” way of doing it?

thheller17:12:39

that has nothing to do with shadow-cljs really. its clojure doing this. I personally do not like using user.clj since that is always loaded unconditionally.

thheller17:12:59

you can put it under src or dev (as long as thats in :source-paths too) it really doesn't matter

thheller17:12:18

it becomes relevant if you want to publish libraries

thheller17:12:51

then you don't want to include your user.clj so I guess it is useful to stick with using dev

dotemacs17:12:31

Got it, thanks for the explanation @thheller :thumbsup:

jcb18:12:40

Hi all, it seems that a few people using latest luminus template including shadow-cljs are having a weird issue compiling a jar - IllegalArgumentException: No matching field found: getSourceName for class com.google.javascript.jscomp.JSError . I'm unsure how to proceed. Thanks!

thheller18:12:21

@jcb that happens when an incompatible closure-compiler version is used. most likely via some dependency conflict. should be these versions

[com.google.javascript/closure-compiler-unshaded "v20191027"]

   [org.clojure/google-closure-library "0.0-20191016-6ae1f72f"]
   [org.clojure/google-closure-library-third-party "0.0-20191016-6ae1f72f"]

jcb18:12:10

thank you!

jcb19:12:18

Sorry, I realise that I'm asking questions about something that you didn't write, but, that stepped me forward but that's opened up a number of other build issues -

jcb19:12:22

------ WARNING #1 - ----------------------------------------------------------- Resource: com/cognitect/transit.js:649:8 variable module is undeclared -------------------------------------------------------------------------------- ------ WARNING #2 - ----------------------------------------------------------- Resource: com/cognitect/transit/impl/writer.js:256:8 variable isObject is undeclared -------------------------------------------------------------------------------- nil Closure compilation failed with 62 errors --- goog/array/array.js:42 The result of a goog.define call must be assigned as an isolated statement. --- goog/array/array.js:50 The result of a goog.define call must be assigned as an isolated statement. --- goog/asserts/asserts.js:50 The result of a goog.define call must be assigned as an isolated statement. --- goog/async/run.js:26 The result of a goog.define call must be assigned as an isolated statement. --- goog/async/workqueue.js:43 The result of a goog.define call must be assigned as an isolated statement. --- remaining errors ommitted ...

thheller19:12:39

thats likely still a version conflict on closure-library this time

jcb19:12:57

oh, I see. I still get the transit issues. but the rest have gone. Thanks again!

thheller19:12:52

yeah the transit stuff is annoying but can't do anything about that

thheller19:12:57

safe to ignore

jcb19:12:22

lovely, thanks