Fork me on GitHub
#shadow-cljs
<
2020-05-06
>
Gordon King02:05:53

Hi is anyone experienced with boot-shadow/shadow-cljs who could help. Am changing from boot cljs to shadow for compilation, and have it successfully working via the command line. I've installed boot-shadow v 2.8.107 and are running into an error when running boot shadow/release.

No matching method sha1Hex found taking 1 args for class org.apache.commons.codec.digest.DigestUtils
This would appear to be related to the hashing function added in shadow-cljs v2.8.102. Full error in attachment. Thank you.

Gordon King04:05:35

Hi ignore for now. I had a class path conflict with commons.codec

wilkerlucio02:05:43

hello, I just started trying to use the web worker feature of shadow, but seems like shadow is trying to install devtools (fulcro inspect) in the worker

wilkerlucio02:05:52

is that a way to make the preloads load only on the :main module?

Pavel Klavík02:05:17

How are your modules set up? Do you have a shared module?

wilkerlucio03:05:56

yeah:

{:target           :browser
 :output-dir       "resources/public/js"
 :asset-path       "/js"
 :compiler-options {:closure-defines {goog.LOCALE "en"}
                    :source-map      true}
 :devtools         {:preloads       [devtools.preload com.fulcrologic.fulcro.inspect.websocket-preload]
                    :http-root      "resources/public"
                    :http-port      8120
                    :browser-inject :main}
 :modules          {:shared {:entries []}
                    :main   {:init-fn    myapp.webapp.main/init
                             :depends-on #{:shared}}
                    :worker {:init-fn    myapp.webapp.worker/init
                             :depends-on #{:shared}
                             :web-worker true}}}

thheller06:05:49

@U066U8JQJ just move the :preloads into the :main module. they can be specified per module.

wilkerlucio05:05:14

hello, something driving me a bit nuts here, I started seeing this error in a project:

------ ERROR -------------------------------------------------------------------
 File: jar:file:/Users/wilkerlucio/.m2/repository/com/wsscode/pathom/2.3.0-alpha6/pathom-2.3.0-alpha6.jar!/com/wsscode/pathom/trace.cljc:289:9
--------------------------------------------------------------------------------
 286 |       (let [trace*       (or (::trace* env) (atom []))
 287 |             env'         (assoc env ::trace* trace*)
 288 |             parser-trace (trace-enter env' {::event ::trace-plugin})]
 289 |         (let-chan [res (parser env' tx)]
---------------^----------------------------------------------------------------
Encountered error when macroexpanding clojure.core.async/go.
ClassCastException: class clojure.lang.Keyword cannot be cast to class clojure.lang.IObj (clojure.lang.Keyword and clojure.lang.IObj are in unnamed module of loader 'app')
I have another project in which the same code compiles fine, I have tried to mimic all the same deps between projects (core.async, shadow, cljs, clj), removed .shadow-cljs every time between builds, but for some reason its just not working, any ideas what I may be missing here?

sergey.shvets05:05:19

I had the same with async-helpers 1.0.5. I rolled it back to 1.0.4 and that disappeared. Probably some version conflict?

wilkerlucio05:05:07

you are right, and there was a core.async bump there, probably is it, gonna dig more on that

wilkerlucio06:05:28

@U4EFBUCUE I found the bug on the library, was a mistaken change in a require from cljs.core.async to clojure.core.async in the com.wsscode.async-cljs.clj file, version 1.0.6 released with the fix

sergey.shvets06:05:26

Thanks, I'll check it out!

Andy Heywood10:05:29

Hi folks - is there a way of using multiple lein profiles with shadow? e.g. a different profile per target?

Andy Heywood10:05:13

Motivation: using https://github.com/weavejester/environ to manage some ‘static’ configuration rather than goog-define

thheller10:05:29

no that is not supported and not recommended either

thheller10:05:04

if you really want to you can just use lein directly though

thheller10:05:25

lein with-profiles +whatever run -m shadow.cljs.devtools.cli release app or so

Andy Heywood10:05:43

ah of course, cool

Andy Heywood10:05:16

I am using config-merge, but it’s not amazing for secrets

Andy Heywood10:05:14

so this is in a node context - using config-merge for e.g. api keys builds them into the js file, so they kind of need to come from the environment. hence went to environ which I’m used to from clj

Andy Heywood10:05:34

unless I am totally missing something

thheller10:05:39

if you are in the node context then keep secrets OUT OF YOUR BUILD! 😛

thheller10:05:52

load them at runtime as actual environment variables 😛

Andy Heywood10:05:40

using environ for that, and was considering it for other things too, but I just won’t 😄

Andy Heywood10:05:19

will keep it exclusively as local dev file vs prod env separation

Andy Heywood10:05:04

thanks @thheller - had a really enjoyable time so far with shadow-cljs, very much appreciate your work

👍 4
pmooser10:05:33

No luck yet figuring out how to get shadow-cljs running under the CIDER debugger.

thheller10:05:07

how do you debug any other clj program?

pmooser10:05:47

Honestly, not too often. If I am debugging my own app it hasn't been a problem to get emacs working. But since I have been using clj since about 2008, I sort of got used to not using a debugger very often with clojure. Even though there was technically debugging support quite early, java debuggers used to get freaked out a lot by locals clearing and other stuff so it never worked very well for me. And emacs had no clojure debugging support for quite a long time.

pmooser10:05:15

Like, just as an experiment, let me see if I can debug my own app ... it'll take at least a few mins.

pmooser10:05:44

Ok, for my own app it's trivial, I just need to launch it with the cider middleware with nrepl ... not 100% sure how to do that with shadow-cljs.

pmooser10:05:16

If I launch into an nrepl interactive session, I'm not totally sure how to replicate what shadow-cljs does when I tell it 'watch app bootstrap'

thheller10:05:26

just ignore shadow-cljs

pmooser10:05:31

I am able to tell it to (compile :app) or (compile :bootstrap) but my breakpoints never get hit

pmooser10:05:35

So I'm obviously doing something wrong.

thheller10:05:42

and start it from within the nrepl session itself

thheller10:05:16

ah no clue what that debugger does

thheller10:05:25

maybe it just hooks into the current thread?

thheller10:05:36

watch runs in its own thread

thheller10:05:52

here is one thing you can try

thheller10:05:58

run shadow-cljs as normal

thheller10:05:12

connect to nrepl (without any kind of debugger or so)

thheller10:05:33

run (in-ns 'shadow.cljs.devtools.server.worker.impl)

pmooser10:05:00

OK, I can try that.

thheller10:05:46

and just eval a modified version of that fn

pmooser10:05:55

Ok thanks.

pmooser10:05:00

I will try that.

thheller10:05:03

you can just add a (tap> build-state) somewhere

thheller10:05:07

and look at it in the shadow-cljs ui

pmooser10:05:10

and lots of printlns

pmooser10:05:13

let me see 🙂

thheller10:05:33

pff println 😛

thheller10:05:53

note that you might need to restart the watch for those things to get picked up

thheller10:05:00

since the resource hooks are cached

pmooser10:05:07

How do I restart the watch?

thheller10:05:11

so start of with shadow-cljs server

thheller10:05:31

or restart from the REPL

thheller10:05:49

just don't start with shadow-cljs watch app because that will shutdown if you stop the watch

pmooser10:05:52

I mean, if I launch it with "watch app bootstrap",

pmooser10:05:58

is there a way to restart that from the repl?

pmooser10:05:07

Or do I have to do (watch :app :bootstrap) from the repl?

thheller10:05:31

you have to start the server separately if you want to be able to restart the watch

thheller10:05:47

shadow-cljs server and then separately shadow-cljs watch app is fine

thheller10:05:55

as that won't kill the server if you ctrl+c the watch

thheller10:05:08

one tap is really all you need. the inspect you will let you drill down into everything else.

pmooser10:05:21

I've never used tap>

thheller10:05:37

when the server is running open http://localhost:9630

thheller10:05:40

click inspect

pmooser10:05:40

So wait, when you say a shadow-cljs server and a separate shadow-cljs watch app, you mean 2 processes??

pmooser10:05:01

I'm a little confused, as I'm sure you can already tell.

thheller10:05:11

confused about what?

pmooser10:05:29

How does it work if I have 2 separate processes, since I want to see what is happening in the watching process?

pmooser10:05:45

(I don't understand how the two separately-launched processes are related here)

thheller10:05:53

read "Server Mode"

pmooser10:05:07

Ok thanks, got it.

pmooser10:05:11

(that makes sense)

pmooser10:05:20

Ok, trying all of this ... let's see what happens.

pmooser10:05:33

Ok clicking on REPL just results in "Loading ..."

pmooser10:05:37

So how am I supposed to add a tap? I need to connect via nrepl somehow?

pmooser10:05:20

And I assume it is the server process I'm supposed to connect to?

pmooser10:05:47

OK my emacs nrepl connection doesn't work AT ALL without the middleware, so let's see if I can connect easily via clj or something.

pmooser10:05:27

There we go, very easy with lein

pmooser10:05:59

So do you really mean (tap> build-state) or is it like (tap> build-configure) ?

pmooser10:05:04

I don't really know tap ...

pmooser10:05:05

Ah sorry, I understand now.

pmooser10:05:57

Ok, now I have those tap results ...

pmooser10:05:09

Just gotta dig around a bit and see if I can make sense of them.

thheller10:05:38

look at the :compiler-env key

thheller10:05:49

then the :cljs.analyzer/namespaces

thheller10:05:59

then the ns that is supposed to have hooks

thheller11:05:04

then the :defs

thheller11:05:12

then the name of that def

thheller11:05:24

it seems to be missing the :name for some reason

pmooser11:05:59

ok I will try to go in that order, it's kind of a lot 🙂

thheller11:05:23

uhm which shadow-cljs version are you on?

thheller11:05:29

> Ok clicking on REPL just results in "Loading ..."

thheller11:05:41

the new UI doesn't have a REPL option so are you maybe on an old one?

pmooser11:05:19

Ok so I am looking at my ns now ...

pmooser11:05:24

Let's see if anything looks weird

thheller11:05:58

I think you might need to upgrade for the UI to make any sense

thheller11:05:12

the old inspect wasn't very good

thheller11:05:23

new one isn't good either but much better than the old one 😉

thheller11:05:36

2.8.110 or so

thheller11:05:00

you really only need to look at one thing though

pmooser11:05:22

Ok I will update soon.

thheller11:05:22

[:cljs.analyzer/namespaces your.ns :defs the-hook-fn] basically

pmooser11:05:27

I am going through all the defs now

pmooser11:05:34

and looking for a :name that is nil

thheller11:05:42

no need to go through all

thheller11:05:48

just the actual name of the hook

thheller11:05:51

nothing else is relevant

pmooser11:05:56

I looked at the hook:

pmooser11:05:15

(defn ^:export ^:dev/after-load init

pmooser11:05:19

So I looked for 'init'

pmooser11:05:45

But it looks OK.

thheller11:05:13

does if have a {:name your.ns/init}?

thheller11:05:50

then I don't know how it can possible be nil when being sent to the client

pmooser11:05:56

Yeah, me neither. I just sent out the output of my init entry in defs, via private message.

pmooser11:05:03

But in any case, you've certainly gone above and beyond to try to help me.

pmooser11:05:06

So thank you for your efforts.

pmooser11:05:30

If I can't figure out emacs I will eventually have IntelliJ so maybe I can bug you about how you would use that debugger, if I don't figure it out first.

thheller11:05:18

I haven't used the debugger in years either

thheller11:05:26

I'm just using tap> nowadays with inspect

thheller11:05:04

@niwinz I think I found and fixed the ShadowJS warning issue. should be gone with next release.

niwinz11:05:43

nice, thank you, and thank for you awesome work with shadow-cljs

👍 4
pmooser12:05:11

In case anyone was following my error earlier, it turns out upgrading to the newest shadow-cljs and cljs seems to have made the error go away.

yenda13:05:06

it seems like shadow-cljs make a much bigger bundle than what we had before with clj and figwheel, is there some fundamental differences? It is only a problem on a specific device where the bundle crashes the js engine 90% of the time

4
thheller14:05:17

@yenda define "a much bigger bundle"? for release the build should be smaller, for development it will be much larger yes.

yenda14:05:56

yeah the problem is in dev

thheller14:05:58

well technically the same but for development all files are combined into one, re-natal loads many small files dynamically

thheller14:05:13

FWIW it would be trivial to provide a secondary approach like re-natal/krell do that only load a tiny js "loader" file on startup and that then loads everything else dynamically

thheller14:05:39

I opted not to do that because of the async layer it introduces, ie. making "loading" async in dev but not in production

thheller14:05:05

also takes a lot longer to load initially if done async in my tests

thheller14:05:31

but yeah I imagine the file can become quite big in larger projects

alex-eberts18:05:25

Hi Folks, I'm trying to use shadow-cljs to compile a reagent / re-frame app and shadow-cljs is telling me that required namespace react is not available. I've seen the note about using shadow-cljsjs and have added it to my shadow-cljs.edn dependencies map but that hasn't fixed the problem. What else do I need to do?

dpsutton18:05:14

is there a package.json file in the directory of the project?

alex-eberts18:05:58

ah, no. That must be it <facepalm>. thx!

wilkerlucio20:05:22

hello, I'm trying to make workspaces with web workers, but when I try to configure I get this error:

[:workspaces] Build failure:
Module Entry "devtools.preload" was moved out of module ":main".
It was moved to ":shared" and used by #{:shared :main}.

wilkerlucio20:05:30

and this is the config I'm trying:

:workspaces      {:target           nubank.workspaces.shadow-cljs.target
                  :ns-regexp        "-(test|cards)$"
                  :output-dir       "resources/workspaces/js"
                  :asset-path       "/js"
                  :compiler-options {:source-map true}
                  :modules          {:shared {:entries []}
                                     :main   {:depends-on #{:shared}
                                              :preloads   [devtools.preload com.fulcrologic.fulcro.inspect.preload]}
                                     :worker {:init-fn    my-app/init
                                              :depends-on #{:shared}
                                              :web-worker true}}
                  :devtools         {:http-resource-root "."
                                     :http-root          "resources/workspaces"
                                     :http-port          8121
                                     :browser-inject :main}}

wilkerlucio20:05:16

but I'm confused about whats going on, the workspaces is using a target that I modified a bit to dont completly override :main :entries so I can set preloads there

thheller20:05:08

don't put the devtools.preload into the :main module

thheller20:05:20

just remove it, it is added automatically when on the classpath

wilkerlucio20:05:49

@thheller I tried messing with the target, if I remove that i complains on the same for the inject-repl-client

wilkerlucio20:05:28

(defn resolve-cards-and-tests
  [{::build/keys [mode config] :as state}]
  (let [{:keys [ns-regexp] :or {ns-regexp "-(ws|test)$"}}
        config

        dynamically-resolved-namespaces
        (find-namespaces-by-regexp state ns-regexp)]

    (-> state
      ;; Add the mounter and all of the resolved cards/tests
      (assoc-in [::modules/config :main :entries] (-> []
                                                      (into (get config :preloads []))
                                                      (into dynamically-resolved-namespaces)
                                                      (conj 'nubank.workspaces.shadow-cljs.mount)))
      (cond->
        (and (= :dev mode) (:worker-info state))
        (update-in [::modules/config :main] browser/inject-repl-client state config)

        (= :dev mode)
        (-> (update-in [::modules/config :main] browser/inject-preloads state config)
          (update-in [::modules/config :main] browser/inject-devtools-console state config)))
      (modules/analyze))))

wilkerlucio20:05:34

the cond-> part seems to be problem

wilkerlucio20:05:45

yeah, removing that the compilatin works, altough it still installing the devtools twice (once on main, once on worker when it starts)

thheller20:05:55

thats normal?

thheller20:05:13

it is its own context after all so it will initialize twice

thheller20:05:27

unless you are not planning on doing any logging in the worker?

wilkerlucio20:05:21

nah, you are right, confusion on my part, first time using web workers, so I guess its fine

thheller20:05:05

yeah all code in :shared will be loaded twice, that will include devtools.preload and whatever that does

thheller20:05:29

btw if you upgrade you don't need the :browser-inject logic anymore

haywood21:05:22

I have a build hook that runs during the configuration step, when building a release it seems like the compile step happens in parallel, is that right?

thheller21:05:28

no, configure always happens once and compile only starts when that finishes

thheller21:05:21

or do you mean the compilation happens in parallel itself? that would be true for development too

haywood21:05:51

during the release build my hook is called after [:app] Compiling ... is printed

thheller21:05:55

Compiling ... is from the build-start event, that happens before anything else?

thheller21:05:11

again .. also true for dev?

haywood21:05:32

the hook generates a new clojurescript file that some files in the project depend on, so during development the generated file is there before the compilation step, but in the release build the compile step fails because the generated file is not there yet

thheller21:05:33

whats the issue? what are you doing in the hook?

thheller21:05:45

didn't I warn you against doing that?

haywood21:05:57

no I don’t think I got guidance

thheller21:05:26

don't use hooks to generate files that you intend to use in the compilation :P

haywood21:05:27

you know, yea I can get around this

haywood21:05:38

so I am using the hook to kick off a filesystem watch

haywood21:05:45

in prod I can just run it beforehand

haywood21:05:48

right thanks

thheller21:05:02

you definitely should not be doing that 😛 (starting a watch in a hook)

haywood21:05:42

(when (= :dev (:shadow.build/mode build-state))
      (fs-watch/start {}
                      (file-seq (io/file pages-directory))
                      ["cljs" "cljc" "clj" "js"]
                      gen-routes-fn))

haywood21:05:55

seems to work fine

thheller21:05:58

yeah .. don't do that

haywood21:05:25

so basically you’re prescribing just a separate step that is bundled in the dev calls

haywood21:05:45

make dev boots up shadow and the watcher

thheller21:05:19

you should run anything like that separately

thheller21:05:36

if you must start it with shadow-cljs use clj-run

haywood21:05:06

roger that!

haywood21:05:15

thanks, and hey

haywood21:05:19

you are my hero I want you to know

😎 4
haywood21:05:39

I do feel like it would be really powerful to have a hook that can be called before shadow does anything, because ultimately it would be nice to open source this thing and that would make the install way easier

haywood21:05:14

wow, could this be what :devtools are for lmao

haywood21:05:33

sorry, I’ll get there

thheller21:05:03

the issue why I'm advising against running this as a hook is that it starts a thread

thheller21:05:23

and you are likely not shutting that down anywhere

thheller21:05:50

so you can get into situations where it will be watching 1,2,3,4,5,6,n times

thheller22:05:03

since configure is called whenever you edit the build config for example

thheller22:05:32

I have a plugin mechanism which would let you plug into the lifecycle properly

thheller22:05:49

but it isn't publicly documented since I don't think its a good idea

wilkerlucio22:05:57

@thheller I like to contribute to shadow docs, where does the source of it lives?