This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-02-24
Channels
- # beginners (113)
- # boot (9)
- # cider (6)
- # cljs-dev (33)
- # cljsjs (1)
- # clojure (73)
- # clojure-italy (4)
- # clojure-russia (6)
- # clojure-spec (13)
- # clojure-uk (21)
- # clojured (1)
- # clojurescript (79)
- # core-async (6)
- # core-logic (4)
- # datascript (5)
- # datomic (5)
- # duct (12)
- # events (1)
- # figwheel (9)
- # fulcro (143)
- # garden (2)
- # leiningen (1)
- # luminus (24)
- # off-topic (1)
- # parinfer (7)
- # protorepl (12)
- # re-frame (4)
- # reagent (32)
- # rum (1)
- # shadow-cljs (46)
- # spacemacs (4)
- # specter (27)
- # sql (6)
- # unrepl (3)
- # videos (1)
So, I would appreciate a community cross-check here: I’m planning to add support to the DOM function to detect and auto-convert clj maps (so we can stop using #js
…it’ll be optional optimization to use it). I’ve benchmarked the change, and it won’t hurt a thing. I’m trying to decide the answer to this: “Should I throw an exception if it isn’t nil, an object?
, or a map?
?” I’ve never written code in Fulcro that would violate that assumption, but it might be technically possible to pass something to react that would work as props, but whose constructor isn’t js/Object
@tony.kay you can just look at the argument in the macro. if its something it can identify as a map/js-object/nil it does the optimization in the macro. if not it falls back to "interpreted" mode and does the conversion at runtime. I do this in my react element wrapper. https://github.com/thheller/shadow/blob/master/src/main/shadow/markup/react.clj#L147-L164
do (dom/h1 {} ...)
, (dom/h1 nil ...)
and (dom/h1 #js {} ...)
are all "fast" and (dom/h1 foo ...)
is slightly slower
@thheller So, you're right that that would cut overhead further, but the actualy measured overhead of the cond compared to everything else is soooo small I don't see it as being worth it. It wasn't even measurable in a statistically significant sense when compared to the overhead, for example, of React's VDOM->DOM stage. I think we're over-optimizing
and string is a legal thing to give props...not sure what you mean by fast path for string?
The one I did think of last night was undefined...that should be explicitly checked for in js since there are ways to end up with that instead of nil
If the cond is structure like this:
(cond
(or (nil? props) (object? props)) props
(map? props) (clj->js props)
...)
(order is important) then it turns into an if (at compile time) that first checks for the "cheap stuff". nil compare is very cheaponce you're to map?
then you're doing a bit more, but you're about to do a conversion which is heavy anyhow, and you already took the overhead of the creation of a persistent data structure
I do know that cond is a macro, and that nil? , object?, and map? are not. I've read the source. I've done a lot of critical optimization in my time 🙂
@thheller this is a really cool optimization, thanks for sharing!
but doesn’t it need to be recursive?
for something like this
(dom/div
{:style {:backgroundColor "red"}} ...)
or JSValue
already recursive?
JSValue is not recursive no. when did react add support for style objects? I didn't know it did. only ever used strings.
we’ve been using it for inline styles for quite a while 😅
shouldn’t be pretty straightforward to make a function that walks the data structure and wraps JSValue
where appropriate
or perhaps style is the only nested case?
i read the source for JSValue
and all i saw was (deftype JSValue [val])
how did you figure out what it did? trial and error?
I wrote shadow-cljs so I'm pretty familiar with the cljs.analyzer/compiler internals
oh nice
if you don’t mind me asking, why does shadow-cljs come with all this react/dom API stuff? i thought it was a build tool (with fancy npm integration) + code reloading
actually i see it has a bunch of other utilities, i’m guessing it’s just your “tool bag” of sorts
it doesn't. shadow is just a library I wrote for my stuff. since I suck at naming things I just use the shadow prefix for all my stuff.
hah i see
a lot of good stuff in here!
I use this for css btw 😉 https://github.com/thheller/shadow/wiki/shadow.markup
have you seen this?
how so? syntax sure, but hey both allow you to write style logic inline but both generate CSS to be inserted into the dom right?
perhaps i’m missing something
anyway shadow-cljs looks awesome, thanks for doing that! i look forward to learning more about it in the future :thumbsup:
I sort of compromised on one things because of react v16 which is really picky about arrays in arguments
for react v16 compat I generation a JS array and then call React.createElement.apply(nil, the-array)
and the compiler will then turn JSValue into plain JS instead of emitting a CLJS object (eg. map)
That makes sense. I had seen those before but kinda assumed they were for compiler internal use only
what I meant by string?
is that currently (dom/h1 "foo")
will not use the optimized path but should
Thanks, I think this will make a big difference in people's perceptions. That #js
thing is pretty annoying, as is peppering nil about as well. Like yours much better.
nice @thheller !! thanks for that approach, sounds awesome :)
Also have to make that all work with SSR, since this all has to evaluate in clj as well.
I personally lean that way as well, but many people have it as a required feature, at least for the top-level pages. Fulcro makes that pretty tractable, actually (as in I was surprised how easy it was to get it functioning when I wrote something non-trivial with it).
well, what happens if the user wants to use some react component? can't do that in CLJ?
Two approaches: you don't need it to "work" on the server, you just need it to "look ok", so a simple wrapper that outputs static content in clj is suffucient
I don't buy the whole SSR is faster argument either. every benchmark I saw complete disregarded load time on the server
@thheller what do you mean by structured data?
the google bot for this does not seem to register things that are added by javascript
but as a library author I don't want to limit my audience due to lack of a feature that is perceived as "necessary"
@tony.kay @thheller this guy's stuff is what convinced me SSR is an exceedingly good idea (i used to be of the 'just serve a <script> tag' group): https://rauchg.com/2014/7-principles-of-rich-web-applications#server-rendered-pages-are-not-optional
https://www.youtube.com/watch?v=Ar9R-CX217o i think this talk discusses it too
Thanks @sundarj. I agree that the speed is improved by SSR, by quite a bit in some cases, and my earlier recommend of using placeholders (shells in your article) for things that cannot be SSR’d is exactly the level of SSR I shoot for when doing it now.
The shell solution works for that as well.. What you’re trying to do is give the user a feeling that something is there. It’s more about perception. Usability isn’t improved.
and what I find most annoying is pages that look like they are finished but don't work because the JS hasn't finished yet
exactly. I just want to know that something is happening. seeing the empty page without anything happening is bad