Fork me on GitHub
#shadow-cljs
<
2018-04-14
>
Alex H13:04:47

@thheller, I'm really struggling with advanced optimisation of JS-on-classpath (which in turn imports other libs); it starts renaming attributes like crazy, breaking all sorts of things, because I think the JS-on-classpath itself gets optimised separately from its imports

Alex H13:04:24

@thheller,is there some way of making that work? would it work any differently if my JS-on-classpath was a separate node module instead packaged up with rollup or so?

thheller13:04:58

@alex340 js on the classpath is optimized. so you'd need to write externs for JS interop since they can't be inferred by the CLJS compiler.

thheller13:04:10

you can try tunning shadow-cljs check your-build

thheller13:04:19

although that will likely create a lot of warnings

Alex H13:04:44

yea, I guessed as much, but there's a metric ton of externs that get messed up

Alex H13:04:03

my JS-on-classpath is effectively a wrapper around slate (the editor thing), which in turn brings in immutablejs

Alex H13:04:26

and none of that has a good way of defining externs for, not with ES6 modules anyway?

thheller13:04:38

I want to add an option so the classpath-js gets treated like npm js

thheller13:04:46

meaning that it doesn't go through :advanced

thheller13:04:11

that would probably fix everything

Alex H13:04:15

but it'd still go through :advanced at the time the final bundle gets created?

Alex H13:04:20

either way, yes, that'd be awesome

thheller13:04:30

but really give check a shot

thheller13:04:40

writing externs is extremely simple with shadow

thheller13:04:03

I'll walk you through it if you want

thheller13:04:16

just run it once and tell me how many warnings you get

Alex H13:04:20

yep, on it

thheller13:04:33

if its more than say 100 its probably not worth it

thheller13:04:40

but shouldn't be that much usually

Alex H13:04:18

36 + 20 warnings (starts counting twice)

Alex H13:04:39

let me paste it somewhere

thheller13:04:41

what is the exact wording again? something about propery not defined

Alex H13:04:56

File: /home/alex/code/dlt/src/gen/slate-code.js:99:19 Property endBlock never defined on _change$value

Alex H13:04:00

for example

thheller13:04:14

what is your build id?

thheller13:04:07

create a externs/<your-build-id>.txt and the you add one word per line

thheller13:04:18

handleOuterClick

Alex H13:04:36

really? that simple?

thheller13:04:42

for every Property ... never defined

thheller13:04:20

and do yourself a favor while doing this: run shadow-cljs server separately

Alex H13:04:41

out of curiosity - should I do that for the ones coming from clojure bits & pieces as well?

thheller13:04:51

then run shadow-cljs check until the warnings are gone 😉

Alex H13:04:56

e.g. in that output re.unicode, instaparse.core

thheller13:04:44

but yes you can also just put those into the .txt file

Alex H13:04:44

yea, I did that

thheller13:04:47

doesn't really matter

Alex H14:04:02

I have :infer-externs :auto

Alex H14:04:56

midly weird some of those, like "getItem never defined on ShadowJS"

thheller14:04:20

ShadowJS is the "type" assigned to anything returned by require

thheller14:04:17

Property core never defined on instaparse

thheller14:04:25

this is weird though? isn't that a cljs namespace?

Alex H14:04:49

yea, my bad, I think. was just trying to optimize things out manually, and I think defparser (the macro) actually needs instaparse.core ns

thheller14:04:13

yes probably

Alex H14:04:30

didn't realize the externs problem was so simple. spent a few hours last week messing up with weird jsdoc strings to tell closure about types

thheller14:04:48

well its only this simple in shadow-cljs 😉

thheller14:04:00

everywhere else its a nightmare

Alex H14:04:34

btw, thanks for that bundle size thing you pointed me at - very useful

Alex H14:04:49

a question about those Cannot infer target type in expression - from what I read in the shadow-cljs doc the other day, you can effectively get rid of them by marking them with ^js metadata - however, is that really required when the whole thing ends up going through closure?

Alex H14:04:15

for example, it complains about some like getToken, which are provided by the google closure library, which presumably will get mangled the same way, so should just work?

Alex H14:04:27

(even without the ^js metadata on it)

thheller14:04:16

isn't this mentioned in the docs? you can tag it with ^goog or ^clj to make the warnings go away

Alex H14:04:22

don't see any mention of ^goog, but now that you mention it, I do see ^clj

thheller14:04:38

^goog is for stuff from the closure lib

thheller14:04:17

in rare circumstance if could become a problem if you tag something not-cljs with ^clj

Alex H14:04:04

is there some way of waiving warnings from cljs dependencies?

Alex H14:04:25

I think it's all clean now, apart from some noise coming in from reagent, instaparse, goog/base and cljs internals

thheller14:04:00

whats left?

thheller14:04:27

variable Java is undeclared

thheller14:04:42

for this you can add global:Java to the .txt file

thheller14:04:51

forgot that I need to add that

thheller14:04:02

hmm yeah can't make those go away

Alex H14:04:21

one less with that global:Java, but yea, still those 12 there

thheller14:04:12

did it work?

Alex H14:04:21

about to try

🤞 4
Alex H14:04:00

most of it does, but the slate-based editor doesn't really work, somehow

Alex H14:04:07

doesn't show any errors on the console either, though

Alex H14:04:26

some rendering issue, the editing itself worked fine

thheller14:04:37

you can try shadow-cljs release app --debug but I doubt that would change anything

thheller14:04:43

might make it easier to debug though

Alex H14:04:22

does this preserve console.log messages?

Alex H14:04:33

for some quick & dirty debug

thheller14:04:52

they are not removed yes

Alex H14:04:27

interesting. it is some mangling gone wrong

Alex H14:04:39

even though there is no warning about it, adding renderMark to the externs list fixes it

Alex H14:04:07

(renderMark is a prop to slate's react editor component, and the function I was passing in for that prop was not getting called)

Alex H15:04:47

yea, doing a diff of the builds with/without that shows that there's two props getting messed up for some reason - renderMark and decorateNode

Alex H15:04:52

mangled, that is

Alex H15:04:53

no idea why

Alex H15:04:47

I've added a comment to that gist to show the original code around that area

thheller15:04:57

hmm yeah all this stuff is not 100% accurate unfortunately

thheller15:04:23

good enough for most things but sometimes things seem to get lost

Alex H15:04:51

is there any reason why most props would map fine, but some would get mangled like that?

Alex H15:04:59

they are pretty symmetric as far as I can tell

thheller15:04:42

not sure. any difference in the JS?

thheller15:04:07

maybe just something the closure compiler doesn't correctly check yet?

Alex H15:04:10

not that I can tell - I have pasted the JS going into it in a comment on that gist

Alex H15:04:05

renderNode, renderMark and decorateNode look pretty similar, yet the latter two get mangled but the first one is ok (and so are all other props on that thing)

thheller15:04:02

hmm looks like it might be related to the name being identical to the value maybe? renderMark: renderMark,

thheller15:04:24

maybe the closure compiler gets confused by that

Alex H15:04:27

interesting

thheller15:04:31

decorateNode: function decorateNodeFoo() {

thheller15:04:15

try this. if that fixes the decorateNode issue we can probably try to create a minimal repro and report to the closure compiler

thheller15:04:30

dunno where renderMark is coming from but if you can change the name for that var as well try that too

Alex H15:04:08

nah, same thing

Alex H15:04:31

I renamed both decorateNode and renderMark to decorate and renderMarkFoo respectively

Alex H15:04:33

same renaming it to something else entirely (abcd)

thheller15:04:01

what does the generated js look like

thheller15:04:16

should be in .shadow-cljs/builds/<your-id>/dev/closure-js

thheller15:04:47

ah crap nevermind. thats a transit file

Alex H15:04:21

renderNode:renderNode$$module$gen$editor(_this.props.readOnly), renderMark:renderMarkFoo$$module$gen$editor, decorateNode:function decorate() {\n return undefined;\n }, value:_this.props.value,

Alex H15:04:33

looks healthy, in other words

thheller15:04:56

but adding those to externs fixes it?

Alex H15:04:04

yep, I'll use that as a workaround

Alex H15:04:12

makes me feel slightly uneasy, but good enough for now

thheller15:04:47

yeah I have no idea why closure wouldn't mention those in check

Alex H15:04:14

no worries, I have taken up enough of your time!

Alex H15:04:32

seems to work well apart from this quirk

lwhorton18:04:08

i just cannot get my vim-fireplace to work, and I have no idea where to look next. 1) start a shadow server 2) from inside a .clj buffer connect via :Connect <nrepl://localhost:port> 3) I can now use :Eval (+ 1 2) and get 3 (yay the connection to nrepl works) 4) cannot use :Eval from inside a .cljs buffer (always spits out Fireplace: class clojure.lang.Compiler$CompilerException) 5) from a .clj buffer run shadow...api/watch :app — get back :watching — success! 6) connect to the js environment by opening a browser 7) still no Eval in a .cljs buffer 8 ) from a clj buffer run shadow...api/nrepl-select :app — get back [:selected :app] — success! 9 ) from a clj buffer :Eval (js/alert) yay it works 10 ) still nothing works from a .cljs buffer

lwhorton18:04:20

the reason i’m asking here is because fireplace works with lein’s nrepl, and I can eval from a .cljs buffer, but i just can’t figure out the differences between repls

thheller18:04:22

wasn't there something like :Piggieback or so?

lwhorton18:04:37

i’m not sure where piggieback fits in — my understanding was nrepl-select :id was going to already put me in a cljs environment?

thheller18:04:41

so after step 5 you run :Piggieback :app?

thheller18:04:14

it puts you into a CLJS environment on the server yes but the client might also need to update something

lwhorton18:04:56

:Piggieback [{env}]     Create a new nREPL session and invoke
                        cemerick.piggieback/cljs-repl with the given or
                        default (Rhino) environment.  This will also happen
                        automatically on first eval in a ClojureScript buffer
                        if not invoked explicitly. If {env} is a number, the
                        piggieback repl-env will will use a cljs.repl.browser
                        (rather than a Rhino) env with the port set to the
                        number provided.

thheller18:04:09

no clue really. might need to ask somebody that knows vim

thheller18:04:38

what happens when you run :Piggieback :app?

lwhorton18:04:18

everything works like magic. 💕

lwhorton18:04:24

thanks again my man. do you have a patreon (or equiv) setup for shadow-cljs by the way?

thheller19:04:13

kind of. I set it up but didn't tell anyone because I'm not really sure I want/how to do this.

thheller19:04:41

that was like 2 months ago and didn't touch it since then 😛

lwhorton19:04:57

a few days ago you mentioned that you do or dont have plans to allow running a shadow clj(s)-repl with an alternative default namespace (like how cli-tools’ clj automatically picks up the user ns? I can’t remember which.

thheller19:04:42

I do have plans and a partial implementation

lwhorton19:04:45

the reason I ask is I basically just want access to the 3 spec generator namespaces required to do generative testing in a repl - test.check.generators, spec.alpha, spec.gen.alpha

thheller19:04:00

I still think it would be way better if the client did this though

lwhorton19:04:42

isn’t the “client” the process invoking shadow-cljs clj-repl (assuming you already have a server running in the background)?

thheller19:04:17

oh I thought you meant to nrepl

thheller19:04:29

for clj-repl that would be easier to add yes

larshelg19:04:39

I get one and just one warning: Use of undeclared Var clojure.string/join. Some libary is using clojure/string. I'm not but thats ok. However the hot reloader gives the compiler warning every time I make a change and messes up the hot loader. I tried to add :warnings false in the compiler-options but still get the warning after compilations. How to turn compiler warnings off?

thheller19:04:47

@larshelg it should only warn once for code that lives in jars by default. if the warning is in a file on your classpath you'll need to fix it.

larshelg20:04:18

I see. I will take a look. So there is no way to simply turn warnings off? If not permanently just for hot reload?

thheller20:04:04

not currently no.

larshelg20:04:10

Warning is this: File: rewrite_clj/parser/string.cljs:39:16

larshelg20:04:18

I think strangely its from a jar

larshelg20:04:15

Actually there is two, this is the second one: File: zprint/spec.cljc:379:14

thheller20:04:17

try shadow-cljs clj-repl and then ( "rewrite_clj/parser/string.cljs")

thheller20:04:34

if its in a jar open a bug report on github please

larshelg20:04:56

Will do, thanks for the input 🙂

thheller20:04:31

(should give you something like jar:... or file:.. urls

larshelg20:04:10

jepp this: #object[java.net.URL 0x29a2b3d7 "jar:file:/Users/larsstrand/.m2/repository/rewrite-cljs/rewrite-cljs/0.4.4/rewrite-cljs-0.4.4.jar!/rewrite_clj/parser/string.cljs"]

thheller20:04:36

and the warning does not go away one the SECOND compile?

thheller20:04:00

hmm ok thats definitely a bug then

larshelg20:04:49

everything is working so smooth with my setup, using reframe and semantic-ui-react

larshelg20:04:04

but this two warnings messes up my hot reload flow

thheller20:04:22

you can fix it

larshelg20:04:26

i just have to do full refresh of my app every time

thheller20:04:36

if you take the file out of the jar. put it in your classpath. and fix the warning 😉

larshelg20:04:04

hehe, i'll try

thheller20:04:06

hmm do you know the github repo for this?

thheller20:04:11

you can just take that file and add a [clojure.string] to the requires

larshelg20:04:33

yeah you can see its not imported/required

larshelg20:04:39

so its a bug

larshelg20:04:07

so since i'm doing this, whats the easiest way to add it to the classpath?

larshelg20:04:38

just copy the file

larshelg20:04:57

or make a rewrite_clj folder in my src?

larshelg20:04:08

and put it there...

thheller20:04:16

yes create a src/rewrite_clj/parser/string.cljs in your project