This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-04-07
Channels
- # announcements (5)
- # asami (17)
- # aws (11)
- # babashka (67)
- # beginners (90)
- # calva (13)
- # cider (17)
- # circleci (6)
- # clj-kondo (3)
- # clojure (53)
- # clojure-europe (12)
- # clojure-france (8)
- # clojure-germany (3)
- # clojure-losangeles (1)
- # clojure-nl (4)
- # clojure-norway (4)
- # clojure-spec (15)
- # clojure-uk (8)
- # clojurescript (41)
- # cursive (7)
- # data-science (6)
- # datomic (8)
- # emacs (10)
- # exercism (1)
- # figwheel-main (2)
- # fulcro (5)
- # graalvm-mobile (97)
- # graphql (1)
- # hyperfiddle (7)
- # inf-clojure (6)
- # interop (4)
- # introduce-yourself (5)
- # jobs (3)
- # kaocha (3)
- # malli (8)
- # meander (8)
- # music (3)
- # nrepl (7)
- # observability (1)
- # off-topic (45)
- # overtone (2)
- # polylith (63)
- # portal (2)
- # re-frame (26)
- # reveal (8)
- # ring (3)
- # shadow-cljs (56)
- # tools-build (5)
- # vim (11)
- # xtdb (8)
When I uninstall clojure tools and then try to compile my project with shadow, I get an error
The error:
throw er; // Unhandled 'error' event
^
Error: spawn clojure ENOENT
at Process.ChildProcess._handle.onexit (node:internal/child_process:283:19)
at onErrorNT (node:internal/child_process:476:16)
at processTicksAndRejections (node:internal/process/task_queues:83:21)
Emitted 'error' event on ChildProcess instance at:
at Process.ChildProcess._handle.onexit (node:internal/child_process:289:12)
at onErrorNT (node:internal/child_process:476:16)
at processTicksAndRejections (node:internal/process/task_queues:83:21) {
errno: -2,
code: 'ENOENT',
syscall: 'spawn clojure',
path: 'clojure',
spawnargs: [ '-M', '-m', 'shadow.cljs.devtools.cli', '--npm', 'server' ]
}
Node.js v17.8.0
if you set :deps
in shadow-cljs.edn
that tells shadow-cljs to use the clojure
tool and deps.edn
yes
Maybe that should be added to the docs under the installation section which lists prerequisites?
it is listed in the docs. you chose to use it. nothing in shadow-cljs requires you to use it.
In my case I thought “I wonder if I can omit the installation of Clojure Tools in my CI/CD environment” — so I checked the prerequisites at the top of the docs in the installation section and it wasn’t listed there, so I figured it was safe to omit it.
well, ok, I would have listed it with a note that it’s only required if you’re using deps.edn
, but ok, no worries, thank you!
Hi ! is there a way to explicitly ignore specific warnings for specific namespaces without using warnings-as-errors?
Suddenly I am seeing errors from shadow:
[2022-04-07 22:51:42.126 - WARNING] :shadow.cljs.devtools.server.worker.impl/cljs-compile-ex - {:input {:code "(clojure.core/refer-clojure)", :ns app.wallet, :repl true}}
ExceptionInfo Failed to process REPL command {:eof? false, :ns app.wallet, :form (clojure.core/refer-clojure), :source "(clojure.core/refer-clojure)", :tag :shadow.cljs.repl/process-ex}
shadow.cljs.repl/process-read-result (repl.clj:502)
shadow.cljs.repl/process-read-result (repl.clj:476)
shadow.cljs.repl/process-input (repl.clj:661)
shadow.cljs.repl/process-input (repl.clj:639)
shadow.cljs.devtools.server.worker.impl/fn--14599 (impl.clj:698)
shadow.cljs.devtools.server.worker.impl/fn--14599 (impl.clj:688)
clojure.lang.MultiFn.invoke (MultiFn.java:234)
shadow.cljs.devtools.server.util/server-thread/fn--14273/fn--14274/fn--14282 (util.clj:269)
shadow.cljs.devtools.server.util/server-thread/fn--14273/fn--14274 (util.clj:268)
shadow.cljs.devtools.server.util/server-thread/fn--14273 (util.clj:241)
java.lang.Thread.run (Thread.java:829)
Caused by:
ExceptionInfo ns* not supported (require, require-macros, import, import-macros, ... must be part of your ns form) {:rename-macros nil, :renames {}, :use-macros nil, :excludes #{}, :name app.wallet, :op :ns*, :env {:fn-scope [], :locals {}, :js-globals {console {:op :js-var, :name console, :ns js}, location {:op :js-var, :name location, :ns js}, escape {:op :js-var, :name escape, :ns js}, screen {:op :js-var, :name screen, :ns js}, global {:op :js-var, :name global, :ns js}, process {:op :js-var, :name process, :ns js}, require {:op :js-var, :name require, :ns js}, alert {:op :js-var, :name alert, :ns js}, history {:op :js-var, :name history, :ns js}, window {:op :js-var, :name window, :ns js}, module {:op :js-var, :name module, :ns js}, exports {:op :js-var, :name exports, :ns js}, document {:op :js-var, :name document, :ns js}, navigator {:op :js-var, :name navigator, :ns js}, unescape {:op :js-var, :name unescape, :ns js}}, :ns {:rename-macros nil, :renames {}, :meta {:file "app/wallet.cljs", :line 1, :column 5, :end-line 1, :end-column 15}, :ns-aliases {cljs.loader shadow.loader, react shadow.js.shim.module$react, clojure.pprint cljs.pprint, clojure.spec.alpha cljs.spec.alpha}, :use-macros nil, :excludes #{}, :shadow/js-access-properties #{"Text"}, :name app.wallet, :reader-aliases {}, :js-aliases {"react-native" shadow.js.shim.module$react_native}, :imports nil, :requires {cljs.core cljs.core, goog goog, shadow.js.shim.module$react_native shadow.js.shim.module$react_native, rn shadow.js.shim.module$react_native}, :seen #{:require}, :uses nil, :defs {wallet-tab {:protocol-inline nil, :meta {:file "app/wallet.cljs", :line 5, :column 7, :end-line 5, :end-column 17, :arglists (quote ([]))}, :name app.wallet/wallet-tab, :file "app/wallet.cljs", :end-column 17, :method-params ([]), :protocol-impl nil, :arglists-meta (nil nil), :column 1, :variadic? false, :line 5, :ret-tag cljs.core/IVector, :end-line 5, :max-fixed-arity 0, :fn-var true, :arglists (quote ([]))}}, :require-macros {cljs.core cljs.core}, :cljs.analyzer/constants {:seen #{:>}, :order [:>]}, :flags {:require #{}}, :js-deps {"react-native" {:as rn}}, :deps [goog cljs.core shadow.js.shim.module$react_native]}, :def-emits-var true, :shadow.build/mode :dev, :column 1, :shadow.build/tweaks false, :line 1, :shadow.build.compiler/repl-context true, :context :expr}, :imports nil, :requires nil, :uses nil, :reload {:use nil, :require nil, :use-macros nil, :require-macros nil}, :require-macros nil, :form (ns* (:refer-clojure)), :reloads {}, :deps []}
shadow.build.compiler/post-analyze (compiler.clj:94)
shadow.build.compiler/post-analyze (compiler.clj:89)
shadow.build.compiler/analyze/fn--12392 (compiler.clj:265)
shadow.build.compiler/analyze (compiler.clj:252)
shadow.build.compiler/analyze (compiler.clj:211)
shadow.cljs.repl/repl-compile/fn--14080/fn--14081 (repl.clj:441)
shadow.cljs.repl/repl-compile/fn--14080 (repl.clj:414)
shadow.cljs.repl/repl-compile (repl.clj:412)
shadow.cljs.repl/repl-compile (repl.clj:409)
shadow.cljs.repl/process-read-result (repl.clj:500)
shadow.cljs.repl/process-read-result (repl.clj:476)
The relevant code is:
(ns app.wallet
(:require
["react-native" :as rn]))
(defn wallet-tab
[]
[:> rn/Text
"Wallet"])
(comment
(js/console.log "dasdf"))
I switched to another namespace, even eval a simple a namespace such as
(ns app.event)
(def initialize-app ::initialize-app)
(def set-active-view ::set-active-view)
will also result in the shadow error.Evaluating (refer-clojure)
throws an error in shadow-cljs and also prints a huge map
{:rename-macros nil, :renames {}, :use-macros nil, :excludes #{}, :name calva.fmt.formatter, :op :ns*, :env {:fn-scope [], :locals {}, :js-globals {console {...
Is this a bug? It's fine evaluating that in a vanilla ClojureScript REPL.I was unaware of it until recently. Turns out that a lot of errors that we instruct Calva users to fix by loading the file is because we just do (in-ns …)
and that switches to the namespace, but doesn't make Clojure core available. Then some while ago I read the in-ns info on this page a bit more carefully: https://clojure.org/guides/repl/navigating_namespaces#_switching_to_an_existing_namespace_with_in_ns
in CLJ refere-clojure
is just a function. in CLJS it technically doesn't even exist since it can't do what it does in CLJ
I actually don't know if the problem it solves for clj is there for cljs. I can test that. Hopefully I can skip calling it for cljs. But if not, it would be good to not have to check if it’s shadow-cljs or vanilla cljs.
OK. So just confirmed what you probably knew, @U05224H0W: (refer-clojure)
isn't needed in ClojureScript REPLs. So then I'll mainly skip that for cljs sessions and am good with that.
well technically it is still invalid to call in-ns
before the ns exists. even in cljs
It doesn't seem to cause problems in practice, though? And that guide seems to be cool with it as long as we call refer-clojure
.
That said. Maybe it is better to do something like (if (find-ns 'foo) (in-ns 'foo) (ns foo))
?
Question about reloading and component-local state. I've set up Shadow to reload my code using https://github.com/pesterhazy/shadow-jest/blob/tictactoe/src/main/tdd/main.cljs#L5, which works fine. However, I'm seeing that component-local state gets lost. My code uses React's useState (here's a https://github.com/pesterhazy/shadow-jest/blob/tictactoe/src/main/tdd/domain/board.cljs#L9 to the code). From reagent I'm used to defonce'd state atoms, which would preserve inputs. This is very useful because while debugging/applying styles I don't need to manually recreate state every time I change a file. Now after moving to modern React and useState, is there a way to both • rerender the components after reload to let the new code take effect and • preserve the component-local state?
this is not something shadow-cljs is involved in really. it is either react or reagent. they manage the state, shadow-cljs just calls a function
I don't know how react-refresh handles preserving useState but it seemed quite involved and required support from the compiler
I didn't know about react-refresh, that's an interesting pointer, thanks!
Oh, as you say React Fast Refresh seems incredibly complicated, at least compared to what CLJS has had, basically, forever
The https://github.com/pmmmwh/react-refresh-webpack-plugin is still experimental
I knew that my question wasn't strictly about shadow-cljs, but given that it does reloading so well this channel felt like a good place to ask
well yeah if you wanted something like react-refresh then shadow-cljs would need to get more involved. I can't really figure out what it would need to do though. likely some compiler modifications that would get icky 😛
Helix already has support for react refresh. I've used it a lot and never had any troubles. https://github.com/lilactown/helix/blob/master/docs/experiments.md#fast-refresh
I used another approach for now. I created a "playground" part of the app, which has data pre-filled in. So I can use that to edit styles
This kind of stuff mostly just worked with reagent/re-frame's global state atom. I didn't realize this was such a big advantage of the (otherwise icky) global var
Not sure if you’ve looked into devcards. My favorite dev experience was using bruce’s test runner in one tab, the devcards in another tab, and the “real” tab in a third. Multiple entries on a build to enable all of this was a really great experience
Yeah, really love devcards as well. For now, I'm keeping it simple with a https://github.com/pesterhazy/shadow-jest/blob/tictactoe/src/main/tdd/main.cljs#L12
While writing this I discovered that shadow-cljs's dev webserver uses a trick to serve index.html back to arbitrary urls but only when used as the entry point - not for images, css etc. I was confused as to how this could possibly work. Turns out it checks if "text/html" is https://github.com/thheller/shadow-cljs/blob/ba0a02aec050c6bc8db1932916009400f99d3cce/src/main/shadow/http/push_state.clj#L12. Ingenious approach that I haven't seen elsewhere
The benefit is that you still get nice 404 if you mistype a jpg url in your code (whereas other popular ad-hoc webservers just blindly serve you index.html for any route that's not found)
Helix already has support for react refresh. I've used it a lot and never had any troubles. https://github.com/lilactown/helix/blob/master/docs/experiments.md#fast-refresh