This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-12-23
Channels
- # adventofcode (21)
- # announcements (4)
- # babashka (35)
- # beginners (36)
- # calva (76)
- # cider (16)
- # clj-kondo (24)
- # clj-on-windows (12)
- # clojure (70)
- # clojure-europe (7)
- # clojure-nl (13)
- # clojure-spec (3)
- # clojure-uk (3)
- # clojurescript (34)
- # conjure (11)
- # cursive (22)
- # datomic (30)
- # deps-new (2)
- # emacs (36)
- # fulcro (28)
- # gratitude (4)
- # honeysql (16)
- # hugsql (8)
- # introduce-yourself (6)
- # jobs (1)
- # malli (4)
- # missionary (6)
- # off-topic (129)
- # other-languages (34)
- # polylith (3)
- # reagent (9)
- # reitit (27)
- # releases (13)
- # remote-jobs (1)
- # reveal (1)
- # shadow-cljs (2)
- # tools-build (3)
- # tools-deps (18)
- # web-security (7)
- # xtdb (4)
Hi All, when I print out the keys in SPA (keys SPA)
, I get:
(:com.fulcrologic.fulcro.application/id
:com.fulcrologic.fulcro.application/state-atom
:com.fulcrologic.fulcro.application/config
:com.fulcrologic.fulcro.application/algorithms
:com.fulcrologic.fulcro.application/runtime-atom)
Should I always keep the database in the state-atom or should I just add my own key for database? Is there a drawback to creating a database-atom key?aren't ::cffa/state-atom
and the "database" the same thing? is using state
as it's provided in e.g. defmutation
by the fulcro framework insufficient for some reason?
Why would you want to do that? Don't mess with where the client DB is, IMO. What do you want to achieve??
So, I don't understand what you are asking. People don't usually ask about the database at this level of technical detail unless one of the following is true: 1. They don't understand Fulcro yet, and have misunderstood something about it. If you're a beginner, treat SPA at opaque and don't mess with it as anything other than an opaque value. 2. You're an advanced user trying to do something fancy. The Fulcro app is a map for a reason (so it can be very open). You are allowed to do advanced things in here, provided you understand their effects. If this is the case, then your questions is vastly under-worded 😄
@U0CKQ19AQ, sound like it is a bad idea. I am probably closer to #1. Thank you for response, it answers my question.
Deferred routing works slower than immediate routing (which feels instant – deferred does not) even though I'm using a rudimentary :will-enter
fn:
(fn [app {id :id}]
(when id
(dr/route-deferred
[:id id]
(fn []
(js/console.log "routing to: " id)
(comp/transact! app [(dr/target-ready {:target [:id id]})])))))
When doing deferred routing, I am seeing 3 (2 of before route, final of after route) re-renders vs. just the one for immediate. Am I doing something wrong?Don't test performance in dev mode. Deferred routing involves going through the transaction system (potentially multiple times), and dev overhead will cause that to lead to multiple renders. Rendering is debounced to 60fps. In release optimized code it is rare to see more than one render unless the transactions themselves do a lot of work.
As a side note: Technically you can also try out the synchronous transaction processing (plugin) which runs transactions on the calling thread. This changes the semantics of operation, but has considerably less latency. It is not heavily used to my knowledge, so I cannot vouch for it as much as the standard mode, and it does not support every internal tx processing feature (e.g. I don't think it understands "after-render"), but if you want absolutely the best possible performance and latency characteristics it is a thing to try.
Thank you. I will make a note of this and try it out once I come to really measuring performance.
I gave it a shot, since it was simple to try out. Some very unscientific 'measurements' – just for a feel of the differences in basic routing (pushy active):
;; sync deferred ~50ms
;; std deferred ~140ms
;; sync immediate ~15ms
;; std immediate ~50ms
Re-renders have gone down to 2.
Being at the beginning of development, I wouldn't mind continuing with the sync processing and testing it out. Being a beginner, I'm worried I would be setting myself up for hard-to-figure-out-what's-wrong situations? What would you recommend? Or what should I keep in mind?😄 It's fine. It's just premature to do this kind of measurement IMO. Use the standard settings. If you're curious, periodically switch to sync and see if you see differences in behavior. I'd love to know it is solid. My prod apps are so large that it would take me a very long time to do that kind of testing and be sure there were no problems, and I don't like using my users as "test subjects" more than I have to 😛
I suspect that in a release build you will not have any issues, and you won't care to be on the cutting edge
but I wrote it because I recognize that for some apps this matters, and has real substantial meaning. Esp real-time interactive kinds of things.
But in all cases, measure release builds. To rely on dev measurement is true madness 😄
The Inspect overhead alone is usually 60+% of total lag...it has to diff the db, serialize it, send it to an external plugin, etc.
Well, because I get the feeling you would love to have more testing done, it would be nice of me to give this little something back, at least 🙂 Besides, I'm looking to build a mostly local app, so I'm looking to get as snappy as possible 🙂 So, any quick things I should keep in mind while working with it?
none that I specifically remember. The book talks a bit about it. There is a compile time option to switch inputs to be "unwrapped", which should be safe to use with it, and will shave off the tiniest of overheads on input response, but may lead to "jumpy cursor". Some bits of RAD or other pre-written things may exhibit unexpected "timing issues", where they've been accidentally written to expect there to be more delay.
but you can always switch back to standard and see if that fixes whatever problem you find, as a way to narrow it down to that
You can also disable Inspect and load react prod js in dev mode, and that gives you 90%+ performance without having to do a release built..it just disables tooling. I typically keep a config in shadow around for doing that...looks like this:
:performance-dev {:target :browser
:output-dir "resources/public/js/main"
:asset-path "/js/main"
:js-options {:ignore-asset-requires true
:resolve {"react-dom" {:target :npm
:require "react-dom/cjs/react-dom.production.min.js"}
"react" {:target :npm
:require "react/cjs/react.production.min.js"}}}
:modules {:main {:entries [app.client]}}
:devtools {:after-load app.client/refresh
:preloads [app.development-preload]}
:compiler-options {:closure-defines {'goog.DEBUG false}}}
you'll still get good stack traces and source mapping, so you can even do source-level debugging in the browser. You can use tap>
to look at things, etc...It's much easier to look at a flame chart this way
I'm seeing basically the same times with your performance-dev
config, same amounts of rendering.
Currently was planning on doing conditional loading and changing the window title on :will-enter
, but I could probably do those things elsewhere and use immediate routing. Or, I could stop worrying about this now :)
One thing I've noticed with stx
is that I don't see the transitory states of my router (like in the https://book.fulcrologic.com/#_live_router_example).