Fork me on GitHub

Hello 👋 I just noticed shadow-cljs is significantly slower to do hot code reloading than figwheel (I only have one dependency: material-ui). Is there something I am doing wrong? We're talking about < 1 second with figwheel and > 5 seconds with shadow


Hi, I used material-ui in the past, en I also had performance issues. The reason was that if you require material-ui core like this: ["@material-ui/core" :refer [Button Container]] You don't only require Button and Container, but everything in core. To prevent that I had to require each component individually. ["@material-ui/core/Button" :default Button] ["@material-ui/core/Container" :default Container] ... Maybe you're experiencing the same issue?


Oooh that makes sense, thanks I'll give it a try!


["@material-ui/core/Button" :default Button] is it :default or :as ?


Also I think the reason we moved away from Material UI is because the newest version had incompatible React feature (for Reagent)


Do you have a link for this issue? I'm using bare react but i'd be useful to know


I can't seem to find it sadly. Sorry.


@frankie the issues I've found are: • TextField cursors acting up -- info & fix: • [:> Component (for ...)] acting up with seqs, solvable by writing (into [:> Component] (for ...)) -- -- • material-ui has started using hooks, which are messy to use in reagent (imo). I've just avoided them, but supposedly they can be used -- info:


Ahh thanks @UCG86LJFN The hooks were my issue as well

😊 4

"dependencies": {
    "@material-ui/core": "^4.9.8",
    "@material-ui/icons": "^4.9.1",
    "create-react-class": "^15.6.2",
    "react": "^16.0.0",
    "react-dom": "^16.0.0",
    "shadow-cljs": "^2.0.80"


@frankie I hope you are not actually using that version? that is like 2 years ago old?


Oh I used the shadow-cljs template to create a fresh one


After using ["@material-ui/core/Button" :default Button] it is much faster now, thanks!


A bit annoying to add a require for each component tho


Yeah it is. But I don't think there's another way since core automatically requires everything in a hardcoded way.


I could be wrong though


And maybe this is interesting, but haven't looked at it myself:


(editted the link)


has :target become a required field in a build in shadow-cljs.edn? all my builds have started complaining about it but i'm not sure why


:target was always required


must be something else then, ta


I have a function using shadow as a library to start shadow:

(defn start-shadow []
  (shadow/watch :app)
  (shadow/watch :bootstrap-support))
This always worked but very suddenly started giving me a stack overflow error:
#error {
 :cause nil
 [{:type java.lang.StackOverflowError
   :message nil
   :at [jt14$start_shadow invokeStatic "jt14.clj" 67]}]
 [[jt14$start_shadow invokeStatic "jt14.clj" 67]
  [jt14$start_shadow invoke "jt14.clj" 66]
  [jt14$start_shadow invokeStatic "jt14.clj" 67]
  [jt14$start_shadow invoke "jt14.clj" 66]
  [jt14$start_shadow invokeStatic "jt14.clj" 67]
  [jt14$start_shadow invoke "jt14.clj" 66]
  [jt14$start_shadow invokeStatic "jt14.clj" 67]
  [jt14$start_shadow invoke "jt14.clj" 66]
It works if I do each one of the three steps sequentially in a repl but not when I call the start-shadow function. I tried updating my shadow dependency to the most recent version (from 8.69 to 8.94). Any clues what might be happening here? Is there a better way to fire up multiple watchers?


AH nevermind


i was doing something dumb


shadow-cljs watch app bootstrap-support


Today I had a wonderful day writing CLJS code. It would not have been as good without shadow-cljs . Thank you ❤️

💯 44
❤️ 8
🔥 8
Pavel Klavík18:04:36

Hi, I am trying to add to my project. They say that it should be included by

import Cropper from 'react-easy-crop'
so I am adding it like this:
["react-easy-crop" :default Cropper]
But I am getting an error that
Uncaught Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
When printed, Cropper is undefined. Do I have to include it in another way?


try ["react-easy-crop" :as Cropper]

Pavel Klavík18:04:45

thanks, helped

Pavel Klavík18:04:14

btw. wouldn't it be possible to infer the correct form automatically by Shadow-cljs compiler?


sure, just a lot of work given that there are about a billion different ways packages are written and detecting them all means work


the docs have a section about default exports

Pavel Klavík18:04:20

ya, I know of that section, and it mostly works, but sometimes a different way is needed, it seems quite random to me

Pavel Klavík18:04:48

wouldn't it be possible to try out all other different ways and to write some info which one works?


possible yes but I'm not really interested


a lot in that area is still changing very much and its gonna change a lot more in the future


so until the JS world has settled on an actual standard you'll just have to manually test sometimes


especially since this is going to be changing on a package by package basis once they adjust their packaging to adhere to the new standards

Pavel Klavík18:04:10

I see, hopefully this gets resolved


I’m sometimes getting a build error that looks like this:

[{:type clojure.lang.ExceptionInfo
   :message "aborted par-compile, [ \"re_frame/core.cljc\"] still waiting for #{re-frame.interop re-frame.interceptor re-frame.fx re-frame.registrar re-frame.router re-frame.std-interceptors re-frame.subs re-frame.cofx re-frame.db}"
   :data {:aborted [ "re_frame/core.cljc"], :pending #{re-frame.interop re-frame.interceptor re-frame.fx re-frame.registrar re-frame.router re-frame.std-interceptors re-frame.subs re-frame.cofx re-frame.db}}
   :at [$par_compile_one invokeStatic "compiler.clj" 955]}] ...
What would cause these namespaces to be waited for like this?


abort only happens after 30sec of no progress


so likely there is something blocking your compilation completely. might be a macro, not necessarily related to the listed namespaces at all


@thheller thanks, any tell tale signs for macros like this? I’m trying to think of how to debug/narrow it down.


par-compile compiles all namespaces in parallel with a limited number of threads


so if all threads get stuck for some reason it'll abort after a while


I haven't seen this reported for re-frame before so dunno why it would fail there


I'm trying to look into CLJS programming, and I keep running across shadow-cljs. However, it's hard to tell from the website what use-cases it's actually for (maybe just because I don't have the necessary vocabulary down XD). So I guess my question is, why would I use shadow-cljs?


the main reason is easy access to NPM libs (for nodejs and browser builds) it also has excellent docs, tooling and active community here. the only downside I’ve encountered is it can be tricky (but not impossible) using code that uses cljsjs deps.

Chris McCormick00:04:43

for me personally the most important "use-case" is not spending hours tinkering with your build config, which i had to do with previous build systems. shadow-cljs has excellent defaults and powerful options for when the defaults don't suit.

✔️ 16

The DX with shadow-cljs is so good, also the support (see #shadow-cljs), so at this point I think the better question is "why would you not?"


I dunno what DX stands for, but I'm probably not going to use shadow-cljs because I like to pick my own tooling. That'd be my personal reason. Also, I'm kind of liking Boot, and using shadow-cljs wouldn't let me use that.


DX stands for developer experience. 🙂 Using shadow-cljs does not preclude using Boot; there just isn't much built-in integration. But Shadow ships a Clojure API which looks pretty simple (I haven't had occasion to use it myself) and probably gets you a lot more than rolling your own CLJS compiler in Boot.


OK. Thanks for the help all!


just want to add that shadow-cljs has great repl support as well 🙂 both on the cljs-side and on the clj-side (e.g. when tinkering with macros)


@U010DM2MVQE I guess I'm biased but if you like spending hours configuring your build setup und digging into issues like hot-reload and repl support then don't use shadow-cljs. if you rather spend time working on your actual code then do use shadow-cljs. 😉

🙂 20