microsoft / microsoft/webui

Support scoped static component asset emission

Open
#364 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement rust
Dominant language
Rust
Stars
90
Forks
23
Avg merge
13h 14m
Merged PRs (30d)
68

Description

## Summary

`webui::render_component_assets(protocol, roots, template)` currently renders static component assets from an already-built `WebUIProtocol`. That is a good API for the full build/CLI path, but it still requires a full `webui::build()` first: app entry parsing, full protocol construction, plugin artifact extraction, and protocol serialization inputs.

For dev/HMR and future bundler-plugin flows, we should support a scoped asset-emission path that compiles only the requested asset roots and their conservative dependency closure.

## Motivation

When a developer changes one lazy component, a watcher or bundler plugin should be able to re-emit that component's `.webui.js` asset without rebuilding the full app entry and unrelated protocol graph. This matters for:

- HMR latency in large apps with many templates.
- Bundler plugins that want to emit one changed root into the module graph.
- Lower memory use during watch mode by avoiding full protocol construction for unrelated fragments.

## Current behavior

PR #360 introduced static component assets. The full build path parses requested roots through synthetic non-entry fragments so the normal parser/plugin component compilation path runs, then removes the synthetic wrapper fragments before protocol serialization.

That proves the parser already has most of the mechanism needed for scoped roots, but today the public asset renderer still consumes a full protocol.

## Proposed direction

Add a build/compiler entry point that:

1. Registers app/external components using the existing discovery path.
2. Skips parsing the SSR entry file.
3. Parses only requested component asset roots through the existing synthetic-root/component compilation path.
4. Computes the same conservative closure used by `render_component_assets`.
5. Emits one or more `ComponentAssetFile`s without producing unrelated protocol fragments.

Possible API shapes:

```rust
pub fn build_component_assets(options: ComponentAssetBuildOptions) -> Result, WebUIError>;
```

or an incremental parser API that a bundler plugin can reuse:

```rust
HtmlParser::compile_component_asset_roots(&mut self, roots: &[String]) -> Result<...>;
```

## Constraints

- Preserve the same output shape as PR #360 (`webui-component-asset`, version 1, templates, templateStyles, templateFunctions).
- Preserve build-time validation: unknown roots, invalid tag names, missing plugin metadata, and filename collisions must fail before writing.
- Do not add recursion; closure walking should remain iterative.
- Avoid request-time `ProtocolIndex` / inventory filtering in this build-time path.
- Keep CSS/module/link behavior identical to the full build path.

## Acceptance criteria

- A caller can emit a static asset for one root without parsing the app entry template.
- Output bytes match the full-build asset output for the same root and build options.
- Tests cover nested component, ``, ``, attribute-template, and route-branch closure dependencies.
- Benchmarks or timing show improved latency for a one-root re-emit in a multi-component fixture.

Related: PR #360 review discussion.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading webui::render_component_assets, webui::build, and the existing synthetic-root/component compilation path described in PR #360; compare how the full protocol is constructed and how conservative closure walking works. Define and implement the scoped build/compiler entry point, then verify matching output, validation failures, closure cases, and improved one-root latency without parsing the SSR entry.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
build-system, devtools
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.