shadow-cljs

https://github.com/thheller/shadow-cljs | https://github.com/sponsors/thheller | https://www.patreon.com/thheller
steveb8n 2021-02-23T01:28:54.055200Z

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?

thheller 2021-02-23T08:16:31.056500Z

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

steveb8n 2021-02-23T08:18:17.056700Z

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

steveb8n 2021-02-23T08:18:21.056900Z

thanks for the heads up

thheller 2021-02-23T08:56:33.063900Z

how does it break?

steveb8n 2021-02-23T09:56:31.069600Z

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

steveb8n 2021-02-23T09:57:13.069800Z

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

steveb8n 2021-02-23T09:57:43.070Z

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

steveb8n 2021-02-23T09:58:03.070200Z

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

thheller 2021-02-23T10:29:30.070400Z

> I have a dependency that breaks in latest shadow

thheller 2021-02-23T10:29:36.070600Z

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

steveb8n 2021-02-23T11:21:31.071Z

Ah ok. We discussed it a while back. It's https://github.com/hubgit/react-prosemirror which can be replaced by a more current wrapper. It's in my backlog

steveb8n 2021-02-23T11:22:30.071300Z

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

steveb8n 2021-02-23T11:23:46.071500Z

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

steveb8n 2021-02-23T11:24:23.071700Z

Useful chat 😀

steveb8n 2021-02-24T06:08:20.081300Z

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

donavan 2021-03-05T12:43:04.250800Z

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!

steveb8n 2021-02-23T01:29:45.055300Z

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

steveb8n 2021-02-23T01:30:15.055500Z

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

steveb8n 2021-02-23T01:30:32.055700Z

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

2021-02-23T05:48:10.055900Z

Did the watch verbose include a timestamp?

steveb8n 2021-02-23T07:06:29.056100Z

I just checked: no timestamp

2021-02-23T09:01:50.068500Z

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.

2021-02-23T09:06:59.068600Z

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"]
                 [day8.re-frame/http-fx "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"]
                                   [day8.re-frame/re-frame-10x "0.3.7-react16"]
                                   [day8.re-frame/tracing "0.6.0"]]
                    :plugins      [[lein-kibit "0.1.8"]
                                   [lein-shadow "0.3.1"]]}
             :prod {:dependencies [[day8.re-frame/tracing-stubs "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
                                                               day8.re-frame-10x.preload]
                                                  :watch-dir "resources/public"}
                               :compiler-options {:optimizations :simple}}}})

thheller 2021-02-23T09:15:40.068800Z

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

thheller 2021-02-23T09:15:50.069Z

what CLJS version did the figwheel variant use?

thheller 2021-02-23T09:17:56.069200Z

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

2021-02-23T09:20:02.069400Z

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

2021-02-23T11:12:04.070800Z

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

thheller 2021-02-23T11:58:14.071900Z

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

thheller 2021-02-23T11:58:29.072100Z

is this with release only or also with development builds?

2021-02-23T11:59:53.072300Z

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

2021-02-23T12:01:37.072500Z

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

Jakub Holý 2021-02-23T14:31:50.074600Z

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!

thheller 2021-02-23T15:14:56.075300Z

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

❤️ 1
Jakub Holý 2021-02-23T15:22:06.075500Z

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?

thheller 2021-02-23T15:25:38.075700Z

yeah you can't do that

Jakub Holý 2021-02-23T15:58:42.075900Z

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ý 2021-02-23T16:03:37.076100Z

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

thheller 2021-02-23T16:05:36.076300Z

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ý 2021-02-23T16:33:07.076600Z

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.

thheller 2021-02-23T16:34:53.076800Z

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ý 2021-02-23T17:38:25.077400Z

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 Ko 2021-02-23T18:58:51.078700Z

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.

nil
IOException: Operation not permitted
	java.io.UnixFileSystem.canonicalize0 (UnixFileSystem.java:-2)
	java.io.UnixFileSystem.canonicalize (UnixFileSystem.java:178)
	java.io.File.getCanonicalPath (File.java:620)
	java.io.File.getCanonicalFile (File.java:645)
	jdk.internal.reflect.NativeMethodAccessorImpl.invoke0 (NativeMethodAccessorImpl.java:-2)
	jdk.internal.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62)
	jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
	java.lang.reflect.Method.invoke (Method.java:566)
	clojure.lang.Reflector.invokeMatchingMethod (Reflector.java:167)
	clojure.lang.Reflector.invokeNoArgInstanceMember (Reflector.java:438)
	shadow.build.node/flush-optimized/fn--18657 (node.clj:224)
	shadow.build.node/flush-optimized (node.clj:212)
	shadow.build.node/flush-optimized (node.clj:209)
	shadow.build.targets.node-library/flush (node_library.clj:194)
	shadow.build.targets.node-library/flush (node_library.clj:189)
	shadow.build.targets.node-library/process (node_library.clj:213)
	shadow.build.targets.node-library/process (node_library.clj:196)

thheller 2021-02-23T19:04:16.079700Z

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

Jakub Holý 2021-02-23T19:09:02.080500Z

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...

Raymond Ko 2021-02-23T19:14:24.080900Z

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...