This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-08-14
Channels
- # aleph (3)
- # announcements (16)
- # aws (6)
- # babashka (10)
- # beginners (28)
- # cider (1)
- # clj-kondo (14)
- # cljdoc (2)
- # cljs-dev (27)
- # cljsrn (7)
- # clojure (78)
- # clojure-europe (2)
- # clojurescript (14)
- # conjure (6)
- # core-async (2)
- # fulcro (5)
- # helix (7)
- # jobs (1)
- # lgbtq (1)
- # malli (12)
- # missionary (1)
- # nbb (10)
- # pathom (1)
- # portal (12)
- # protojure (1)
- # re-frame (41)
- # react (2)
- # reitit (1)
- # reveal (1)
- # shadow-cljs (72)
- # sql (11)
- # tools-deps (8)
- # vim (1)
- # xtdb (4)
In this talk, David Nolen demos using Krell to have two REPLs, running on separate devices, with separate state, using the same code base. https://youtu.be/3HxVMGaiZbc?t=2054 is something similar supported by shadow-cljs?
@pez what do you mean specifically? this is pretty much the default of how shadow-cljs works? only that you only need one process and not 2 separate ones?
you can connect as many devices as you want and/or run as many builds in parallel as you want (or your machine can tolerate)
yeah thats a bit manual at the moment since no editor (wink, wink) has added support for manual selection yet
quick overview you can check is http://localhost:9630/runtimes
and when you can pick when when you start the repl via (shadow.cljs.devtools.api/repl :the-build-id {:runtime-id 123})
there is also (shadow.cljs.devtools.api/repl-runtimes :the-build-id)
to get the data from the REPL without the UI
[{:since #inst"2021-08-14T06:20:06.623-00:00",
:proc-id "3133b4c9-82b9-4144-a0dc-68e8daddfdae",
:connection-info {:remote true, :websocket true},
:client-id 4,
:user-agent "Chrome 537.36 [Win32]",
:type :runtime,
:lang :cljs,
:build-id :browser,
:host :browser,
:dom true}
{:since #inst"2021-08-14T06:20:07.205-00:00",
:proc-id "3133b4c9-82b9-4144-a0dc-68e8daddfdae",
:connection-info {:remote true, :websocket true},
:client-id 5,
:user-agent "Chrome 537.36 [Win32]",
:type :runtime,
:lang :cljs,
:build-id :browser,
:host :browser-worker,
:dom false}]
from my test build that also has a webworker connected (which you can also REPL into)
I get a lot of #X ready!
messages, with increasing id numbers. (And the id:s are bumped accordingly.) I’m using the :react-native
target and have started a web and an iOS client. Looks like so after a while:
= web
#5 ready!
#7 ready!
#8 ready!
#10 ready!
#12 ready!
#14 ready!
#16 ready!
#17 ready!
#20 ready!
= iOS Simulator
#4 ready!
#6 ready!
#9 ready!
#11 ready!
#13 ready!
#15 ready!
What could be part of this is that I started the apps, then closed the lid on my laptop and made some breakfast to the family. Now opening the laptop again there is this. I think I just managed to reproduce the behaviour when closing and re-opening, but only in the web app. The runtime info looks like so:
[{:connection-info
{:remote true,
:websocket
true},
:since
#inst "2021-08-14T08:45:55.502-00:00",
:host
:react-native,
:type :runtime,
:lang :cljs,
:build-id :app,
:proc-id
"165ac90e-ac63-4516-9453-3c49e4f85815",
:client-id 15}
{:connection-info
{:remote true,
:websocket
true},
:since
#inst "2021-08-14T08:53:30.446-00:00",
:host
:react-native,
:type :runtime,
:lang :cljs,
:build-id :app,
:proc-id
"165ac90e-ac63-4516-9453-3c49e4f85815",
:client-id 20}]
I can select the repl as per above, and evaluations happen in the right app.the ready message you get when the websocket connects. if that disconnects it'll attempt to reconnect, which gives you a new id
don't know why you'd get that many though. never seen that before. is it constantly reconnecting the websocket or does that actually have that many websockets open?
the only problem I remember was with android and react-native. that didn't disconnect the websocket when reloading the app. don't know if thats still a thing
> is it constantly reconnecting the websocket or does that actually have that many websockets open? Don’t know if this answers it, but if select an old id, I get no complaints, but when evaluating I get this message
The previously used runtime disappeared. Will attempt to pick a new one when available but your state might be gone.
It seems that the :since
doesn’t change. Can I rely on that, as long as the app is not reloaded?
yeah, so the longer backstory to all of this: I built shadow.remote as the default remote mechanism for shadow-cljs. even the UI uses that to do everything it does. All REPLs use it. so ideally any editors would also directly connect to the shadow.remote endpoint. part of shadow.remote is a notification for when a runtime connects or disconnects
the editor would then be supposed to handle that and inform the user in some form of UI or auto select the next one etc
the regular REPL however is stuck in a block Read with no way to ask the user what they want to do
so I had to compromise in picking the next one that arrives. however that logic doesn't apply if you specified one
https://github.com/thheller/shadow-cljs/blob/master/doc/remote.md docs are sparse at the moment
tap>
and the inspect UI runs over shadow.remote, so anything the UI displays you have access to as well
Using this I can solve the old issue with Calva not really knowing when the REPL is available.
It does make shadow-cljs very special from Calva’s POV, but may well be worth it to create a nice UI/Ux.
just as a transport layer I mean. don't know how well that would integrate into your nREPL code though as the message flow is a bit different. usually nrepl doesn't push messages to the client without receiving a request first
I’d love me a shadow.remote over nrepl. Calva has ways to deal with “orphaned” incoming messages, so I should be able to weed out the ones from shadow/remote there.
well the messages you'd get are all marked as such, so "op" "shadow.remote"
or so. haven't really looked into it too much yet
the thing I don't like about nrepl is that there is no explicit connection management. so you don't know when a connection starts or ends from the middleware perspective
As for the android react-native client. It doesn’t disconnect at app reload, as you remembered. It is cleaned away after a few seconds though. Both iOS and web disconnect immediately before reconnecting.
I’m trying to use react-bootstrap with shadow-cljs and I’m requiring like so
(:require ["react-bootstrap" :as bs])
But when I console.log bs
roughly half the keys (component names) have no values
Image: {$$typeof: Symbol(react.forward_ref), defaultProps: {…}, render: ƒ}
InputGroup: {$$typeof: Symbol(react.forward_ref), Text: {…}, render: ƒ, Radio: ƒ, Checkbox: ƒ, …}
ListGroup: {$$typeof: Symbol(react.forward_ref), Item: {…}, render: ƒ}
ListGroupItem: {$$typeof: Symbol(react.forward_ref), defaultProps: {…}, render: ƒ}
Modal: undefined
ModalBody: undefined
ModalDialog: undefined
ModalFooter: undefined
Any idea why Modal
and friends would not get imported?I noticed this map also includes __esModule: true
not sure if that that’s relevant
I see a pattern, the components that are missing are all function components
of what? react?
(js/require "react-bootstrap/Tabs")
does load the correct function component
ditto for (js/require "react-bootstrap")
although that might be something else?
:browser
but it’s an electron app with node integration in the renderer
hmm might be the other problem again. try setting :js-options {:entry-keys ["browser" "main"]}
in your build config
yup that worked!
so getting rid of the default last "module"
fixed it, that’s strange
i see, well thank you so much for the help
with this setting, does that mean I cannot use some npm packages? i.e. do some packages require "module"
?
annoyingly some require that yes but after adding that more people reported problems than before
the weird and wonderful world of npm
well the transition to ESM away from CommonJS is going to bring many hurdles. this is one of them since commonjs<->ESM interop is tricky
I would have expected this to go a little faster but so far it seems rather slow going
yeah i bet
Is there a way to output to the root directory? expo EAS requires the entry point to be a root level index.js file. I can make it work by copying shadows build/index.js
to the root level and then doing a find/replace to fix the paths in the file, so is there a reason why shadow wouldn’t allow you to do this automatically?
@alex395 do this instead https://github.com/thheller/reagent-react-native/blob/master/react-native/index.js. :output-dir "."
might also work but not recommended, no guarantee that shadow-cljs won't overwrite a file that you might need for something. preferable to have its own directory that you can delete at any point
Thanks! I actually tried "."
but it doesn’t generate the correct paths for the js/require
calls, then I pretty much did what you’ve suggested there
:target :esm
might also be an option. been a while since I looked at react-native stuff, see https://clojureverse.org/t/generating-es-modules-browser-deno/6116