-
Notifications
You must be signed in to change notification settings - Fork 27
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Explanation of tradeoffs compared to Reagent / Om, etc #44
Comments
Hi Julian, yes this is probably something that will be useful, but I'm not planning to do much "promotion" until 0.2.0 is released - hopefully this summer. Briefly, the pros and cons I would list are: For
Cons:
For
Not sure what the cons are... |
Nice work. Should pop this on the front page IMHO. Would freactive allow one to do iframe content-diffing between changing srcDoc text? (in other words, when my ratom that contains the srcDoc of my iFrame changes, it currently will rerender the entire thing, causing masses of img reloads... but a DOM-diffing (freactive.dom ?) would allow this not to be the case.) |
Another question - does freactive do atom-change updates automatically? Reagent is pretty fantastic at this, but it can get bogged down sometimes. |
Regarding srcDoc diffing, are you talking about diffing HTML text? |
@aaronc Kind of, but not really. I'm talking about loading an iFrame's srcdoc initially with HTML source text, the browser obviously then renders that into the actual DOM, but then subsequent updates being done via comparing the iFrame's DOM with the modified to-be-rendered VDOM (VDOM diffing). Does that make any sense to you? |
The reason I bring this up is that React and therefore Om & Reagent all have a problem where everything has to be wrapped... and this precludes doing things like this, amongst other things like "components" that return just text nodes, but if we use the actual DOM in freactive, it's possible to have a VDOM in an iFrame and do partial updates using "ordinary HTML" (such as my current project just happens to need). |
Okay, I think I understand... mostly. One of the long-term goals is to support server-side rendering in pure Clojure (no js-engine required), by interpreting freactive's syntax as a dialect of hiccup. Now there are some difficulties here. First of all, if we show the user the pre-rendered HTML, no events will be wired up. One pretty straight-forward solution is to overlay the UI with a translucent loading indicator until the virtual DOM gets wired up. To re-use the pre-rendered elements when freactive mounts is a little more difficult. We could diff against actual DOM elements via Does that make sense? Would this address your issue? |
What do you mean by "do atom-change updates automatically"? freactive will automatically bind to anything that implements |
Yeah, right now it just doesn't support |
re: "One of the long-term goals" Sorry I think I've led you up the garden path a bit. I just got excited with the per-element DOM updating idea, but I don't think this is really something beneficial to either of us. The below is what I was going to say, but I don't think it'll work. I'm being far too ambitious. :) ... Actually I have a different thing that I need to do in mind... my app is an HTML editor of sorts (editing happens in fragments of HTML), and as users make their changes, there's also a preview of those changes: an iFrame that is driven by a render function, which simply glues the correct model state together and is bound to the iFrame's srcDoc attr. On every keypress, the entire iFrame is re-rendered, which means all images are reloaded. I've experimented with doing delayed updates using a kind of slow debouncing algorithm, and even experimented with creating my own custom iFrame component that interpreted the HTML as React, in order to use the diffing. Trouble is, the HTML source (being edited) isn't under my program's direct control, it's under the control of a different user of the app. I hope this makes sense. My thought was because freagent is able to wrap ANY HTML element, it would be able to do efficient diffing within the iFrame... only changing the (usually text) portions that a user is editing, but, yes, if they were editing portions of javascript or CSS, that would cause some pretty serious issues... especially if the thing they were editing was itself a full MVC JS application. Not really sure how to get around this. Perhaps I'll just look to more efficient caching as a better way to do this. |
If you stick with browsers that support Element.attributes and On Mon, Jun 1, 2015 at 12:48 PM, JulianLeviston [email protected]
|
re: "Yeah, right now it just doesn't" - excellent. This project is great! Love where it's going. Interestingly, this project (and reagent) consistently highlight some of the issues there seem to be with Clojure(script) in terms of them being not lazy enough, or data-driven enough, and also with the way the browser functions right now. (live rewriting of an application on the fly from wtihin itself anyone? figwheel FTW, but compiler needs to be within the browser). Anyway I'm rambling. Sorry! As to my other issue, perhaps hipo can me help with its "live DOM node reconciliation" https://github.com/jeluard/hipo/ (ie VDOM diffing). Obviously, if the DOM node that is being manipulated is a script tag or somesuch, the entire page/frame would need to be reloaded. Ah I'll see how I go :) I'll close this now. Thanks very much for your time. This stuff is great. |
Is there any advantage to having DOM diffing at all? Unwanted re-renders can be avoided by minimizing the scope of The biggest advantage we've found with freactive is that bindings maintain the references to DOM nodes. This opens up the possibilities in working with 3rd-party libs without worrying about them playing nice with virtual DOM. We had a lot of headaches getting some Polymer elements to work correctly within virtual DOM. paper-dialog moves elements in the DOM to get "modal" overlay behavior, and the diff got confused. And we never did get the ACE editor to work correctly with vdom, but it was straightforward with freactive. |
In freactive's design diffing has always seemed to be the least important piece to me - it's what happens when all else fails to prevent unnecessary changes. I'm not sure there's no advantage to at all, but in an otherwise well-designed system you're right that diffing really wouldn't do that much. If a diffing algorithm is maintained, there would be a way to turn it off and I definitely wouldn't want it to interfere with using Polymer. In terms of features, I see management of keyed sequences of items being a much higher priority which would also eliminate a lot of use cases for diffing. Is this the virtual DOM lib that you're referring to: https://github.com/Matt-Esch/virtual-dom? I'm curious, where are the cases that you need to use |
I guess there might be cases where diff could be useful, but I have yet to run into them. I can contrive some examples, but the our common use-cases so far would be pretty well-served by some basic static analysis - just doing this by hand now. Part of the reason diff seems marginal might be that we're using HTML custom elements, and have them wired up so that they manage their own state and DOM subtree internally. The more likely case where we would encounter large pieces of DOM with small differences is going to be keyed sequences. We were using that https://github.com/Matt-Esch/virtual-dom, via our first attempt at web components: https://github.com/allgress/web-components. That turned out to be kind of a mess, trying to add features to deal with aspects of working with other "uncooperative" libraries, including a half-baked version of Elm-style FRP. Some of the issues we saw might have been handled using virtual-dom's "widgets" and/or other methods, but it felt like we had too many different fiddly knobs to turn already. Our second attempt is https://github.com/allgress/cereus, leveraging freactive. The library itself is considerably smaller, and the consensus on our team is that the resulting code is much cleaner. Most of our use of |
And using freactive and Polymer 1.0, I can't reproduce the race condition issue I saw before with text inputs, so that use of |
Cool, glad that use of |
Btw, I just pushed a new DOM implementation to freactive's |
Immediately hit this: Uncaught #ExceptionInfo{:message "Can't safely do manual DOM manipulation within the managed element tree. Please do manual DOM manipulation only on top-level managed elements.", :data {:managed-element #<[object HTMLElement]>}} I'll put together an isolated repro soon, but I think what's happening is I've got a parent custom element creating a child custom element. That occurs in the context of |
Yes, previously it would have been possible to have nested sub-trees that On Wed, Jun 3, 2015 at 6:00 PM, Dave Dixon [email protected] wrote:
|
I'm not sure it really is necessary to nest dom/mount!. The first implementation of Cereus used it to mount to the custom element shadow DOM. But I've not made shadow DOM optional - by default the view mounts to the custom element itself. I would still like Cereus to support the use-case of using custom elements directly from HTML. So I think I need to mount in this case, but if I can get some info about the context where the element is being attached, maybe I can conditionally call mount! when the parent is not managed by freactive. Is there a way to do that? The other thing I'll try now is to just defer the call to dom/mount! with js/setTimeout. |
I just added a managed? fn to freactive.dom. Nested manipulation may be On Wed, Jun 3, 2015 at 6:32 PM, Dave Dixon [email protected] wrote:
|
It isn't really "nested" manipulation per se. Rather I want to treat the sub-tree of a custom element in isolation, updated by the state atom owned by that element. The state in turn is updated via event-handlers from internal elements, or attribute changes from the outside world. My current solution when attaching a custom element is to create a "root" via |
Well there's nothing to prevent you from using different atoms in different By nesting mounts you risk that the child mount won't get disposed of On Wed, Jun 3, 2015 at 9:23 PM, Dave Dixon [email protected] wrote:
|
That's good info, thank you. I believe you're correct, and my approach would not have allowed the mount to be properly disposed. Web components have a standard set of lifecycle methods, so I think the right approach is to wire up the I don't know how you would handle shadow-DOM with a single mount. In full implementation of the (draft) web components standard like Chrome has, the shadow DOM is essentially hidden from the rest of the DOM, and is where you do the actual rendering for the component. The component can have "light DOM", which is what the user specifies as content, but the light DOM is really input for rendering. Example: <paper-button>
<span>Button</span>
</paper-button> The |
So there's nothing wrong with doing multiple mounts on a single page - nesting is the only issue and can probably be avoided with good planning. But if you need to nest you can do it - just make sure you |
Got this working fine. |
Cool... There's a possibility I may loosen some restrictions later down the road, but glad you have this working how it is. |
Okay, but that's definitely in the category of "nice to have". For browsers supporting shadow DOM, I'll just mount to the shadow root (haven't tested this yet, but can't see why it wouldn't work). Everybody else just gets an unmanaged container as a child of the managed custom element. That
serves as the mount point. The only very minor downside is that there's an extra element in the rendered DOM tree of the custom element, not a big deal.
Related question: what will happen when Polymer moves managed nodes around in the DOM? Cereus doesn't really support this yet (no use-cases in our current application), but at some point probably will need to do the same thing. |
How will Polymer be moving managed nodes around the DOM? freactive provides On Fri, Jun 5, 2015 at 2:21 PM, Dave Dixon [email protected] wrote:
|
Polymer 1.0 seems to have done away with one scenario, where For Polymer 1.0, when using "shady DOM", they move elements to emulate the light/shadow/composed DOM behavior of the web components spec. So markup like this: <paper-button>
<span>Submit</span>
</paper-button> winds up as this in the DOM: <paper-button role="button" tabindex="0" aria-disabled="false" class="x-scope paper-button-0" pressed="">
<paper-ripple class="style-scope paper-button" animating="">
<div id="background" class="style-scope paper-ripple" style="opacity: 0; background-color: rgb(0, 0, 0);"></div>
<div id="waves" class="style-scope paper-ripple"><div class="wave-container style-scope paper-ripple" style="top: -20.4296875px; left: 0px; width: 82.234375px; height: 82.234375px; -webkit-transform: translate(0.2578125px, 0.3125px); transform: translate3d(0.2578125px, 0.3125px, 0px);"><div class="wave style-scope paper-ripple" style="opacity: 0.25; -webkit-transform: scale(2.58437067390754, 2.58437067390754); transform: scale3d(2.58437067390754, 2.58437067390754, 1); background-color: rgb(0, 0, 0);"></div></div></div>
</paper-ripple>
<paper-material animated="" class="content style-scope paper-button x-scope paper-material-0" elevation="0">
<span>Submit</span>
</paper-material>
</paper-button> |
And Polymer uses either the Polymer.dom APIs (discussed in Issue #45) or the raw DOM APIs to actually manipulate the DOM. |
Let's continue this discussion in issue #45. |
More people will choose Freactive if they understand the tradeoffs of design choices and advantages / disadvantages of each compared to reagent, Om, etc.
The text was updated successfully, but these errors were encountered: