tildeio / htmlbars

A variant of Handlebars that emits DOM and allows you to write helpers that manipulate live DOM nodes
MIT License
1.6k stars 193 forks source link

Implement Google's Incremental DOM #405

Closed adamzr closed 9 years ago

adamzr commented 9 years ago

Use Google's New Incremental DOM as the backend for rendering. This will allow using its patch function to make re-rendering more efficient.

mixonic commented 9 years ago

@adamzr "more efficient" seems to be a large assumption? Do you see a specific improvement that Incremental DOM brings to the HTMLBars rendering algorithm? It is new, and interesting. I'm not sure that means we should undertake a massive re-write to leverage it.

stefanpenner commented 9 years ago

A quick read, suggests this solves something Orthogonal (although appears to be a pretty cool piece of tech..

Some confusion may exist, let me try to quickly share: HTMLBars does not diff trees of DOM, or VDom (like react and friends). Instead it applies patches to the existing DOM. It does so after detecting changes in the streams of data the populate the dom.

If my interpretation is incorrect please provide further context, and we can reopen.

matthewrobb commented 9 years ago

I've followed HTMLBars pretty closely for a decently long time and I have also been following IncrementalDOM since it's announcement. I'm by no means an expert on either but I do believe that the methods used for applying changes to the DOM are very similar in nature between these two projects.

It's probably much too early but it seems reasonable at some future point that some commonalities could become a shared substrate.

wycats commented 9 years ago

@matthewrobb there is a lot in common between these two solutions, but there is something fundamentally different between the approaches.

Incremental DOM has an API that looks like this:

var IncrementalDOM = require('incremental-dom'),
    elementOpen = IncrementalDOM.elementOpen,
    elementClose = IncrementalDOM.elementClose,
    elementVoid = IncrementalDOM.elementVoid,
    text = IncrementalDOM.text;

function render(data) {
  elementVoid('input', '', [ 'type', 'text' ]);
  elementOpen('div', '', null);
    if (data.someCondition) {
      text(data.text);
    }
  elementClose('div');
}

When you run an operation (like elementVoid), if you are running the same operation as last time, it knows it doesn't have to do any work.

However, you still have to run the above code on every rerender (the incremental DOM strategy just makes it faster to determine what the changes are than the equivalent Virtual DOM code).

HTMLBars works differently. The compiler divides up the work between static areas and dynamic areas.

Let's consider the Handlebars equivalent of the incremental DOM example:

<input type="text">
<div>{{#if someCondition}}{{text}}{{/if}}</div>

For this template, we will get a template with two parts:

  1. buildFragment will build the <input>, <div>, and insert a placeholder for the {{#if}} and its child {{text}}.
  2. the rendering process describes how to fill in the placeholders.

On initial render, we run both (1) and (2). On re-renders, we only run (2). This means that re-renders do not even need to do the work Incremental DOM is doing to discover that the calls to elementVoid and elementOpen are the same as they were the first time.

The cool thing about both Virtual DOM and Incremental DOM is that they shrink the amount of work you need to do to discover "no work" dramatically from what you would naively expect. The latest optimizations in Babel are targeted at exactly this: how can we make the comparison as fast as possible.

In contrast, the strategy of HTMLBars/Glimmer is to not actually run any code related to the static parts on re-render. It may well turn out that a highly tuned Virtual DOM or Incremental DOM gets pretty close to that strategy, especially with a modern JIT, but I still prefer not to run any code (No code is faster than no code).

S-YOU commented 9 years ago

Thanks for the detailed explanations @wycats. Glad I subscribed repo. What technique do you use for placeholders, btw? comment nodes?

matthewrobb commented 9 years ago

@wycats Just curious couldn't it be possible to do that static analysis and produce code that builds the whole dom tree the first time through but skips the static parts there after? It seems like idom doesn't really PREVENT you from doing smaller patch operations on sub sections of a built tree.

stefanpenner commented 9 years ago

@matthewrobb unless I misread what you meant, that describes what htmlbars does.

mmun commented 9 years ago

@S-YOU Yes, primarily comment nodes with some empty text nodes sprinkled in.

S-YOU commented 9 years ago

Thanks for the info @mmun.

matthewrobb commented 9 years ago

@stefanpenner If that is the case (and if I am understanding the right way) then it seems like the primary difference between htmlbars and idom is that htmlbars incorporates a built in model for an efficient output target, correct?

wycats commented 9 years ago

htmlbars incorporates a built in model for an efficient output target, correct?

Can you say more about what you mean by this?

matthewrobb commented 9 years ago

I guess it just seems like considering idom a compile target you could output code that never tries to rerender the static portions of a template and instead does small patch operations on the dynamic portions for all subsequent changes. It seems like that efficiency all comes from the compiler and not from the runtime per se.

stefanpenner commented 9 years ago

@matthewrobb what you describe, if I understood you correctly, is what htmlbars does today.

stefanpenner commented 9 years ago

Also note, I am not implying there isn't something that can't be learned from idom. Rather the points raised are already competencies of htmlbars.

matthewrobb commented 9 years ago

@stefanpenner I'm sorry about the confusion. I was just trying to clarify my own understanding. It sounds like we're on the same page now.

My take away is that in theory idom could be just as efficient as htmlbars if compiled correctly (or I guess written by hand that way).

stefanpenner commented 9 years ago

Ah ok

atomictag commented 7 years ago

Although this is an old and closed thread, in case anybody is still interested I have just published incremental-bars, a library that allows to use incremental-dom with Handlebars templates.

You can check it out here.