dotnet / dotnet/aspnetcore

Roadmap: First-class Web Components support for Razor components (or endorse JS Render API + helpers)

Open
#64,216 0 comments 0 reactions 0 assignees View on GitHub
area-blazor
Dominant language
C#
Stars
38.4k
Forks
10.9k
Avg merge
2d 10h
Merged PRs (30d)
281

Description

### Is there an existing issue for this?

- [x] I have searched the existing issues

### Is your feature request related to a problem? Please describe the problem.

We embed **Razor components** inside existing **Vue/React/Angular apps** (design-system widgets and micro-frontends). We see two paths:

**JS Render API** — RegisterForJavaScript(...) + Blazor.rootComponents.add(...) + dispose().
This is reliable, but every consumer must write glue (mount/update/dispose orchestration, event bridging, date/number normalization). Contracts vary team by team.

**Blazor Custom Elements** — attractive declarative contract, but currently experimental/unsupported and has gaps (e.g., no child content/templated components, unclear update semantics/events). This makes it risky as an enterprise boundary.

Result: teams either accept the risk of experimental CE or keep building bespoke wrappers on top of the JS API, leading to fragmentation and duplicated effort.

### Describe the solution you'd like

**Request A (preferred):** A clear roadmap to **graduate Blazor Custom Elements** from experimental to supported, with:

Support for **child content / templated components** (slot/RenderFragment mapping).

Documented **parameter update** semantics (properties vs attributes; rich object props update without re-add).

A standard **eventing model** (DOM CustomEvent with typed detail, bubbles+composed across Shadow DOM).

Explicit **lifecycle guarantees** (when instances are mounted/unmounted; disposal and cleanup).

Guidance for **RCL** assets (/_content/...) and script choice (blazor.webassembly.js / blazor.server.js vs blazor.web.js) for SPA embedding.

**Request B (if CE won’t be prioritized):** Explicitly endorse the JS Render API as the long-term contract and ship small official helpers to reduce glue:

**1. SPA Bridge SDK (JS/TS):**
```
await waitForBlazor();
const inst = await mount(el, "componentId", params); // Date→ISO handled
await update(inst || el, params); // live UpdateParams when available; else safe re-add
dispose(inst);
on(el, "my:event", (payload) => { ... }); // DOM CustomEvent conventions
```

- Normalizes Dates/numbers; attaches hostId; enforces bubbles+composed events; guards against concurrent mounts.

**2. Types & codegen:**

TypeScript typings for component parameters and event payloads (source from component metadata) to give strong types in host apps.

**3. Optional wrappers:**

Thin custom-element facade generator that uses the JS API under the hood (declarative for consumers, stable internals).

Tiny framework shims: Vue component, React wrapper, Angular directive — all built on the same bridge SDK.

**4. Docs & guidance:**

Update docs to present one endorsed path (JS API + helpers) with examples for micro-frontends and design systems, and clarify blazor.web.js readiness criteria.

**Acceptance criteria (either path):**

- A supported way to embed Razor components cross-framework with stable lifecycle, typed params, and rich events—without each team writing bespoke glue.
- Clear statement on long-term support (CE vs JS API) and capabilities scope.

### Additional context

**- Why now**: Many orgs are standardizing on Web Components for cross-framework reuse. Angular already binds CE props/events; React 19 improved CE interop; Vue plays nicely with DOM events. Razor components can participate—if Blazor provides a supported CE story or endorses the JS API with helpers.

**- Minimal repro / helper prototype (attached, see lower):**
A runnable sample demonstrating both patterns:

- JS Render API: mount a Razor component with a rich params object (date/bool/number/nested) and receive a rich payload back via CustomEvent.
- Custom Element facade: a thin wrapper that calls rootComponents.add(...) internally, exposing a clean declarative tag while retaining explicit dispose() control.

**Impact if unaddressed**: Teams continue to ship ad-hoc wrappers; inconsistent contracts; pressure to adopt experimental CE; slower adoption of Razor components in heterogeneous SPA estates.

**- What feedback would help you most:**
- Whether CE is intended to graduate (and rough timeframe).
- If not, confirmation that the JS Render API + official helpers is the long-term direction, so we can align internal standards and avoid bespoke solutions.

Please see: https://github.com/paulvanbladel/BlazorWebComponentsInteropDemo

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.