Fork me on GitHub
#shadow-cljs
<
2020-06-25
>
neilyio01:06:37

I'm getting a INTERNAL COMPILER ERROR trying to use https://github.com/oliver-moran/jimp in a new ClojureScript project. I've installed it with npm install --save jimp , and using :require ["jimp" :as jimp] . Not sure what to do, my Google searches have been dead ends.

dpsutton01:06:19

Have you looked in the shadow users guide for the different ways to interact with node libraries?

dpsutton01:06:00

There are examples of all the ways to import npm libs. Perhaps you could identify which jimp is and make sure you are requiring it correctly

neilyio01:06:03

Yes, jimp asks for var Jimp *=* require('jimp'); and my import seems correct according to the user guide:

(:require ["jimp" :as jimp])

neilyio01:06:56

Full, painful output:

lilactown01:06:23

I would check out what node_modules/jimp/browser/lib/jimp.js looks like

lilactown01:06:44

it might be in a weird format and/or require some sort of processing before being usable by shadow-cljs

neilyio01:06:11

I'll check it out, thank you for the pointer. It's a little frustrating to have this error from a "npm install" when it seems like a perfectly good CLJSJS package for jimp is available... but my understanding is that there's no way for me to use CLJSJS jimp in shadow-cljs, correct?

lilactown01:06:38

that’s correct, yeah. CLJSJS packages do not work with shadow-cljs

dpsutton01:06:43

Have you seen the import style and checked what form it should be in the users guide?

lilactown01:06:18

you could try using the version that is on CLJSJS. It’s 0.2.27

lilactown01:06:38

@dpsutton the import style would probably not effect this, since it’s failing to even process the file

lilactown01:06:42

it’s not breaking on usage

neilyio01:06:14

Yikes, node_modules/jimp/browser/lib/jimp.js is big. I really don't know what I'm looking for here. Here's the file if you're curious.

lilactown01:06:51

yeah, it’s failing at the exports["default"] = void 0 for some reason

lilactown01:06:15

have you tried restarting shadow-cljs yet?

neilyio01:06:26

Yes, a couple times. Also updated it.

lilactown01:06:45

you could also try and require something other than the browser build

lilactown01:06:12

e.g. ["jimp/es/index.js" :as jimp]

lilactown01:06:44

I’m just spit balling, I am not really sure why it fails to process that file

neilyio01:06:45

Good thinking. I'll try that and then the CLJSJS build if nothing works.

neilyio01:06:18

The only thing that came up in my searching was that "It's a Google Closure Compiler bug".

neilyio01:06:40

["jimp/es/index.js" :as jimp] worked! It compiles now.

neilyio01:06:57

How did you know to do that?

neilyio02:06:44

Also, do you think there's any point in raising this issue in the google/closure-compiler repo? Should I post the file there?

lilactown02:06:03

reading the docs and source of jimp helped a bit

lilactown02:06:03

the README talks about the different builds and their tradeoffs. the browser build is something specific to webpack

lilactown02:06:19

at least, AFAICT

lilactown02:06:37

either way, I had hope that the ES module was built in a way that was more amenable to GCC’s parser

neilyio02:06:25

Thanks for all your help with this, saved me hours.

sova-soars-the-sora04:06:29

@neil.hansen.31 is it not the coolest thing when somebody saves you mountains of effort?! gotta give thanks. gratefulness the blessing

💯 3
bbss07:06:39

I am trying to use shadow-cljs as a library. I want to grab some cljs with npm dependencies from a jar or files. I found out I can do that with get-classpath-entries and index-classpath from shadow.build.classpath . Furthermore I am using shadow.build.api to configure the build with the various api/with-* and seem to successfully compile-sources. But I don't see the output appear in the :output-dir I wonder what I'm missing for that to work.

thheller07:06:38

you need to "flush" it but each :target option has its own way of doing that

bbss07:06:00

okay, thanks. Searching for flush examples :)

thheller07:06:27

what are you trying to do exactly? none of those things are documented in any way and not really part of any public API I recommend using 😛

bbss07:06:20

On a high level, I am trying to make "plugins" that provide a nice way to use cljs and JavaScript libraries from Clojure by providing convenient api's to them and a base cljs app that relays usage of that api from clojure.

bbss07:06:33

And right now I want to grab the base-app for each plug-in and compile it with shadow-cljs.

thheller07:06:53

I don't understand 😛

bbss07:06:33

for example if you'd want to use http://deck.gl

bbss07:06:42

awesome webgl dataviz stuff

bbss07:06:06

I'm wrapping that JS and allowing it to be used from Clojure

bbss07:06:05

by running a web server with a base-app that understands calls you made to the clojure wraper

bbss07:06:22

and the idea is to have multiple different JS libraries available like that

thheller07:06:28

I still don't understand 😛

thheller07:06:37

what is a "base-app"?

bbss07:06:56

base app is some clojurescript that bridges the calls you made to the clojure wrapper to the actual JS

thheller07:06:10

how do you call the actual JS?

thheller07:06:32

I mean how do you intend to call CLJS from CLJ?

bbss07:06:52

run a webserver that passes websockets messages to the running base-app

thheller07:06:10

and the user is supposed to open a browser?

bbss07:06:23

well, the library I'm making does that, but yes

thheller07:06:50

ok, so its a regular :browser build and you just dynamically add a few :entries for your plugins?

thheller07:06:00

so why the low level API use?

bbss07:06:24

Hmm, I tried the higher level api, which is devtools.server I think? But that didn't pick up my resources well.

thheller07:06:39

(shadow.cljs.devtools.api/compile* {:build-id :foo :target :browser :modules {:main {:entries [foo.bar-plugin] :init-fn {})

thheller07:06:07

(shadow.cljs.devtools.server/start!) needs to be running before that though

bbss07:06:37

then it would pick up :foo from a shadow-cljs.edn in project root right?

thheller07:06:54

no, this is entirely custom config

thheller07:06:16

you can call (api/get-build-config :foo) and then update-in or whatever and pass that to compile*

bbss07:06:31

where would it get the resources from?

bbss07:06:06

Okay, I'll give that api another go to see where I get. Thank you!

thheller07:06:13

but I really don't have a clue what you are doing still 😛

bbss07:06:42

I'm providing a nice way to use some JS libraries from CLJ basically

thheller07:06:20

I don't understand what that means ... why would you ever use a JS library from CLJ?

bbss07:06:37

because you want to visualize some data you have in clj

thheller07:06:39

the http://deck.gl is webgl visualization. how do you use that from CLJ?

thheller07:06:05

I guess the part I don't get is why you are trying to compile on the consumer side? that gets soooo complicated soo quickly

thheller07:06:27

dealing with arbitrary npm install conflicts and so on

bbss07:06:41

http://deck.gl uses layers, I generated macros that wrap them and visualize them

bbss07:06:19

Sure it's another layer of indirection

bbss07:06:26

I'm using first bootstrap, and now sci to compile functions in clj. It's complicated, but seems to work fairly well so far.

thheller07:06:45

I guess I'm confused by the whole plugin thing which CLJS is completely terrible at

thheller07:06:13

which is probably why you are compiling on the consumer side in the first place?

thheller07:06:06

let me make a different suggestion maybe

thheller07:06:18

it sounds like you are writing the plugin anyways?

thheller07:06:34

and you interact with that plugin over websocket provided by the base app

thheller07:06:15

why not compile the "base-app" and provide that as part of the library (the compiled variant)

thheller07:06:40

then on the consumer side you just need a webserver and serve static JS? no need to shadow-cljs to run at all?

thheller07:06:22

if you want you can use :modules to split everything

bbss07:06:13

yes, that's what I'm doing now, but I am combining multiple bundles which seems problematic

thheller07:06:33

I never said compiled multiple bundles

thheller07:06:41

that is a definite no-no.

thheller07:06:56

I mean the base-app distribution contains compiled code for all plugins ...

thheller07:06:05

yes I know that is less extensible

thheller07:06:42

but plugins isn't something CLJS does well in any kind of way unfortunately

thheller07:06:08

and giving up on all :optimizations is also terrible

bbss07:06:20

Yeah I am aware of no optimizations and it being hacky

bbss07:06:10

I dynamically resolve symbols from from the window, and the main blocker now is that react hooks don't seem to work if I include two plugins that use react.

bbss07:06:29

my assumption is because there are multiple reacts required (eventhough same version)

bbss07:06:23

that's why I was hoping that compiling it consumer side would solve those issues

thheller07:06:29

yes combining multiple builds on the same page is a recipe for disaster

bbss07:06:28

sidenote: I think it's interesting you wrote your own "cljs bootstrap" recently. I'm fairly happy with sci, but it is kind of restrictive, needing to include symbols, explicitly allowing certain usage of DOM stuff, and erroring when functions get called with variadic arguments.

thheller07:06:05

I did no such thing 😛

thheller07:06:18

well I guess kind of but it only looks like that

bbss07:06:48

you mentioned something along those lines and maybe expanding upon it later, looking forward to reading more 🙂

thheller07:06:55

sci works without a running shadow-cljs watch. my stuff doesn't 🙂

bbss07:06:28

I'm mostly writing this as an extension of a clojure programmers toolkit in mind, not necessarily web-app proof.

bbss07:06:53

So running shadow-cljs in the background and not doing advanced compilation is not an issue.

thheller07:06:35

well but what happens if they already use shadow-cljs? two instances is not a great idea and its not designed to work that way.

borkdude07:06:05

@bbss > erroring when functions get called with variadic arguments that should not happen. btw, you can access most DOM stuff with {:classes {:allow :all 'js goog/global}} maybe

borkdude07:06:26

please post a bug report about the variadic stuff

bbss07:06:50

Thanks @borkdude will give that a try. It was able to side-step the issue for now by declaring [.. & args] for the calls to not error.

borkdude07:06:26

@bbss Do you mean that sci errors on function calls that would also error on the JVM, but not in CLJS?

borkdude07:06:52

like: (apply inc [1 2 3])

bbss07:06:07

Yes, I looked into the codebase for a while to try and fix it but didn't really figure it out at the time.

borkdude07:06:37

I don't see how one would like to turn that off honestly 😉

borkdude07:06:20

feel free to discuss any other sci issues in #babashka (sorry for the off topic-ness here)

bbss07:06:29

Okay, bringing it there.

bbss07:06:43

@thheller two instances wouldn't be good, agreed. Having all this plugin stuff play nicely with shadow-cljs is something I want to consider.

thheller07:06:03

well I think you could create 2 new targets

thheller07:06:07

one for the main app

thheller07:06:15

and one for the plugins

thheller07:06:32

but I don't even know how you'd deal with things using different versions

thheller07:06:45

and how you handle plugins sharing dependencies and so on

thheller07:06:53

so compiling on the consumer side may be your best option

bbss08:06:08

alright, giving that a go. Thanks!

superstructor10:06:56

@thheller I just raised an issue for a possible race condition in shadow.cljs.bootstrap.browser/init for bootstrapped environments. Please ping me here or on GitHub if you need any further info or help as we have quite comprehensive tests. Thanks 🙂

thheller12:06:16

@superstructor please setup a reproducible example if you want me to look into this

superstructor12:06:44

Ok will look into this tomorrow :thumbsup:

kenny15:06:49

I'm getting an error in a production shadow-cljs build. It occurs only some of the time but I don't think that actually has to do with the issue. The error message is "ReferenceError: Highcharts is not defined". In Chrome I can click the line number in the error message to take be to the minimized JS. Chrome also has a handy formatter that will pretty print the minimized code (this feature is extremely cool btw. It even goes back and updates the line numbers in the error to point to the pretty printed code!) The line number it takes me to has this code:

d: Highcharts.SVGRenderer.prototype.symbols.arc(g, m, this.center[2] / 2, 0, {
Typing Highcharts in the browser console also leads to a "ReferenceError: Highcharts is not defined". It would appear Highcharts is expecting the Highcharts object to be globally defined but it is likely not due to the advanced build. Any idea what the correct solution to this would be?

kenny15:06:58

I could add a top-level (set! (.-Highcharts js/window) highcharts) which may fix the issue but that doesn't seem like the right solution.

kenny15:06:46

Highcharts is used in our app by including "highcharts": "8.1.2" in package.json and in a :require like this ["highcharts" :as highcharts].

kenny16:06:41

Yep that was it. For those interested or who may hit this as well.. Rolling back to 8.1.0 appears to fix it 🙂

tony.kay17:06:00

I’m trying to use an npm module that requires css. My understanding was that shadow just ignores css requires (according to this blog post https://code.thheller.com/blog/shadow-cljs/2018/06/15/why-not-webpack.html), but I’m getting this error:

Failed to inspect file
  /Users/tonykay/fulcrologic/ucv/node_modules/react-calendar/dist/Calendar.css
which is coming from this statement in the react-date-picker library require("react-calendar/dist/Calendar.css");

thheller19:06:56

I changed the default to throw instead of ignore. set :js-options {:ignore-asset-requires true} to get the old behavior back

thheller19:06:03

guess I forgot to document that somewhere

tony.kay20:06:15

ah, that explains it

thheller21:06:52

fun thing is that previously it just always ignored .css requires

thheller21:06:16

but there are actual packages that have require("./some.css") that actually is supposed to load a some.css.js file ... fun times ...

tony.kay17:06:59

using 2.10.12 of shadow-cljs

tony.kay18:06:19

rolling back to 2.8.100 (as a random choice) works

tony.kay18:06:32

perhaps “works” is too strong a word. It doesn’t complain, but I guess it also ends up importing nothing. I think this lib just isn’t usable…nvm.

lread19:06:02

Hello @thheller! As part of my checklist to test out rewrite-cljc before release, I’m verifying against various projects. One of these projects uses Shadow CLJS. It taught me that rewrite-cljc does not currently compile under Shadow CLJS. Rewrite-cljc has an internal cljs version of potemkin import-vars which, by its nature, looks at analyzer data. I dug in and noticed that Shadow CLJS analyzer data is a wee bit different than ClojureScript analyzer data. The part that interests me is that Shadow CLJS includes macros only under :macros and ClojureScript includes them under both :defs and :macros. I don’t know if this is an intentional choice by Shadow CLJS, and I expect I can adapt, but thought I should letcha know. Here’s a repro of what I found: https://github.com/lread/repro-shadow-cljs-analyzer-macro-diff

lread19:06:19

And… I am by no means an expert here, so I may very well be doing something incorrectly or inappropriately!

thheller19:06:24

@lee IMHO its a bug that CLJS includes macros from CLJS files. they can never be used and shouldn't exist in that ns as functions. leads to weird and strange behavior.

thheller19:06:30

or maybe I'm misunderstanding something? basically shadow-cljs ignored defmacro in CLJS files. that is all.

lread19:06:17

Thanks for the reply @thheller! Ya, I really don’t know what is correct. My cljs import-vars only currently updates :defs and does not touch :macros and import-vars on macros works. I’ll experiment.

thheller19:06:38

well your import-vars should likely ignore the macro defs since they are unusable anyways

thheller19:06:49

no use in importing them to another ns, still useless there 😛

lread19:06:03

ah… interesting… thanks for the tip!

neilyio20:06:16

I've been wondering... with a "hot-reload" setup like shadow-cljs, is there any reason why I would ever want to "evaluate" my ClojureScript code through CIDER in Emacs? As in using cider-eval-defun-at-point after changing some code? My understanding is that shadow-cljs is just watching for changes to the saved file, and evaluating code in the CIDER REPL isn't so useful.

magra19:06:23

Hi, in Cider I find the

cider-eval
which default bindings
C-x C-e
very userful. I have complex fulcro components, which are react-components. With cider eval I can evaluate any part of bigger structures. Like in
(let [a (my-fun (+ c b))]
  do-stuff)
I can put the cursor between the two closing parens of b)) and check whether (+ a b) is what I think it is. Or behind be to check just whether a is what I think it is. If c or b is not defined because they are arguments of the function I can have a comment in the file which binds values for debugging like so:
(comment
  (def a 4)
)
This is invaluable for me when chasing bugs. Of course I often just insert (str a) into the ui to do a sort of println debugging, too, but the ui often stops rendering when react gets bad data.

thheller20:06:31

yeah I use the CLJS much less than CLJ because of hot-reload

neilyio20:06:07

I'm sure the answer will seem obvious... but as a newcomer I don't have a great conceptual model of how the whole system works. I don't really get the relationships between the ClojureScript that is getting compiled, evaluation in CIDER nREPL, shadow-cljs server, shadow-cljs watch app, etc.

neilyio20:06:32

@thheller could you elaborate on that? I don't understand.

thheller20:06:48

read the user guide?

neilyio20:06:13

Sorry, I meant your last statement.

neilyio20:06:30

I realize that I have some studying to do to build my mental model.

thheller20:06:32

in CLJ I use the REPL for basically everything all the time

thheller20:06:39

in CLJS I barely ever use it

neilyio20:06:02

Got it, glad to hear I'm not missing something then.

neilyio20:06:25

Thanks for the tip, and for shadow-cljs. I wouldn't have made it this far in ClojureScript without it.

👍 12
sova-soars-the-sora21:06:49

Hi, i'm trying to make a .js build for production.

sova-soars-the-sora21:06:07

But I get some funky errors on calls...

sova-soars-the-sora21:06:12

when on the server online

sova-soars-the-sora21:06:39

MBP:rolo-client janell$ npx shadow-cljs release frontend --debug
------------------------------------------------------------------------------
shadow-cljs - config: /Users/ja/nos.lv/rolo/rolo-client/shadow-cljs.edn
[:frontend] Compiling ...
Warning: Nashorn engine is planned to be removed from a future JDK release
------ WARNING #1 -  -----------------------------------------------------------
 Resource: com/cognitect/transit.js:649:8
 variable module is undeclared
------------------------------------

thheller21:06:30

thats not an error thats a warning. you can ignore that one

sova-soars-the-sora21:06:17

in the clientside when i run it i get some red... pardon the redness

sova-soars-the-sora21:06:54

kinda hard to diagnose but i'm on it ^.^

thheller21:06:08

make sure thats on :auto

sova-soars-the-sora21:06:40

learning in progress pls wait

sova-soars-the-sora21:06:04

no dice yet but i'll keep learning about the options

sova-soars-the-sora21:06:14

gonna try with optimizations simple

sova-soars-the-sora21:06:20

😄 😄 😄 😄 😄 😄 😄

sova-soars-the-sora21:06:27

we are live ladies and gentlemen

lread22:06:04

@thheller thanks again for your help on the analyzer differences. I dug a little more. My problem arose from the fact that Shadow CLJS and ClojureScript return different data for resolve. Details are here if you are curious: https://github.com/lread/repro-shadow-cljs-analyzer-macro-diff#resolve-macro-differences