This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-12-09
Channels
- # adventofcode (93)
- # announcements (11)
- # babashka (7)
- # babashka-sci-dev (17)
- # beginners (73)
- # biff (7)
- # calva (3)
- # cider (1)
- # clj-kondo (160)
- # clj-together (12)
- # clojure (44)
- # clojure-art (2)
- # clojure-europe (12)
- # clojure-losangeles (1)
- # clojure-nl (3)
- # clojure-norway (22)
- # clojure-uk (2)
- # clojurescript (8)
- # clr (1)
- # cursive (6)
- # data-science (1)
- # datomic (1)
- # emacs (6)
- # events (1)
- # exercism (1)
- # fulcro (6)
- # graphql (2)
- # introduce-yourself (1)
- # lsp (18)
- # nrepl (7)
- # off-topic (45)
- # polylith (25)
- # portal (25)
- # practicalli (3)
- # re-frame (14)
- # reagent (28)
- # reitit (2)
- # releases (2)
- # shadow-cljs (73)
- # sql (11)
- # tools-deps (12)
- # transit (4)
- # xtdb (4)
hey all - for some reason I am not seeing a manifest.edn in my output directory. is there some way to ensure that itโs produced?
with this shadow-cljs.edn https://github.com/mentat-collective/jsxgraph.cljs/blob/sritchie/new_clerk/shadow-cljs.edn
Hi all, I'm trying to use code splitting to load debugging code wtihout having the production app burdened with the debug code. The way it is now, the debug module needs to be called after the re-frame subscription cache is cleared, but before the app is rendered to the dom.
(defn init!
[]
(f/clear-subscription-cache!)
(shadow.loader/load "debug") ; Must happen here
(some->> "container"
(.getElementById js/document)
(dom/render [ui/app])))
However, it seems that with the code above the debug module is actually being executed after the dom/render
. I have the following in my shadow config:
{:module-loader true
:modules {:main {:init-fn app/init!}
:debug {:depends-on #{:main}
:entries [app.debug.loader]}}}
Are my expectations wrong that the module would be loaded synchronously at (shadow.loader/load "debug")
?something like
{:module-loader true
:modules {:main {:entries [app.debug.loader]
:init-fn app/init!}}}
just the presence of the debug code in the build will hinder :advanced
and likely make your build much larger even in the :main
module
Thanks for the response! Hmm... at that point do I even need the module-loader? It would seems that there's no dynamic module loading with that approach?
Ok, and just to be clear, you're suggesting I should duplicate app/init!
one with the debug line and one without?
{:modules {:main {:init-fn app/init!}}
:dev {:modules {:main {:entries [app.debug.loader]}}}}
Apologies, I'm not sure I immediately parse the above map. Is it missing an :app
build? How do you mean "one build".
A little more detail on what I'm trying accomplish: I'm putting together a little OSS lib that has both domain features and debug features. In an ideal world, a user would use the domain features as normal, and where necessary include a preloads namespace for the debug module. However, the use of re-frame f/clear-subscription-cache!
introduces imperative logic around instantiated subscriptions in the debug module. I can't just dump the debug module in a preload namespace because the debug module has to be loaded after the (f/clear-subscription-cache!)
, but ideally before the render. I'm not really sure I see how to accomplish this imperatively without dynamic module loading.
I guess a solution where the user defines two builds, with duplicated init
methods one with and without the debug loading could work. But I've been trying to identify the approach that would be easiest to use as a library, and I'm not sure I've found it yet.
Has something changed about how shadow-cljs
works?
I've got it setup in my user.clj to require shadow in the form of [shadow.cljs.devtools.api :as shadow]
so I can then call (shadow/watch :app)
and (shadow/browser-repl)
.
However just trying to start the repl blows up. Commenting out the require seems to work and then sending the form to my repl does this:
Connecting to local nREPL server...
Clojure 1.11.1
nREPL server started on port 63444 on host 127.0.0.1 -
(ns user
(:require [shadow.cljs.devtools.api :as shadow]))
Execution error (NoSuchMethodError) at com.google.javascript.jscomp.deps.ModuleLoader/createRootPaths (ModuleLoader.java:257).
'java.util.stream.Collector com.google.common.collect.ImmutableSortedSet.toImmutableSortedSet(java.util.Comparator)'
I'm using [thheller/shadow-cljs "2.20.13"]
via lein.nothing has changed, except that you introduce a dependency conflict. likely on guava
To add more detail:
*e
=>
#error{:cause "'java.util.stream.Collector com.google.common.collect.ImmutableSortedSet.toImmutableSortedSet(java.util.Comparator)'",
:via [{:type clojure.lang.Compiler$CompilerException,
:message "Syntax error macroexpanding at (closure.clj:77:5).",
:data #:clojure.error{:phase :execution, :line 77, :column 5, :source "closure.clj"},
:at [clojure.lang.Compiler$StaticMethodExpr eval "Compiler.java" 1750]}
{:type java.lang.NoSuchMethodError,
:message "'java.util.stream.Collector com.google.common.collect.ImmutableSortedSet.toImmutableSortedSet(java.util.Comparator)'",
:at [com.google.javascript.jscomp.deps.ModuleLoader createRootPaths "ModuleLoader.java" 257]}],
:trace [[com.google.javascript.jscomp.deps.ModuleLoader createRootPaths "ModuleLoader.java" 257]
[com.google.javascript.jscomp.deps.ModuleLoader <init> "ModuleLoader.java" 147]
[com.google.javascript.jscomp.deps.ModuleLoader <init> "ModuleLoader.java" 48]
[com.google.javascript.jscomp.deps.ModuleLoader$Builder build "ModuleLoader.java" 139]
[com.google.javascript.jscomp.deps.ModuleLoader <clinit> "ModuleLoader.java" 408]
[com.google.javascript.jscomp.DiagnosticGroups <clinit> "DiagnosticGroups.java" 182]
[jdk.internal.misc.Unsafe ensureClassInitialized0 "Unsafe.java" -2]
[jdk.internal.misc.Unsafe ensureClassInitialized "Unsafe.java" 1160]
[jdk.internal.reflect.MethodHandleAccessorFactory
ensureClassInitialized
"MethodHandleAccessorFactory.java"
300]
[jdk.internal.reflect.MethodHandleAccessorFactory
newMethodAccessor
"MethodHandleAccessorFactory.java"
71]
[jdk.internal.reflect.ReflectionFactory newMethodAccessor "ReflectionFactory.java" 159]
[java.lang.reflect.Method acquireMethodAccessor "Method.java" 720]
[java.lang.reflect.Method invoke "Method.java" 575]
[clojure.lang.Reflector invokeMatchingMethod "Reflector.java" 167]
[clojure.lang.Compiler$StaticMethodExpr eval "Compiler.java" 1743]
[clojure.lang.Compiler$InvokeExpr eval "Compiler.java" 3713]
[clojure.lang.Compiler$DefExpr eval "Compiler.java" 457]
[clojure.lang.Compiler eval "Compiler.java" 7199]
[clojure.lang.Compiler load "Compiler.java" 7653]
[clojure.lang.RT loadResourceScript "RT.java" 381]
[clojure.lang.RT loadResourceScript "RT.java" 372]
[clojure.lang.RT load "RT.java" 459]
[clojure.lang.RT load "RT.java" 424]
[clojure.core$load$fn__6908 invoke "core.clj" 6161]
[clojure.core$load invokeStatic "core.clj" 6160]
[clojure.core$load doInvoke "core.clj" 6144]
[clojure.lang.RestFn invoke "RestFn.java" 408]
[clojure.core$load_one invokeStatic "core.clj" 5933]
[clojure.core$load_one invoke "core.clj" 5928]
[clojure.core$load_lib$fn__6850 invoke "core.clj" 5975]
[clojure.core$load_lib invokeStatic "core.clj" 5974]
[clojure.core$load_lib doInvoke "core.clj" 5953]
[clojure.lang.RestFn applyTo "RestFn.java" 142]
[clojure.core$apply invokeStatic "core.clj" 669]
[clojure.core$load_libs invokeStatic "core.clj" 6016]
[clojure.core$load_libs doInvoke "core.clj" 6000]
[clojure.lang.RestFn applyTo "RestFn.java" 137]
[clojure.core$apply invokeStatic "core.clj" 669]
[clojure.core$require invokeStatic "core.clj" 6038]
[shadow.build.js_support$eval5552$loading__6789__auto____5553 invoke "js_support.clj" 1]
[shadow.build.js_support$eval5552 invokeStatic "js_support.clj" 1]
[shadow.build.js_support$eval5552 invoke "js_support.clj" 1]
Oh? I'm not requiring guava myself, so there's a deps mismatch that I need to resolve?
So I'll just deps tree and require the latest version? Or does shadow-cljs need a specific older version?
This is the one thing I do wish was a bit better, you can have stuff working perfectly well which then blows up when you're doing a deps build on a clean repo and you have no idea what's causing the failure...
Ok, this is weird, now shadow is complaining that shadow-cljs has not been started yet?
(shadow/watch :app)
Execution error (ExceptionInfo) at shadow.cljs.devtools.server.runtime/get-instance! (runtime.clj:10).
shadow-cljs has not been started yet!
In embedded mode you need to call (shadow.cljs.devtools.server/start!) to start it.
If you have a shadow-cljs server or watch running then you are not connected to that process.
But I have it running in a separate terminal.Sorry, I'm calling (shadow.cljs.devtools.api/watch :app)
Which normally just says the watch is running. So I can confirm that the server REPL is seeing the same stuff that the watch command I'm running via npx shadow-cljs watch app
is seeing.
but if you get shadow-cljs has not been started yet!
you are not connected to a running shadow-cljs
So my process, which I normally use is based on:
1. Run npx shadow-cljs watch app
2. Start the lein repl via cursive and require [shadow.cljs.devtools.api :as shadow]
3. Confirm the connection via (shadow/watch :app)
4. Start a browser repl with (shadow/browser-repl)
The problem is that if I don't do it this way, I don't get clojurescript symbol import.
Checking the embedded link you shared
Yep, which has worked, as it keeps clojurescript errors contained in one location (the terminal)
there are a million ways to do this and none of this has changed since it was released
That's fair, I suppose I'm trying to work out why this is no longer able to detect the running shadow-cljs instance whereas previously it could.
if you run npx shadow-cljs watch app
you don't need an extra (shadow/watch :app)
since that is redundant
Oh sure, but in this case it confirms that the clojure server can also see the same watcher.
Huh, that's interesting:
(require '[shadow.cljs.devtools.server])
=> nil
(shadow.cljs.devtools.server/start!)
Execution error (ExceptionInfo) at shadow.cljs.devtools.server/check-for-other-instance! (server.clj:412).
shadow-cljs already running in project on . Use or terminate it before starting another one.
So it can detect it, but not connect to it?Hmm, ok, running it directly in the repl doesn't quite work:
=> :shadow.cljs.devtools.server/started
(shadow/watch :app)
[:app] Configuring build.
[:app] Compiling ...
[:app] Build failure:
IllegalArgumentException: No matching method legacySetOutputFeatureSet found taking 1 args for class com.google.javascript.jscomp.CompilerOptions
clojure.lang.Reflector.invokeMatchingMethod (Reflector.java:127)
clojure.lang.Reflector.invokeInstanceMethod (Reflector.java:102)
shadow.build.closure/set-options (closure.clj:166)
shadow.build.closure/convert-goog* (closure.clj:2298)
shadow.build.closure/convert-goog (closure.clj:2445)
shadow.build.closure/convert-goog (closure.clj:2396)
shadow.build.compiler/maybe-closure-convert (compiler.clj:1241)
shadow.build.compiler/compile-all (compiler.clj:1475)
shadow.build.api/compile-sources (api.clj:253)
shadow.build/compile (build.clj:493)
shadow.cljs.devtools.server.worker.impl/build-compile (impl.clj:360)
shadow.cljs.devtools.server.worker.impl/eval16926/fn--16928 (impl.clj:445)
clojure.lang.MultiFn.invoke (MultiFn.java:234)
shadow.cljs.devtools.server.util/server-thread/fn--16684/fn--16685/fn--16693 (util.clj:283)
shadow.cljs.devtools.server.util/server-thread/fn--16684/fn--16685 (util.clj:282)
shadow.cljs.devtools.server.util/server-thread/fn--16684 (util.clj:255)
java.lang.Thread.run (Thread.java:1589)
Thanks for your help =)...
I'll try and see if I can re-engineer this to work again, the split workflow was helpful as I could keep the client-side / server side deps separate, whereas now I would need to co-mingle them.
The biggest issue is no longer having easy access to the browser repl, though I can just use a remote repl connection to use that, so perhaps it's fine ๐...that "shadow-cljs already running in project" is an error I added recently because people often unknowingly started two shadow-cljs instances which compete with each other
Is it possible to have dependencies specific to a build in a pure shadow-cljs project? For context on my problem: the dev builds of my app make use of two devtools preloads. One depends on highlight.js
and has it added as a normal dependency in my package.json
file, instead of as a dev dependency. I want to avoid unnecessarily packing libraries into production builds
@hifumi123 not required, if you don't require it it won't be included in the build. extra dependencies otherwise have no impact.