Skip to content

Commit 8dbdc8f

Browse files
Split WASM parser and handler bundles (#344)
1 parent 35071bf commit 8dbdc8f

17 files changed

Lines changed: 889 additions & 544 deletions

File tree

.github/actions/setup-wasm/action.yml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ runs:
2626
- name: Verify WASM output
2727
shell: bash
2828
run: |
29-
test -f docs/.webui-press/public/wasm/webui_wasm_bg.wasm
30-
test -f docs/.webui-press/public/wasm/webui_wasm.js
31-
! grep -q "from 'env'" docs/.webui-press/public/wasm/webui_wasm.js
29+
for variant in all handler parser; do
30+
test -f "docs/.webui-press/public/wasm/${variant}/webui_wasm_${variant}_bg.wasm"
31+
test -f "docs/.webui-press/public/wasm/${variant}/webui_wasm_${variant}.js"
32+
! grep -q "from 'env'" "docs/.webui-press/public/wasm/${variant}/webui_wasm_${variant}.js"
33+
done

.github/workflows/publish.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,6 @@ jobs:
246246
publish/npm/*
247247
publish/nuget/*
248248
publish/crates/*
249-
publish/wasm/*
249+
publish/wasm/**/*
250250
env:
251251
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ prost = "0.14.3"
3535
napi = { version = "3.8.5", features = ["napi4"] }
3636
napi-derive = "3.5.4"
3737
wasm-bindgen = "=0.2.100"
38+
js-sys = "0.3.77"
3839
serde-wasm-bindgen = "0.6"
3940
actix-web = "4.11.0"
4041
rustls = "0.23.39"

DESIGN.md

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1476,16 +1476,39 @@ webui-cli ──────► webui (library) ◄────── webui-node
14761476
├── webui-protocol └── serde_json
14771477
└── webui-discovery
14781478
1479-
webui-ffi ──────► webui-handler ◄────── webui-wasm
1480-
webui-parser webui-parser
1481-
webui-protocol webui-protocol
1479+
webui-ffi ──────► webui-handler ◄────── webui-wasm (handler feature)
1480+
webui-parser ┌──── webui-wasm (parser feature)
1481+
webui-protocol └──── webui-wasm (all/default feature)
14821482
```
14831483

14841484
The `webui` library crate is the primary API surface for programmatic use.
14851485
It re-exports `WebUIHandler`, `ResponseWriter`, and `WebUIProtocol` from their
14861486
respective crates and provides `build()`, `build_to_disk()`, and `inspect()`
14871487
functions with `BuildStats` (duration, fragment/component/CSS counts, protocol size).
14881488

1489+
### WASM Distribution
1490+
1491+
The `microsoft-webui-wasm` crate exposes feature-gated browser bindings so
1492+
consumers only ship the parser and/or handler code they need:
1493+
1494+
- `handler` builds `webui_wasm_handler.js` and exports `render`,
1495+
`render_partial`, `protocol_tokens`, and `render_component_templates`. It
1496+
accepts protobuf protocol bytes and depends on `webui-handler` and
1497+
`webui-protocol`, not `webui-parser`. `render(protocolBytes, stateJson,
1498+
onChunk, options)` uses the same `ResponseWriter` callback shape as the
1499+
Node binding: each handler write calls `onChunk(html)`, while callers that
1500+
need a full string concatenate chunks in JavaScript.
1501+
- `parser` builds `webui_wasm_parser.js` and exports `build_protocol`. It
1502+
returns protobuf protocol bytes and depends on `webui-parser` and
1503+
`webui-protocol`, not `webui-handler`.
1504+
- `all` is the default feature, builds `webui_wasm_all.js`, and exports the
1505+
parser plus handler surfaces for playground-style live preview. Callers
1506+
compose `build_protocol()` and callback-based `render()` explicitly.
1507+
1508+
`cargo xtask build-wasm` builds all three variants into
1509+
`docs/.webui-press/public/wasm/{all,handler,parser}/` with stable `wasm-pack`
1510+
output names.
1511+
14891512
### npm Distribution
14901513

14911514
The `@microsoft/webui` npm package follows the esbuild single-package model:

crates/webui-wasm/Cargo.toml

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,19 @@ wasm-opt = false
1818
name = "webui_wasm"
1919
crate-type = ["cdylib", "rlib"]
2020

21+
[features]
22+
default = ["all"]
23+
all = ["handler", "parser"]
24+
handler = ["dep:microsoft-webui-handler"]
25+
parser = ["dep:microsoft-webui-parser"]
26+
2127
[dependencies]
22-
microsoft-webui-parser = { path = "../webui-parser", version = "0.0.15", default-features = false }
23-
microsoft-webui-handler = { path = "../webui-handler", version = "0.0.15" }
28+
microsoft-webui-parser = { path = "../webui-parser", version = "0.0.15", default-features = false, optional = true }
29+
microsoft-webui-handler = { path = "../webui-handler", version = "0.0.15", optional = true }
2430
microsoft-webui-protocol = { path = "../webui-protocol", version = "0.0.15" }
2531
serde_json = { workspace = true }
2632
wasm-bindgen = { workspace = true }
33+
js-sys = { workspace = true }
2734
serde-wasm-bindgen = { workspace = true }
2835
thiserror = { workspace = true }
2936

crates/webui-wasm/README.md

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,31 @@
11
# microsoft-webui-wasm
22

3-
WebAssembly bindings for the [WebUI](https://github.com/microsoft/webui) framework, built with `wasm-bindgen`. Powers the online WebUI playground.
3+
WebAssembly bindings for the [WebUI](https://github.com/microsoft/webui) framework, built with `wasm-bindgen`.
44

55
## Overview
66

7-
`microsoft-webui-wasm` exposes WebUI's parser and handler to the browser via a WASM module, enabling live template preview without a server.
7+
`microsoft-webui-wasm` can be built as three browser bundles:
8+
9+
| Feature | Bundle | Exports |
10+
|---------|--------|---------|
11+
| `handler` | `webui_wasm_handler.js` | `render`, `render_partial`, `protocol_tokens`, `render_component_templates` |
12+
| `parser` | `webui_wasm_parser.js` | `build_protocol` |
13+
| `all` | `webui_wasm_all.js` | Parser and handler exports |
14+
15+
The default feature is `all`, which powers the online playground. Consumers that only need to render prebuilt protobuf protocol bytes should use the handler bundle to avoid shipping parser code.
16+
17+
## Building
18+
19+
```bash
20+
cargo xtask build-wasm
21+
```
22+
23+
This writes the three generated bundles under `docs/.webui-press/public/wasm/`.
824

925
## Documentation
1026

1127
See the [WebUI repository](https://github.com/microsoft/webui) for full usage guides and examples.
1228

1329
## License
1430

15-
MIT Copyright (c) Microsoft Corporation.
31+
MIT - Copyright (c) Microsoft Corporation.

crates/webui-wasm/src/error.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT license.
3+
4+
//! Shared WASM binding errors.
5+
6+
/// Error type used by the WASM binding layer.
7+
#[derive(Debug, thiserror::Error)]
8+
pub(crate) enum WasmError {
9+
/// Requested entry file was not present in the virtual file map.
10+
#[cfg(feature = "parser")]
11+
#[error("Entry file '{0}' not found")]
12+
MissingEntry(String),
13+
14+
/// Template parsing or authoring validation failed.
15+
#[cfg(feature = "parser")]
16+
#[error("{0}")]
17+
Parse(#[from] webui_parser::ParserError),
18+
19+
/// Protocol protobuf bytes could not be decoded or encoded.
20+
#[error("Protocol error: {0}")]
21+
Protocol(#[from] webui_protocol::ProtocolError),
22+
23+
/// State JSON could not be decoded.
24+
#[cfg(feature = "handler")]
25+
#[error("State JSON error: {0}")]
26+
State(serde_json::Error),
27+
28+
/// Rendering failed.
29+
#[cfg(feature = "handler")]
30+
#[error("{0}")]
31+
Render(#[from] webui_handler::HandlerError),
32+
33+
/// A requested handler plugin name is not supported.
34+
#[cfg(feature = "handler")]
35+
#[error("Unknown plugin: {0}. Use \"webui\", \"fast-v3\", \"fast-v2\", or \"fast\".")]
36+
UnknownPlugin(String),
37+
38+
/// The JavaScript render options object was invalid.
39+
#[cfg(feature = "handler")]
40+
#[error("Invalid render options: {0}")]
41+
InvalidOptions(String),
42+
}

0 commit comments

Comments
 (0)