[WICG/webcomponents] Streaming DSD (Issue #1123)

henrijoss created an issue (WICG/webcomponents#1123)

# Streaming DSD

When a server-rendered web component using Declarative Shadow DOM (DSD) is streamed to the browser, the HTML parser invokes the custom element constructor **synchronously** as soon as it encounters the host element’s start tag. This happens *before* the parser processes the element’s children, including the `<template shadowrootmode="...">`.

At the moment, there doesn’t appear to be a straightforward way to detect when the HTML parser has finished processing (or “upgrading”) that `<template>`.

[Minimal reproduction example](https://stackblitz.com/edit/stackblitz-starters-zarcmxih?file=index.html)

The console shows the error:

> A second declarative shadow root cannot be created on a host.

## What’s happening

By the time the parser reaches the `<template shadowrootmode>`, the component’s JavaScript has already been registered and its constructor has run. If the constructor calls `attachShadow()`, the parser’s later attempt to attach the declarative shadow root fails.

This is due to the order of execution:

- The constructor runs immediately when the host element’s start tag is parsed.
- At that point:
  - The element is **not yet connected** to the DOM.
  - Its **children have not been parsed**.
  - Its **attributes may not yet be fully available**.

As a result, the element appears effectively “empty,” making it unreliable to inspect or act on at this stage.

## Current solution

A practical workaround is to defer the `attachShadow()` call to `connectedCallback`. At this point:

- The element is attached to the DOM.
- Its attributes can be read reliably.

Although the HTML parser may still be processing child nodes, this is usually sufficient to determine whether the component is:

- **Hydrating server-rendered output**, or  
- **Falling back to client-side rendering**

If we are in the server rendered case we can decide:

- If a `shadowRoot` already exists, the parser has finished processing the `<template>`, and execution can continue normally.
- If no `shadowRoot` exists yet, the component must wait until parsing completes.

One way to handle this is by using a `MutationObserver` to detect when the shadow root becomes available. In a real-world scenario, you might also wait for a higher-level signal (e.g. a streaming completion marker) before proceeding with hydration.

---

**Question:**  
Am I missing something, or is there currently no reliable way to detect when the HTML parser has finished processing the `<template shadowrootmode>` in a streaming scenario?

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

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

Received on Tuesday, 28 April 2026 11:34:33 UTC