Fork me on GitHub
#shadow-cljs
<
2022-03-09
>
Christopher Genovese03:03:56

I have a clojurescript library using shadow-cljs with the :node-library target that I would like to use both within node/commonJS and from ES6/import style js code (e.g., react). I'm producing a release js file with shadow-cljs using :advanced optimizations. While I'm clear on how to load js code of different types into clojurescript, I'm less clear from the users guide what if anything is required to go the other way. Is it usable as is with both commonJS and ES6 imports? Or is a further transpiling step needed? And if so, what is the best practice for doing that transformation? Thanks

thheller05:03:03

@genovese that entirely depends on what the JS side is using to build. both commonjs and es6 are fine usually with webpack and don't make much of a difference either way. note though that :node-library is meant to run in node as the name implies. so if this is a library intended to run in the browser :target :esm might be better

Christopher Genovese05:03:15

I'd like to use it in a create-react-app app, which uses webpack, and I'm also using the library in a node application, and in that situation with straight js code, webpack seems to allow both uses without much trouble. It makes sense to use two different builds for these purposes. I've had some trouble with the esm build for this, but I'll give it another go before troubling you further. Thanks for your help.

thheller06:03:41

:npm-module is another option

thheller06:03:09

:node-library is fine too as long as you don't use node specific things too much

thheller06:03:33

:esm is probably the trickiest of the bunch, so maybe avoid that one

Christopher Genovese06:03:37

I use no node-specific things at all. I do use a few of the es2018 regexp features.

Christopher Genovese06:03:48

Yes, esm hangs for me when I try to import it in react.

Christopher Genovese06:03:07

I set :output-feature-set to :es2018 which might be an issue?

Christopher Genovese06:03:29

Yes, just hangs on Starting development server... seemingly forever

thheller06:03:32

for target esm you need to set :js-options {:js-provider :import}

thheller06:03:45

otherwise it'll bundle react and webpack will again

thheller06:03:03

what is Starting development server? thats not a shadow-cljs message

Christopher Genovese06:03:11

Ah, thanks, I missed that. The library does not use react.

Christopher Genovese06:03:18

I know. That's when I import it in to CRA

Christopher Genovese06:03:24

The library is purely computationoal.

Christopher Genovese06:03:36

I just want to use it in teh react app

Christopher Genovese06:03:12

(I'm doing the CRA in development mode at the moment which is why that message.)

Christopher Genovese06:03:21

The library works fine in node.

thheller06:03:23

hmm yeah dunno why that would hang

thheller06:03:53

might just be taking a long time. it is a known issue that webpack can take its time processing cljs output + source maps

thheller06:03:07

although it should eventually finish

Christopher Genovese06:03:06

OK, I'll wait longer then. The only message I get is (node:33893) [DEP_WEBPACK_DEV_SERVER_ON_AFTER_SETUP_MIDDLEWARE] DeprecationWarning: 'onAfterSetupMiddleware' option is deprecated. Please use the 'setupMiddlewares' option. when I do npm start in the CRA directory. If this doesn't work, do you have any other suggestions? Thanks again!

thheller06:03:38

if :esm doesn't work then don't use :esm 😉

thheller06:03:07

:npm-module was meant for node/webpack integration, so depending on what you need that may fit best

Christopher Genovese06:03:08

🙂 I suppose I can use :umd and attach it to the window object, but that's less than ideal. :node-library with conversion is not working. I can try :node-module I suppose. If :esm doesn't work...my list of options grows thin. I had guessed that others have used cljs libraries in a js/react codebase...right?

Christopher Genovese06:03:23

OK. The docs seem to warn away from that so I discounted it a bit. For instance, I really want to get advanced optimization... But I'll try

thheller06:03:34

advanced works fine, just need to remember to ^:export what the JS stuff wants to access

thheller06:03:36

in :node-library this is done via build config. in :npm-module that is done via metadata in the namespaces

Christopher Genovese06:03:18

Right, with :export metadata. That should be fine.

Christopher Genovese06:03:47

With :npm-module, does the :entries config require all namespaces to be compiled or only the top-level (export-containing) namespaces?

thheller06:03:00

should contain all namespaces that you want the JS code to be able to access *directly*

thheller06:03:15

so if thats just one then just that one. eg. the export containing one

Christopher Genovese06:03:11

Great, that's what I tried. Thanks. Just to make sure I'm clear: I put the files from the :npm-module build into a`local` directory within the react app project and did import { foo } from './local/main.namespace.js'; where foo is the name of one of several exported symbols. Does that seem right? Webpack is taking a go at it. It's been about 10 minutes so far and it's still working.

thheller06:03:48

hmm yeah thats right but it should definitely not take that long

thheller06:03:12

stick a .babelrc into the local dir

thheller06:03:26

with just

{
    "ignore": ["*.js"]
}

Christopher Genovese06:03:34

I was afraid of that. Ok, great idea!

Christopher Genovese07:03:33

Sadly, it seems to be doing the same thing. I'll give it a while longer but I am at a loss. I think I will try making a trivial shadow-cljs project and see that I can get that to import; maybe that will reveal something?? I'd welcome any ideas you have. And in any case, as always, I really appreciate your help and time on this!

thheller07:03:08

I don't know about the current state of CRA. there might be other ways to tell it to ignore processing certain files

thheller07:03:18

it used to work via .babelrc but that may have changed

Christopher Genovese07:03:19

Good point. I'll check into that.

Christopher Genovese14:03:25

@thheller OK, I think I got it working by doing the :esm target for the library, creating a "fake" npm project with the shadow-cljs output file as the index.js, and pointing the "browser" tag in package.json to that file. I then did a local install of the fake npm project. And apparent success.... phew. (I was pretty worried there.) I'm assuming that would then work if packaged to npm as well. Would it mess up shadow-cljs at all if I put an analogous package.json entry (i.e., using the "browser" tag) in my shadow-cljs project? That would make it pretty straightforward to use this way. Thanks again

hoppy16:03:16

Noticing some sort of friction between cider and shadow-cljs using a node repl. I noticed this issue start a couple of weeks back, but was busy and had to keep moving (aka switched back to calva for a while). Shadow nodejs project. It can be pulled from: [email protected]:/Gnurdle/aoc2019.git using 2.17.5 of shadow cider version is 1.3.0-snapshot (few days old now?) spacemacs - develop pulled last night, nothing bizzare in config so, pretty current/mainline stuff. This is from a jack-in-cljs, selecting node repl: [nREPL] Starting server via /home/chopper/.nvm/versions/node/v14.17.6/bin/npx shadow-cljs -d nrepl/nrepl:0.9.0 -d cider/cider-nrepl:0.28.3 -d cider/piggieback:0.5.2 server [nREPL] server started on 40693 Get this traceback: 1. Unhandled java.lang.AssertionError Assert failed: (keyword? repl-env) nrepl.clj: 30 shadow.cljs.devtools.server.nrepl/shadow-cljs-repl nrepl.clj: 30 shadow.cljs.devtools.server.nrepl/shadow-cljs-repl RestFn.java: 410 clojure.lang.RestFn/invoke REPL: 1 shadow.user/eval28143 REPL: 1 shadow.user/eval28143 Compiler.java: 7181 clojure.lang.Compiler/eval Compiler.java: 7171 clojure.lang.Compiler/eval Compiler.java: 7136 clojure.lang.Compiler/eval core.clj: 3202 clojure.core/eval core.clj: 3198 clojure.core/eval interruptible_eval.clj: 87 nrepl.middleware.interruptible-eval/evaluate/fn/fn AFn.java: 152 clojure.lang.AFn/applyToHelper AFn.java: 144 clojure.lang.AFn/applyTo core.clj: 667 clojure.core/apply core.clj: 1977 clojure.core/with-bindings* core.clj: 1977 clojure.core/with-bindings* RestFn.java: 425 clojure.lang.RestFn/invoke interruptible_eval.clj: 87 nrepl.middleware.interruptible-eval/evaluate/fn main.clj: 437 clojure.main/repl/read-eval-print/fn main.clj: 437 clojure.main/repl/read-eval-print main.clj: 458 clojure.main/repl/fn main.clj: 458 clojure.main/repl main.clj: 368 clojure.main/repl RestFn.java: 1523 clojure.lang.RestFn/invoke interruptible_eval.clj: 84 nrepl.middleware.interruptible-eval/evaluate interruptible_eval.clj: 56 nrepl.middleware.interruptible-eval/evaluate interruptible_eval.clj: 152 nrepl.middleware.interruptible-eval/interruptible-eval/fn/fn AFn.java: 22 clojure.lang.AFn/run session.clj: 218 nrepl.middleware.session/session-exec/main-loop/fn session.clj: 217 nrepl.middleware.session/session-exec/main-loop AFn.java: 22 clojure.lang.AFn/run Thread.java: 829 java.lang.Thread/run ===== repl seems to be connected, but can't do much. This project works flawlessly with calva, so maybe not a shadow issue. Happy to help debugging, if I knew what to do first...

Christopher Genovese17:03:25

Did cider display the ClojureScript REPL init form? And if so, what was it?

hoppy18:03:21

where would I find that?

Christopher Genovese18:03:44

If it got you to the repl, it usually prints it as part of the introductory banner text, labeld as ClojureScript REPL init (at least in 1.2)

thheller18:03:20

that error happens when you try to initialize the CLJS REPL incorrectly. I don't know what it is sending but maybe this helps https://shadow-cljs.github.io/docs/UsersGuide.html#cider

thheller18:03:28

no clue if that is still accurate. don't use emacs myself

Christopher Genovese19:03:41

The problem appears to be happening in the pre-condition assertion of shadow-cljs-repl and this gets its value directly from cider's init form. Cider gets a list of builds, converts to keywords, and passes that directly to shadow/nrep-select. I'm thinking that maybe in 1.3 (or for some other reason like local context), the build is not getting set properly when the init form in CIDER is created. Just a hypothesis, but there's not much other action between that and the assertion failure.

thheller19:03:56

I suspect its just trying to use the default regular cljs repl init form. which doesn't work with shadow-cljs. a keyword is expected but its not given.

Christopher Genovese19:03:40

Agreed that the regular default makes sense. But CIDER normalizes that build string to turn it into a keyword if it's not already, so that should be ok. Whether the new version changes something (intentionally or not) remains to be seen

thheller19:03:59

I doubt very much that its just a build string conversion issue

thheller19:03:22

it likely sends something like (cljs.repl.node/repl-env) or whatever the exact form is to init a default CLJS repl

thheller19:03:42

but regardless. it is a config setting you must change. if you do not the default will not work.

Christopher Genovese19:03:47

I asked him to see the build string to check what it passes. I'm running CIDER 1.2 and am using that to compare with what he is seeing and

thheller19:03:49

I guess that error message could be improved though https://github.com/thheller/shadow-cljs/issues/997

Christopher Genovese19:03:11

it looks like that repl-env does not change from the init form issued by cider to when it hits shadow-cljs-repl. I could be mistaken and I juust took a quick look in response to @U19EVCEBV's query, but that's how it appears. I think this is more likely a CIDER issue. Maybe config if the cider build variable is set strangely...

hoppy20:03:00

(--> id "1" op "clone" time-stamp "2022-03-09 14:22:43.411305273" ) (<-- id "1" session "f0e132e6-371a-4e83-b3c6-4ab586343a01" time-stamp "2022-03-09 14:22:43.419432571" new-session "9d6616e6-135f-4081-8795-ec3021192007" status ("done") ) (--> id "2" op "clone" time-stamp "2022-03-09 14:22:43.443379704" ) (<-- id "2" session "70ab6175-207a-4c2b-b6ca-06eee7a483e1" time-stamp "2022-03-09 14:22:43.445479986" new-session "b6c2b018-8bbb-467f-82e3-d2b0499ca16e" status ("done") ) (--> id "3" op "describe" session "9d6616e6-135f-4081-8795-ec3021192007" time-stamp "2022-03-09 14:22:43.463869510" ) (<-- id "3" session "9d6616e6-135f-4081-8795-ec3021192007" time-stamp "2022-03-09 14:22:43.495298617" aux (dict ...) ops (dict ...) status ("done") versions (dict ...) ) (--> id "4" op "eval" session "9d6616e6-135f-4081-8795-ec3021192007" time-stamp "2022-03-09 14:22:43.518527675" code "(clojure.core/apply clojure.core/require clojure.main/repl-requires)" column 1 file "cider-repl cms-aero/cms-wave:localhost:36541(pending-cljs)" inhibit-cider-middleware "true" line 47 nrepl.middleware.print/buffer-size 4096 nrepl.middleware.print/options (dict ...) nrepl.middleware.print/print "cider.nrepl.pprint/pprint" nrepl.middleware.print/quota 1048576 nrepl.middleware.print/stream? "1" ) (<-- id "4" session "9d6616e6-135f-4081-8795-ec3021192007" time-stamp "2022-03-09 14:22:43.544699094" value "nil" ) (<-- id "4" session "9d6616e6-135f-4081-8795-ec3021192007" time-stamp "2022-03-09 14:22:43.545315091" ns "shadow.user" ) (<-- id "4" session "9d6616e6-135f-4081-8795-ec3021192007" time-stamp "2022-03-09 14:22:43.545483854" status ("done") ) (--> id "5" op "out-subscribe" session "9d6616e6-135f-4081-8795-ec3021192007" time-stamp "2022-03-09 14:22:43.545928236" ) (--> id "6" op "init-debugger" session "9d6616e6-135f-4081-8795-ec3021192007" time-stamp "2022-03-09 14:22:43.546291705" nrepl.middleware.print/buffer-size 4096 nrepl.middleware.print/options (dict ...) nrepl.middleware.print/print "cider.nrepl.pprint/pprint" nrepl.middleware.print/quota 1048576 nrepl.middleware.print/stream? "1" ) (--> id "7" op "eval" session "b6c2b018-8bbb-467f-82e3-d2b0499ca16e" time-stamp "2022-03-09 14:22:43.546956467" code "(require 'cljs.core)" ) (<-- id "5" session "9d6616e6-135f-4081-8795-ec3021192007" time-stamp "2022-03-09 14:22:43.608404490" out-subscribe "9d6616e6-135f-4081-8795-ec3021192007" status ("done") ) (<-- id "7" session "b6c2b018-8bbb-467f-82e3-d2b0499ca16e" time-stamp "2022-03-09 14:22:44.789805407" ns "shadow.user" value "nil" ) (<-- id "7" session "b6c2b018-8bbb-467f-82e3-d2b0499ca16e" time-stamp "2022-03-09 14:22:44.790105861" status ("done") ) (--> id "8" op "eval" session "b6c2b018-8bbb-467f-82e3-d2b0499ca16e" time-stamp "2022-03-09 14:22:44.805745358" code "(require 'cider.piggieback)" ) (<-- id "7" session "b6c2b018-8bbb-467f-82e3-d2b0499ca16e" time-stamp "2022-03-09 14:22:44.826579764" changed-namespaces (dict ...) repl-type "clj" status ("state") ) (<-- id "8" session "b6c2b018-8bbb-467f-82e3-d2b0499ca16e" time-stamp "2022-03-09 14:22:44.826837261" ns "shadow.user" value "nil" ) (<-- id "8" session "b6c2b018-8bbb-467f-82e3-d2b0499ca16e" time-stamp "2022-03-09 14:22:44.826950218" status ("done") ) (<-- id "8" session "b6c2b018-8bbb-467f-82e3-d2b0499ca16e" time-stamp "2022-03-09 14:22:44.827251572" changed-namespaces (dict) repl-type "clj" status ("state") ) (--> id "9" op "eval" session "9d6616e6-135f-4081-8795-ec3021192007" time-stamp "2022-03-09 14:22:44.837460053" code "(do (require 'cljs.repl.node) (cider.piggieback/cljs-repl (cljs.repl.node/repl-env)))" ns "shadow.user" ) (<-- id "9" session "9d6616e6-135f-4081-8795-ec3021192007" time-stamp "2022-03-09 14:22:44.877871371" err "Execution error (AssertionError) at shadow.cljs.devtools.server.nrepl/shadow-cljs-repl (nrepl.clj:30). Assert failed: (keyword? repl-env) "

hoppy20:03:26

the nrepl log from cider (sorry slack wouldn't take a snippet in a thread for some reason)

hoppy20:03:57

not sure if it helps, but here is the nrepl log from cider

hoppy20:03:19

dunno if it helps, but this is the nrepl log from cider

Christopher Genovese21:03:24

Hmm... Does the repl start and show you the welcome banner or message? If so, I'd like to see the last non-trivial comment line. Do you have any non-default cider config set? I tried to trace backward from the one spot that can be causing the error, and it would be good to know what that repl-env value is. We could see the input in the banner message. Now as @thheller says, it could be something else entirely... If you could try it with cider 1.2.x, it would distinguish some possibilities. I'd also suggest putting this on the cider slack channel as it looks more a CIDER-related issue than a shadow-cljs one. (It's often hard to separate those, though; I've had that experience too.)

hoppy22:03:02

I don't believe it got around to making a repl buffer to display anything in

hoppy22:03:54

will bring this up in cider though, since calva is working in this situation

hoppy01:03:39

they busted me being tricked by a bitey-dog. I was selecting 'node-repl' but what I needed to be doing was first selecting shadow and then node-repl. The ergonomics of this a bit distressing IMHO & 2c worth.

Christopher Genovese04:03:06

Ah, that can happen. Glad you figured it out. In case you weren't aware of it, you can set dir-local vars in a project so you don't have to answer that every time. Good luck!

thheller05:03:31

> code "(do (require 'cljs.repl.node) (cider.piggieback/cljs-repl (cljs.repl.node/repl-env)))"

thheller05:03:01

that is the part that is incorrect. as I said this is trying to initialize a regular node cljs REPL, which is not what shadow-cljs expects

thheller05:03:05

it should be something like (do (require 'shadow.cljs.devtools.api) (shadow.cljs.devtools.api/repl :your-build-id))

hoppy22:03:54
replied to a thread:Noticing some sort of friction between cider and shadow-cljs using a node repl. I noticed this issue start a couple of weeks back, but was busy and had to keep moving (aka switched back to calva for a while). Shadow nodejs project. It can be pulled from: [email protected]:/Gnurdle/aoc2019.git using 2.17.5 of shadow cider version is 1.3.0-snapshot (few days old now?) spacemacs - develop pulled last night, nothing bizzare in config so, pretty current/mainline stuff. This is from a jack-in-cljs, selecting node repl: [nREPL] Starting server via /home/chopper/.nvm/versions/node/v14.17.6/bin/npx shadow-cljs -d nrepl/nrepl:0.9.0 -d cider/cider-nrepl:0.28.3 -d cider/piggieback:0.5.2 server [nREPL] server started on 40693 Get this traceback: 1. Unhandled java.lang.AssertionError Assert failed: (keyword? repl-env) nrepl.clj: 30 shadow.cljs.devtools.server.nrepl/shadow-cljs-repl nrepl.clj: 30 shadow.cljs.devtools.server.nrepl/shadow-cljs-repl RestFn.java: 410 clojure.lang.RestFn/invoke REPL: 1 shadow.user/eval28143 REPL: 1 shadow.user/eval28143 Compiler.java: 7181 clojure.lang.Compiler/eval Compiler.java: 7171 clojure.lang.Compiler/eval Compiler.java: 7136 clojure.lang.Compiler/eval core.clj: 3202 clojure.core/eval core.clj: 3198 clojure.core/eval interruptible_eval.clj: 87 nrepl.middleware.interruptible-eval/evaluate/fn/fn AFn.java: 152 clojure.lang.AFn/applyToHelper AFn.java: 144 clojure.lang.AFn/applyTo core.clj: 667 clojure.core/apply core.clj: 1977 clojure.core/with-bindings* core.clj: 1977 clojure.core/with-bindings* RestFn.java: 425 clojure.lang.RestFn/invoke interruptible_eval.clj: 87 nrepl.middleware.interruptible-eval/evaluate/fn main.clj: 437 clojure.main/repl/read-eval-print/fn main.clj: 437 clojure.main/repl/read-eval-print main.clj: 458 clojure.main/repl/fn main.clj: 458 clojure.main/repl main.clj: 368 clojure.main/repl RestFn.java: 1523 clojure.lang.RestFn/invoke interruptible_eval.clj: 84 nrepl.middleware.interruptible-eval/evaluate interruptible_eval.clj: 56 nrepl.middleware.interruptible-eval/evaluate interruptible_eval.clj: 152 nrepl.middleware.interruptible-eval/interruptible-eval/fn/fn AFn.java: 22 clojure.lang.AFn/run session.clj: 218 nrepl.middleware.session/session-exec/main-loop/fn session.clj: 217 nrepl.middleware.session/session-exec/main-loop AFn.java: 22 clojure.lang.AFn/run Thread.java: 829 java.lang.Thread/run ===== repl seems to be connected, but can't do much. This project works flawlessly with calva, so maybe not a shadow issue. Happy to help debugging, if I knew what to do first...

will bring this up in cider though, since calva is working in this situation