Fork me on GitHub

Q: I’ve switched to an M1 mac/Big Sur and I’m seeing a delay in shadow compiles when using the :watch. Has anyone else seen this?


I use Cursive and “Save All” to initiate. I’m pretty sure Cursive is saving the file because when I try the same thing in a node/browsersync project, the rebuild is instant


I’ve switched to :watch verbose but don’t see anything there.


Any suggestions on how I can diagnose where the delay comes from?

eccentric J05:02:10

Did the watch verbose include a timestamp?


I just checked: no timestamp


@U0510KXTU update. I removed hawk and that makes everything faster again.


ok. I’ll try that soon. I have a dependency that breaks in latest shadow so I’ll have to refactor that first


thanks for the heads up


how does it break?


No break. Just a delay between save and start of compile. In cursive I can see the dirty file indicator disappear so that's why I suspect the watcher


It's not a blocker, just interrupts flow a bit


Seems only fair that I upgrade before asking more of your time


I'll report back again once I'm on latest


> I have a dependency that breaks in latest shadow


that break I meant. the delay I know and fixed.


Ah ok. We discussed it a while back. It's which can be replaced by a more current wrapper. It's in my backlog


I'm on latest shadow for all other cljs projects so I need to do this anyway


Hmm, that makes me realise I can verify the fix on other projects. I'll test this in the morning and will report back


Useful chat 😀


ok, I can confirm the delay goes away with 2.11.18. it was still there with 2.11.8. thanks for the fix


Interesting, I’ve been running :fs-watch {:hawk false} on an M1 Mac for 2 months now and came here to say the exact same thing. It’s faster without hawk on my setup. I should have mentioned it sooner!


Hey, I have a bit of a weird bug that appeared when I switched from figwheel-sidecar (0.5.20) + cljsbuild (1.1.8) over to shadow-cljs (2.11.18). My application is running on Electron (5.0.2, can't update) and re-frame (0.10.9). The app uses a touch screen and no other peripherals, and the users need to input text, so a homebrew on-screen keyboard is used. Everything worked fine with figwheel, but when I switched to shadow, with no other dependencies being updated or changed, text inputs broke. When the user types into a field with the on-screen keyboard, the caret stays stuck to the start of the input. Naturally I have access to a keyboard when developing, which works just fine for text input: the caret moves as I input characters into the text field. After I've input some text with a keyboard, and switch to using the on-screen keyboard, the caret also continues to behave normally. Only when I input into an untouched field, with the on-screen keyboard, does the caret get stuck. The text field content is managed from re-frame db, and the on-screen keyboard "inputs" append the pressed key to the selected field's state in the db. I've tried to dispatch the same events a physical keyboard would send (`input`, keyup and keydown). I've tried to use .setSelectionRange to manually correct the caret to the right place, but it gets overwritten, so right now the ugly workaround I have is to set the caret position on a short timeout. This leads to the caret visibly jumping as you type, but the characters mostly go where they need to go. I want to stress that this all worked completely normally with figwheel, and only upgrading to shadow broke it. Are there any guesses to what might have broken it? Different optimizations, transpiling to a different version? I might have to switch back to figwheel if I can't solve this, because the current hack to type correctly is very unreliable and fragile.


I can't give the project sources over, but here's the project.clj for the frontend. Shadow config included because of lein-shadow

(defproject xxx "3.3.1"
  :dependencies [[org.clojure/clojure "1.10.1"]
                 [org.clojure/clojurescript "1.10.764"]
                 [org.clojure/spec.alpha "0.2.187"]
                 [medley "1.3.0"]
                 [re-frame "0.10.9"]
                 [garden "1.3.10"]
                 [ "v0.2.0"]
                 [com.taoensso/tempura "1.2.1"]
                 [com.andrewmcveigh/cljs-time "0.5.2"]
                 [thheller/shadow-cljs "2.11.18"]]

  :plugins [[lein-garden "0.3.0"]]

  :min-lein-version "2.5.3"

  :source-paths ["src/clj" "src/cljs" "src/cljc"]

  :clean-targets ^{:protect false} ["resources/public/js/compiled" "target"]

  :garden {:builds [{:id           "screen"
                     :source-paths ["src/clj" "src/cljc"]
                     :stylesheet   xxx.css/screen
                     :compiler     {:output-to     "resources/public/css/garden.css"
                                    :pretty-print? true}}]}

  :profiles {:dev  {:dependencies [[binaryage/devtools "1.0.2"]
                                   [ "0.3.7-react16"]
                                   [ "0.6.0"]]
                    :plugins      [[lein-kibit "0.1.8"]
                                   [lein-shadow "0.3.1"]]}
             :prod {:dependencies [[ "0.6.0"]]}}

  :npm-deps [[create-react-class "15.6.3"]
             [react "16.8.6"]
             [react-dom "16.8.6"]
             [react-flip-move "^3.0.4"]
             [react-highlight.js "^1.0.7"]]

  :npm-dev-deps [[shadow-cljs "^2.11.18"]]

  :shadow-cljs {:lein   true
                :builds {:app {:target           :browser
                               :modules          {:app {:entries [xxx.core]}}
                               :output-dir       "resources/public/js/compiled"
                               :asset-path       "/js/compiled"
                               :dev              {:closure-defines {"re_frame.trace.trace_enabled_QMARK_"        true
                                                                    "day8.re_frame.tracing.trace_enabled_QMARK_" true}}
                               :devtools         {:preloads   [devtools.preload
                                                  :watch-dir "resources/public"}
                               :compiler-options {:optimizations :simple}}}})


For one you are not using the correct CLJS version. That should be 1.10.773 for 2.11.18.


what CLJS version did the figwheel variant use?


the cause of this problem will be somewhere in your code but I cannot say where. I vaguely remember some things breaking because of a CLJS update sometime ago but can't remember details


CLJS version was not changed, so it was the same when I used figwheel. I will update CLJS and report back!


Bumping CLJS version to 1.10.773 did not change behaviour. I'm not ruling out a problem in re-frame/reagent/react that manifested by changing build tools, but I'm at loss so I will ask on #re-frame


yeah I don't have a clue what could be causing this


is this with release only or also with development builds?


I've narrowed it down just now to re-frame not firing off the input events until after the virtual keyboard has been closed the first time for each field or physical keyboard input is given. Not sure why this surfaced now, but that's the issue


So I will continue the discussion on re-frame channel if I get stuck again 👍

Jakub Holý (HolyJak)14:02:50

Hello! Is it possible to require a ns only if goog.DEBUG is true? In Clojure I would use requiring-resolve but that is not available in cljs. (I have a library under my :dev alias dependencies that I use during development but do not want to include in production code.) Thank you!


@holyjak :preloads [that.ns] in your :modules or :devtools

❤️ 3
Jakub Holý (HolyJak)15:02:06

Thank you! I have now added my.ns as a pre-load and in my code I use

(when goog.DEBUG (my.ns/my-fn))
But will this not complain about unknown symbol my.ns when I run release?


yeah you can't do that

Jakub Holý (HolyJak)15:02:42

Ok. So what is a solution when I need to call to the dev-only code from my prod code (but only while running in dev)? Perhaps in the preload I could store the fn in some *dyn-var* that lives in code that is save to share between both and call (when *dyn-var* (*dyn-var*)) in my prod code?

Jakub Holý (HolyJak)16:02:37

I guess I could simply define js/myThing in my dev code and use that from my prod code...


I cannot answer that without more information. I do not know what you are calling this way and what the code actually does. You cannot dynamically require anything so you'll have to find a different solution.

Jakub Holý (HolyJak)16:02:07

I figured it out. Instead of calling (holyjak.fulcro-troubleshooting/troubleshooting-render-middleware) in my prod code I will call (js/holyjak.fulcro_troubleshooting.troubleshooting_render_middleware) As long as I only do this in dev, it will work.


can't you just create a ns that you add to preload and that adds the middleware in question? or does it have to be in your app ns?

Jakub Holý (HolyJak)17:02:25

The problem is that it cannot "add the middleware". The prod code has to ask for the middleware. There is, in prod code, something like:

(setup-app {:middleware <some middleware...>})
And my dev-time code is a library so I cannot assume anything about the user's code other than that it has a use for a middleware (as defined by the framework).

Raymond Ko18:02:51

Has anyone seen this kind of error before? A case if works on my local machine, but stopped working on CircleCI. The build user is root so I am not sure why it would fail a file system operation.

IOException: Operation not permitted ( ( ( (
	jdk.internal.reflect.NativeMethodAccessorImpl.invoke0 (
	jdk.internal.reflect.NativeMethodAccessorImpl.invoke (
	jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke (
	java.lang.reflect.Method.invoke (
	clojure.lang.Reflector.invokeMatchingMethod (
	clojure.lang.Reflector.invokeNoArgInstanceMember ( (node.clj:224) (node.clj:212) (node.clj:209) (node_library.clj:194) (node_library.clj:189) (node_library.clj:213) (node_library.clj:196)


odd. is that permanent or just temporary? maybe some disk stuff going on?

Raymond Ko19:02:24

Inside a :builds target, I had :output-dir "./" :output-to "./handler.js This stopped working for some reason. I changed it to :output-dir "output" :output-to "output/handler.js` and it worked! Removing the trailing / does not make a difference. Must be CircleCI or my updated Docker build image...

Jakub Holý (HolyJak)19:02:02

What could this mean? I have done this for ages and never seen this error - "missing instance" - before:

Connecting to remote nREPL server...
Clojure 1.10.1
(shadow/repl :main)
Execution error (ExceptionInfo) at shadow.cljs.devtools.server.runtime/get-instance! (runtime.clj:11).
missing instance
(I am running npx shadow-cljs watch main ) Restarting Shadow fixed it so it is not a problem anymore but still, it was weird...