[WICG/webcomponents] [dom-parts] Declarative API for defining DOM parts (Issue #990)

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

One thing that seems lacking is the ability to declaratively create DOM parts with some type of HTML instruction or node that the parser processes and exposes via an imperative JavaScript API to the page.

# Use Cases

## Hydration

Server side rendered code that undergoes some type of hydration soon after the page loads is becoming more popular in external frameworks and being added to formerly client-side rendering frameworks like React. Other frameworks like Qwik are entirely based around the idea of server-side rendering first and then hydrating on demand.

Most of these frameworks do some type of DOM query or walk to locate nodes that need to be hydrated. DOM parts, if they could be generated declaratively, could speed up these operations by caching nodes that the page will likely need to visit later.

## Templates

Using `<template>` fragments is a good way to avoid repeatedly parsing the same piece of DOM, and can be used to update pieces of the page as well. When using `<template>` fragments for rendering, the `<template>` typically needs to be updated immediately after clone for anything that isn't statically defined. To do this, frameworks walk the `DocumentFragment` looking for placeholder attributes and comments. DOM parts could remove the need for this walk by parsing instructions in the `<template>` and storing those nodes.

# Requirements

1. Doesn't affect rendering
2. Doesn't affect tree hierarchy
3. Fast to find

# Proposal

Processing instructions provide one mechanism of adding content to the HTML that does not affect rendering or tree hierarchy but is available to the parser.

```html
<html>
  <section>
    <h1 id="name"><?child-node-part?><?/child-node-part?></h1>
    Email:
    <?node-part metadata?><a id="link"></a>
  </section>
</html>
```

Here's one example drawn from [a recent proposal](https://github.com/tbondwilkinson/dom-parts) based on DOM parts. 

- `<?node-part?>` would create a `NodePart` attached to the next sibling node.
- `<?child-node-part?>` would mark the start of a `ChildNodePart` range and `<?/child-node-part?>` would mark the end of the range.

Anything after the processing instruction identifier would be parsed as `metadata`.

There would need to be some imperative API for retrieving these parts.

```ts
interface PartRoot {
  // In-order DOM array of parts.
  getParts(): Part[];
}

interface DocumentPart implements PartRoot {
  getParts(): Part[];
}

declare global {
  interface Document {
    getDocumentPart(): DocumentPart;
  }

  interface DocumentFragment {
    getDocumentPart(): DocumentPart;
  }
```

This API would add a new `DocumentPart` that is retrievable from a `Document` or `DocumentFragment` and has a `getParts()` method that returns the parts parsed from the DOM.

-- 
Reply to this email directly or view it on GitHub:
https://github.com/WICG/webcomponents/issues/990
You are receiving this because you are subscribed to this thread.

Message ID: <WICG/webcomponents/issues/990@github.com>

Received on Tuesday, 21 March 2023 18:55:00 UTC