Closed kuraga closed 8 years ago
Ok, now I see readme of perf-spike branch, so another question:
Are there (global) differences unnoted there?
And does Inferno, on dynamic content, diff with real DOM or current DOM structures are converted to virtual DOM and then diffed?
Hi @kuraga, thanks for checking Inferno out. The key difference is that Inferno uses templates to represent fragments of virtual DOM. The virtual DOM gets pre-compiled once into a DOM static nodes and gets given instructions and a shape. It then uses these to make highly optimal passes to the DOM to create/update/remove the dynamic parts. It never needs to "diff" virtual DOM, it simply diffs the values that get passed into the fragment and mutates the DOM structure it already knows about.
I hope that explanation helped detail what goes on within the core of Inferno!
@trueadm , thanks very much for reply! But further: Suppose the whole tree is dynamic. There are variables in each attribute, every tag name is a variable and contents of tags are also variables :smile: Which scheme of updating do we have in this case, and are there differences from other libraries here?
@kuraga in the case that everything is dynamic, it would simply traverse through each shape in the tree and update each one, ensuring the changes are all carried out. This should be a very fast operation, still much faster than typical virtual DOM implementations as they still have to carry out a render
to work out what has changed. Inferno already knows what can change so simply does a ===
check on values and updates as necessary.
@trueadm ,
does a
===
check
Left operand is property of Fragment
object (e.g. {tag: 'li', attrs: { className: 'row' }, text: text}
, and right operand is property of HTMLElement
object, am I right?
@kuraga Sorry I'm a bit lost by that comment. Inferno will build a tree for the fragment {tag: 'li', attrs: { className: 'row' }, text: text}
. The tree will consist of shape(s) that are highly optimised objects that do very specific tasks to the DOM or of child shapes in the tree.
In the example given, it would know only to "diff" the text
value on that fragment, thus only touching the HTMLElement
and its Text
child object to change its nodeValue
.
@trueadm, I'm asking about what exactly does it compare with ===
.
simply does a
===
check on values and updates as necessary.
Can you point out a line of code of this check, please?
@kuraga it's done within the shapes, for example:
const nextValue = getValueWithIndex(nextItem, valueIndex);
if (nextValue !== getValueWithIndex(lastItem, valueIndex)) {
domNode.firstChild.nodeValue = nextValue;
}
@trueadm So, shape is compared with shape.
Thanks very much!
Last question: are there plans about unit tests?
Yes, there are plans for UTs although the ATs provide great coverage and feedback given the fact the API of Inferno is tiny.
On 18 Dec 2015, at 13:07, Alexander Kurakin notifications@github.com wrote:
So, shape is compared with shape.
Thanks very much!
Last question: are there plans about unit tests
— Reply to this email directly or view it on GitHub.
Thanks very much!
@kuraga No problem! Inferno has always been about three things:
1 have the absolute best performance in regards to manipulation of the DOM 2 keep a React like API, allowing for people to migrate projects to Inferno with little overhead 3 have the absolute best performance when handing server-side rendered text (Node)
We're still to build on point 3, and point 2 still has some coverage that needs expanding on (stateless components for example). In its current state, Inferno simply destroys every other framework out there in terms of performance (virtual DOM and non virtual DOM frameworks alike). I've managed to get performance almost 30% faster in the vdom benchmark compared to the older Inferno thanks to help from the author of Cito and his methods of template initialisation.
I see great things from Inferno in the future and I'd love to get more people contributing and adding ideas if you're interested.
@trueadm Big thanks for discussion.
I am just trying to create own minimalistic component-based library. So, immutable model as a dependency, DOM manipulation as a dependency, and Application class (with application loop) and Component class (immutable). See: RotorJS.
It uses virtual-dom. And I like virtual-dom interface but yesterday I opened VDOM Benchmark... And saw that virtual-dom conception isn't most optimized.
As I'm creating RotorJS just-for-fun-and-knowledges I'm interested of other conceptions. The fastest libraries are Inferno, Vidom and Snabbdom. Vidom's creator said that Vidom applies patches directly to DOM instead of "patch vDOM and then re-render the whole DOM using vDOM". As I see, Inferno does the same. Both of you have "some additional optimizations" :smile: but code is too hard to see all of them now.
By the way, which "tricks" have been taken from other libraries? So I'm interested of mechanisms and not real usage. And I'm a fan of conceptions "let's be compatible with standards but not other products", and "good interface and speed instead of simple entry point". So, I :smile: points 1 and 3 but :-1: point 2 :smile: And sure :+1: for 100%-coverage of unit-tests (by the way, it's a good documentation, too!)
I hope I'll understand you're mechanisms, and maybe transfer RotorJS to Inferno. Because I like very much 1) static-parts idea and 2) apply directly to DOM. Hope, there are some more techniques... (which have or would been taken from other libraries, too :smile:) And code will be stable! :smile:
The author of Cito and I have been working on ideas and concepts for a very long time. I've not taken much inspiration from else-where to be honest as I don't see too much value in what other people are doing in the virtual DOM scene (all attempting to solve the same "problem" even though the problem to begin with shouldn't have been one). I'll keep an eye on RotorJS, it looks promising.
In respect to my point 2, it's simple why I've done this. If Inferno didn't do this, it would add very little value to anyone. The realism is this: if it's not React or React-like, no one will use it. The adoption of React and the fact it's quickly becoming the most used frontend view/component library makes it very hard to beat, especially with Facebook backing it. So in my opinion, it's best to offer an API surface that matches people using React, rather than try and convince them that React's API is all wrong.
@trueadm regarding point 2, couldn't that be handled with another library such as "inferno-react"? React may be nothing in 1.5 years.
@stevenvachon whilst it's true, React might not be here in 1.5 years, I very much doubt that. React doesn't care about the DOM, it's more the fact it's addressed the hardest problem around, how to properly build componentized UIs regardless of their target endpoint (desktop, mobile, web etc). I don't see any other library coming remotely close to replacing React's principles.
I'm definitely behind a functional approach and using immutable data a single atomic store (i.e. Redux) to work with Inferno – as that's a very smart approach to complicated large scale applications. If people can simply do something like this (this won't work but it will give you an idea): import {Inferno as React} from 'inferno'
and their application gains an instant 10-20x performance boost, well that's a very compelling point indeed.
Yeah, agree with @trueadm ! Further-more I think (every) library should be as more modularized as possible... So, it's good idea to separate JSX (done), Ract-like features and DOM manipulate functions and component functions should (well, may) be in different libs...
@kuraga I like the idea of separating the DOM from the components, as React does with react-dom
. I just haven't seen it as a priority right now.
Well, you're really fast result and painstaking (as of count of good-stored TODOs in code) approach are more important, you're right! :smile:
@trueadm do you plan to have hyperscript [1] or jsonml [2] transpiler (probably augmented with any needed Inferno-isms) so that a dev can use those shortened formats to define templates rather than the long-form required by Inferno's createElement
?
i'm also wondering how a template compiled using createElement
rather than template strings can determine the immutability of any node without regenerating the template - i did not see any way to indicate node immutability in these cases. does it just fallback to typical vdom recreate-the-world & diff/patch?
[1] https://github.com/dominictarr/hyperscript [2] http://www.jsonml.org/
Inferno's Inferno.TemplateFactory.createElement
is simply a factory method that creates a object literal that looks like { tag: 'div', attrs: {}, children: [ ... ] }
. It would be very trivial to write your own that follows any other type of template out there, including hyperscript
. These all go inside Inferno templates
and works out what is dynamic or not by what is passed through as arguments.
const template = Inferno.createTemplate((val1, val2, val3) => ({tag: 'div', children: [val1, val2, val3]}));
Inferno.render(template('Value 1', 'Value 2', 'Value 3'), document.body);
So super easy to write and customise how you like, either at compile-time (for better performance) or run-time (no need for a transpiler/compiler).
ah i see. i think the missing piece in that scenario for me would be something like function argument reflection [1]. that way the template can be compiled once with getters/setters inserted in place of where the arguments are used in the func body so the diff can be done just on the passed args and the setters/DOM patch invoked where they differ.
@leeoniya if I'm not confusing your question, Inferno does this already. Templates are only compiled once. Each variable in the arguments represents a pointer to where the value exists in the arguments for the fragment.
no, no there's no question. just thinking out loud to grok the core idea and clarifying that it uses reflection to determine what parts of the func body are static (during compilation)
@leeoniya this works the exact same as before. You can't do things like this inside templates val1 + val2
or val1.map(...)
. Everything is literally based on pointers to values passed into the fragment. Exactly the same as how ES2015 template strings work.
got it, thanks!
btw, sorry for disappearing off gitter, i couldn't realistically help with my schedule and spend time troubleshooting the bunch of issues that came up with installing the build dependencies on Windows. Contributing wasn't as simple as "git clone, npm install, write js" :) Maybe i missed something.
I believe @Kflash fixed that with a new workflow, so you should be able to do that now on Windows! on the perf-spike
branch anyway. Which is in far better shape than the new-build
branch. Just getting test coverage up to 95%+.
@trueadm Do you have any sense of what the performance of perf-spike
is like versus master
(or what is on vdom-benchmark)?
In my testing, the new perk-spike
was about 30% faster than the last Inferno on the vdom-benchmark. :)
@trueadm ,
keep a React like API, allowing for people to migrate projects to Inferno with little overhead
vs
While the cito.vdom API is kept simple
What do you think? Not a good option?
Maybe we are mistaking different things, I was talking about the Component Lifecycle API. If we're talking about the general API, Inferno's API is vastly simpler than both React and Cito.
Inferno.render()
does everything you need, mounting, partial mounting and unmounting. Inferno.renderToString()
will do server-side rendering of strings (once complete) and Inferno.createTemplate()
will create your templates – that's all there is of the main API.
React's best API is its component API, i.e: componentDidMount
, componentWillUpdate
etc.
Hm... Yes. I'm interested about DOM manipulation :smile:
Can the diff algorithm be used for diffing "real" DOM nodes or is it tied to inferno's vdom implementation ?
@kapouer Inferno only diffs against Inferno's vdom nodes and tries to avoid touching the DOM where possible (for better performance). The only exception to this is where Inferno needs to hydrate the vdom against the real DOM (which is currently a WIP for 0.8).
I'm asking because there is no "perfect" solution for diffing real dom nodes using basic level1 api (nodeType, attributes, nodeName, childNodes). Morphdom is not right and diffDOM has subtle errors, hence the interest - but i don't want to take hostages about that :)
hi there can anyone help me how to use inferno js in php, i mean what must i do for make it working in php, i use inferno v1.0.0 beta 37, thanks before .
@trueadm Do you have any sense of what the performance of
perf-spike
is like versusmaster
(or what is on vdom-benchmark)?
This page seems not exists
@mcooder the benchmark was removed a while ago. This is a very old thread.
Good day!
Say please, what's the difference from virtual dom libraries making Inferno so fast? Say from virtual-dom...
Thanks.