WICG / webcomponents

Web Components specifications
Other
4.38k stars 374 forks source link

[dom-parts] Tree structure of parts in the DOM #992

Open tbondwilkinson opened 1 year ago

tbondwilkinson commented 1 year ago

@justinfagnani @mfreed7 @sorvell @kevinpschaaf and a few folks from Angular have been thinking about the DOM parts API fresh.

In the current DOM parts proposal, there's no concept of being able to walk a "tree" of parts in the DOM. Because users create part objects, they're mostly used as an update mechanism rather than a structural mechanism.

Considered with #990, if DOM parts are something that is attached to the DOM and can be constructed by the browser, it makes sense to propose that parts should also form a tree structure and each part should have a parent and children.

Updating a subtree of the DOM

If the only place to get parts for the document is to call getParts() on the DocumentPart, it's much more difficult to do a partial render update for only a portion of the subtree. If a ChildNodePart has a getParts() method, it's easier for that portion of the tree to be walked and updated independently. Most frameworks do not walk the entire document on every update, and allow partial rendering and skipping rendering for subtrees.

Nested templates

This becomes even more important for templating approaches that can be nested.

<html>
  <?node-part classes>
  <div id="parent">
    <?node-part src?>
    <div id="icon">
    </div>
    <?child-node-part content?>
    <div>
      Pre-content
     <?child-node-part greeting?>
     <span>Hello there, <?child-node-part name/?><span>
     <?/child-node-part?>
     Post-content
    </div>
    <?/child-node-part?>
  </div>
</html>

This might be HTML generated for template with nesting

function page(name: JSX.Element, src: string) {
  const greeting = <span>Hello there, {name}</span>;
  const content = <div>Pre-content {greeting} Post-content</div>;
  const html = (
      <html>
        <div id="icon" src={src}><div>
        <div id="parent" {classes}>
          {content}
        </div>
      </html>);
}

If ChildNodePart can also be a PartRoot with a getParts() method, then each nested <template> can be the part container for its parts and can be walked independently of the rest of the DOM.

For more about how this fits into a broader DOM parts proposal, see this new proposal based on DOM parts

keithamus commented 1 year ago

WCCG had their spring F2F in which this was discussed. Present members of WCCG identified an action item to take the topic of DOM Parts and break it out into extended discussions. You can read the full notes of the discussion (https://github.com/WICG/webcomponents/issues/978#issuecomment-1516897276) in which this was discussed, heading entitled "DOM Parts API".

As this issue pertains to DOM parts, I'd like to call out that https://github.com/WICG/webcomponents/issues/999 has been raised for extended discussions and this topic may be discussed during those sessions.

rektide commented 1 year ago

ServiceWorker had a longstanding issue requesting a DOM in w3c/ServiceWorker#846. The issue was closed with a similar note to what's happening here, saying ServiceWorkers wasnt the right forum for the spec, and pointing out that DOM has a lot of rendering-related capabilities (like getclientrects) that would need to be nulled out for success, and referring the issue to https://github.com/whatwg/dom for follow-up.

I don't think that follow-up ever happened with Service Worker folk. Has any follow-up happened in this group? This seems like a hot-potato, cross-sectional issue for the w3c but seems to keep being dropped.

sashafirsov commented 1 year ago

From prospective of the frameworks needs, the traversal is just a part of more general solution: the DOM with template render results merging.

Browser would perform this operation way more efficient then JS as has ability to use threads on simultaneous DOM sub-trees inspection. Of course if exposed to JS API would have async nature.

As the detached DOM just have to follow the Node interface, the data layer for it could be served by wrapper from the POJO HTML presentation, virtual DOM, XML, etc.

Going further, as the data to detached DOM transformation can be a streaming/ multithreaded process, the API can be exposed as the template engine method which instead of rendering own result would merge the results into live DOM.

🤔 Perhaps it worth to propose the API for merging the alive DOM with detached one?