This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-04-28
Channels
- # aleph (3)
- # babashka (66)
- # beginners (96)
- # calva (45)
- # clj-kondo (28)
- # clojure (30)
- # clojure-dev (2)
- # clojure-europe (20)
- # clojure-germany (22)
- # clojure-norway (4)
- # clojurescript (176)
- # clojutre (1)
- # cursive (23)
- # datalog (6)
- # datomic (7)
- # docker (3)
- # emacs (3)
- # exercism (4)
- # figwheel-main (5)
- # fulcro (8)
- # gratitude (9)
- # hyperfiddle (8)
- # introduce-yourself (2)
- # jobs (2)
- # malli (4)
- # membrane (3)
- # off-topic (17)
- # polylith (3)
- # portal (2)
- # re-frame (27)
- # reitit (3)
- # releases (1)
- # remote-jobs (1)
- # shadow-cljs (152)
- # spacemacs (8)
- # tools-deps (15)
- # vscode (1)
- # xtdb (24)
@santosx99xx that is a Clojure error. So you are connected to a clojure REPL. you first need to switch to the CLJS REPL from that CLJ REPL. dunno what editor you use https://shadow-cljs.github.io/docs/UsersGuide.html#_editor_integration
I'm using vs code and calva
So I've built a nice little in-browser REPL using cljs_eval
for my app, and I'm trying to add autocompletion to it. Is there a way to get a list of loaded namespaces, either via the standard library (I tried https://cljs.github.io/api/cljs.analyzer.api/all-ns but it doesn't seem to work) or shadow-cljs?
can't really do this on top of cljs-eval
. really need access to the compiler env which is on the clojure side.
There's no way to smuggle in a clojure command from the browser?
I'm okay with finding a hacky approach to this; doesn't need to go through cljs_eval
Maybe there should be? ;)
I don't like nrepl at all so I would be building this kind of thing over shadow.remote
You've been working on some really cool browser-based stuff with the shadow-cljs UI. It seems to me like you could come up with a lot of use-cases for something like that
Haha I can imagine
the UI also uses shadow.remote for everything, everything it uses you also have access to
Cool! Just read the rationale for shadow.remote and I think it sounds great
I don't really care if it's undocumented/alpha
If i wanted to use it to do stuff like this, how would I get started? :)
that would need to call this fn https://github.com/thheller/shadow-cljs/blob/b8466f176b6e8f6bf61cd70fbfbaf4762c581eb1/src/main/shadow/cljs/devtools/client/shared.cljs#L67
init-fn
gets one parameter being the environment, including the runtime and all the dependencies
I mean it gets very involved very quickly but the REPL is implemented on top of all of this
alright
the entire UI inspect and tap thing are also just plugins https://github.com/thheller/shadow-cljs/blob/b8466f176b6e8f6bf61cd70fbfbaf4762c581eb1/src/main/shadow/cljs/devtools/client/shared.cljs#L374-L381
but yeah not documented anything here and the CLJ side is currently not using this plugin mechanism
got it
so if I wanted to add a plugin that (as a first step) lets me list all loaded namespaces, how would I set it up?
from what you wrote earlier I assume it has to deal with clj?
alright
so the clients sends this https://github.com/thheller/shadow-cljs/blob/b8466f176b6e8f6bf61cd70fbfbaf4762c581eb1/src/main/shadow/cljs/devtools/client/shared.cljs#L248 and the worker handles it in the multi-method above
does all the cljs code you linked run in the browser? or is there a cljs part on the backend too?
okay, great
I think this should be enough to get me started
are there any specs or similar that describe the messages being passed around here?
basically you would (defmethod impl/do-relay-msg ::my-auto-complete [worker-state msg] ...)
somewhere in your code on the CLJ side
alright, so my messages can be arbitrary data?
what about e.g. the stuff that gets passed to the add-plugin fns?
any specs for that?
got it
:to
tells it to direct the messages to the worker, which can then answer via the multi-method
the multi-method must return the worker-state
it gets. in the worker-state
there is a :build-state
which has :compiler-env
hey also, do you think it would be possible to use this approach to get require
working from my browser-based repl?
(add-plugin! ::plugin #{}
(fn [{:keys [runtime] :as env}]
(api/add-extension runtime ::auto-complete {})
(shared/call runtime
{:op ::complete-me
:to env/worker-client-id
:foo "bar"}
{::complete-result
(fn [msg]
(js/console.log "result from worker" msg))})
env)
(fn [{:keys [runtime]}]
(api/del-extension runtime ::auto-complete)))
alright, thanks
seems straightforward enough 🙂
(defmethod impl/do-relay-msg ::complete-me
[worker-state {:keys [foo] :as msg}]
(impl/relay-msg worker-state msg
{:op :complete-result
:yo []})
worker-state)
note that you need to add the multi-method implementations before starting the worker
hmm okay
I had some problems with require earlier, but it might just have been an error on my part
I'll take a closer look at it
anyway thanks; looking forward to testing this out 🙂
I develop in calva, and the jack in command of calva with launch shadow with the command like this
npx shadow watch :app
The issue is, whenever I run the vscommand Developer reload window
. And after the new vscode window show up, and then if I perform a jack in, it will say
shadow port already taken
I suspect this might be related to the shadow server mode.
In all, is it possible to tell shadow to quite when vscode quits (to be exact, window reloads) ?Oh, the reason I don't just help you here is that I am short on time. But hopefully in the #calva channel someone else can help.
I don't understand it, but as long as I have :extra-paths ["src/dev"]
, and there's an empty (ns user)
in there, it builds. Otherwise it gives me an exception.
:shadow-cli {:extra-paths ["src/dev" "resources"]
:extra-deps
{thheller/shadow-cljs {:mvn/version "2.16.12"}
binaryage/devtools {:mvn/version "1.0.0"}}
:main-opts ["-m" "shadow.cljs.devtools.cli"]},
$ tree src/dev/
src/dev/
└── user.clj
0 directories, 1 file
$ cat src/dev/user.clj
(ns user)
I don't want dev
on my classpath at all for release, so I shouldn't need it as an :extra-path
.@alex.sheluchin what exception would that be? I assume you just have another user.clj
on some other :paths
. by just adding src/dev
you are effectively overwriting that one
https://clojurians.slack.com/files/UPWHQK562/F03CX51NS8P/untitled.cpp
It's the only user.clj
I have actually.
if you try (enumeration-seq (.getResources (.getContextClassLoader (Thread/currentThread)) "user.clj"))
I assume you mean clj -A:shadow-cli
because that's the name of the alias I have. Nope, it doesn't give me errors.
(#object[java.net.URL 0x2e01e8ae "file:/home/alex/repos/personal-projects/example/src/dev/user.clj"])
If I don't include :extra-paths ["src/dev"]
, that's when I get the above exception.
I am running it from my command line, no editor. When you gave me that snippet to look for user.clj
, I used clj -A:shadow-cli clj-repl
to evaluate it.
might also be related to core.async
in some way. or some AOT classes you have somewhere
I mean your entire setup is full of red flags for me but should still be possible to figure out exactly what is causing your issues
I've been making do with it for local dev, but now that I'm looking at deployment stuff is indeed screaming at me.
Yes, I do have some stuff in my global deps:
{:aliases
{:cider-clj
{:extra-deps {org.clojure/clojure {:mvn/version "1.10.1"}
cider/cider-nrepl {:mvn/version "0.21.1"}}
; fipp {:mvn/version "0.6.23"}}
:main-opts ["-m" "nrepl.cmdline"
"--middleware" "[cider.nrepl/cider-middleware]"]}
:cljs
{:extra-deps {nrepl/nrepl {:mvn/version "0.7.0"}
cider/piggieback {:mvn/version "0.4.1"}}}
; fipp {:mvn/version "0.6.23"}}}
:nREPL
{:extra-deps {nrepl/nrepl {:mvn/version "0.8.1"}}}
:repl/reveal {:extra-deps {vlaaad/reveal {:mvn/version "1.3.270"}
lambdaisland/deep-diff2 {:mvn/version "2.0.108"}}
:ns-default vlaaad.reveal
;; note Fira Code is a ligature font so it's not supported in Reveal, whjch only uses monospaced
:jvm-opts ["-Dvlaaad.reveal.prefs={:theme,:light,:font-family,\"Fira Code\",:font-size,8}"]
:repl-options {:nrepl-middleware [vlaaad.reveal.nrepl/middleware]}
:exec-fn repl}}}
did you at some point experiments with AOT maybe? are there a lot of .class files in your project somewhere?
Not that I am aware of. I can't find
any .class files from my root and I haven't knowingly used any AOT stuff. Should I try just blowing away my .m2 and pulling everything anew?
I have a largely unfounded suspicion this is somehow related to https://github.com/fulcrologic/guardrails, but don't really have any evidence to back up the hunch.
Sorry for the noob troubles being so time consuming here @U05224H0W. Thank you for helping out.
I have no idea how I could have broken anything in the Maven cache. I guess I'll just get in the habit it nuking it when things stop working smoothly.
Huh. Moved some JS files from <script>
s in index.html
inside the compiled bundle, and now I can't build my project on Heroku where there's a restriction on memory.
The stack trace doesn't mention shadow-cljs, it even looks like it's been trimmed for some reason because the entry point doesn't make sense.
{:clojure.main/message
"Execution error (OutOfMemoryError) at java.util.Arrays/copyOf (Arrays.java:3537).\nJava heap space\n",
:clojure.main/triage
{:clojure.error/class java.lang.OutOfMemoryError,
:clojure.error/line 3537,
:clojure.error/cause "Java heap space",
:clojure.error/symbol java.util.Arrays/copyOf,
:clojure.error/source "Arrays.java",
:clojure.error/phase :execution},
:clojure.main/trace
{:via
[{:type java.lang.OutOfMemoryError,
:message "Java heap space",
:at [java.util.Arrays copyOf "Arrays.java" 3537]}],
:trace
[[java.util.Arrays copyOf "Arrays.java" 3537]
[java.lang.AbstractStringBuilder ensureCapacityInternal "AbstractStringBuilder.java" 228]
[java.lang.AbstractStringBuilder append "AbstractStringBuilder.java" 682]
[java.lang.StringBuffer append "StringBuffer.java" 393]
[java.io.StringWriter write "StringWriter.java" 122]
[java.io.PrintWriter write "PrintWriter.java" 541]
[java.io.PrintWriter write "PrintWriter.java" 558]
[java.io.PrintWriter print "PrintWriter.java" 685]
[clojure.data.json$write_string invokeStatic "json.clj" 317]
[clojure.data.json$write_string invoke "json.clj" 290]
[clojure.data.json$fn__262$G__257__269 invoke "json.clj" 286]
[clojure.data.json$write_array invokeStatic "json.clj" 348]
[clojure.data.json$write_array invoke "json.clj" 342]
[clojure.data.json$fn__262$G__257__269 invoke "json.clj" 286]
[clojure.data.json$write_object invokeStatic "json.clj" 335]
[clojure.data.json$write_object invoke "json.clj" 319]
[clojure.data.json$fn__262$G__257__269 invoke "json.clj" 286]
[clojure.data.json$write_object invokeStatic "json.clj" 335]
[clojure.data.json$write_object invoke "json.clj" 319]
[clojure.data.json$fn__262$G__257__269 invoke "json.clj" 286]
[clojure.data.json$write_array invokeStatic "json.clj" 348]
[clojure.data.json$write_array invoke "json.clj" 342]
[clojure.data.json$fn__262$G__257__269 invoke "json.clj" 286]
[clojure.data.json$write_object invokeStatic "json.clj" 335]
[clojure.data.json$write_object invoke "json.clj" 319]
[clojure.data.json$fn__262$G__257__269 invoke "json.clj" 286]
[clojure.data.json$write invokeStatic "json.clj" 475]
[clojure.data.json$write doInvoke "json.clj" 424]
[clojure.lang.RestFn invoke "RestFn.java" 425]
[clojure.lang.AFn applyToHelper "AFn.java" 156]
[clojure.lang.RestFn applyTo "RestFn.java" 132]
[clojure.core$apply invokeStatic "core.clj" 671]],
:cause "Java heap space"}}
There are some places in shadow-cljs where JSON writing could easily be made more memory efficient, like e.g. in this code:
(spit target
(json/write-str sm-index))
But given the stacktrace, it's completely unclear where exactly the right place for an improvement would be...which java version is this using? older JVM versions didn't detect container memory correctly, so they used the actual machine memory as a reference
if you use a newer jvm version that usually sorts itself out too, older require manual settings
fine to leave this in always, shadow-cljs doesn't really need that much memory. the default jvm settings are a bit greedy
Yeah, that would require doubling my client's spending on Heroku because AFAIC you can't get a separate build dyno - it all runs with the same limits and the current RAM limit is 1 GB, which is plenty for the app itself. JDK 17
I'll probably switch to building an uberjar or a full-on container locally. It's been a long time coming.
Well, I do inline KBs worth of static data in other projects - where it really makes sense. :) But not here.