Skip to content

Commit bbfa3bd

Browse files
feat: add Node.js napi-rs binding and Express integration
Uses napi-rs over FFI or WASM because it compiles Rust directly into a native .node addon, bypassing the C ABI entirely (JS↔Rust vs JS→C→Rust→C→JS). Buffer for protocol data is zero-copy from V8 backing store. No manual memory management (V8 ref-counting vs webui_free()). WASM exists already for browser/universal use but is ~1.5-3x slower than native for CPU-bound rendering. Add webui-node crate that compiles the WebUI handler into a native Node.js addon via napi-rs, exposing a render(html, dataJson) function. Add Express integration example at examples/integration/node-express following the same patterns as hyper and tiny_http (--app CLI arg, routes for /, /assets/*, /hmr, file watcher for HMR). - New crate: crates/webui-node (napi-rs cdylib with 10 unit tests) - New integration: examples/integration/node-express (ESM, Express 5) - Add napi/napi-derive/napi-build to workspace dependencies - Add ISC license to deny.toml allowlist (napi transitive dep) - Add node-express to xtask INTEGRATION_BUILDS - Update DESIGN.md and README.md Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 7a9e663 commit bbfa3bd

18 files changed

Lines changed: 1690 additions & 2 deletions

File tree

Cargo.lock

Lines changed: 235 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ members = [
44
"crates/webui-expressions",
55
"crates/webui-ffi",
66
"crates/webui-handler",
7+
"crates/webui-node",
78
"crates/webui-parser",
89
"crates/webui-protocol",
910
"crates/webui-state",
@@ -31,6 +32,8 @@ tokio = { version = "1.49.0", features = ["full"] }
3132
clap = { version = "4", features = ["derive"] }
3233
console = "0.15"
3334
prost = "0.13"
35+
napi = { version = "3", features = ["napi4"] }
36+
napi-derive = "3"
3437
wasm-bindgen = "0.2"
3538
serde-wasm-bindgen = "0.6"
3639

@@ -42,6 +45,7 @@ tokio-test = "0.4.5"
4245

4346
# Build dependencies
4447
prost-build = "0.13"
48+
napi-build = "2"
4549

4650
[profile.release]
4751
lto = true

DESIGN.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,7 @@ webui/
477477
│ ├── webui-expressions/ # Expression evaluation engine
478478
│ ├── webui-ffi/ # C-compatible FFI bindings
479479
│ ├── webui-handler/ # Protocol handler implementation
480+
│ ├── webui-node/ # Node.js native addon (napi-rs)
480481
│ ├── webui-parser/ # HTML/CSS/template parser
481482
│ ├── webui-protocol/ # Protocol definition
482483
│ ├── webui-state/ # State management

README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,24 @@ The interactive playground runs WebUI in the browser via WebAssembly. The WASM o
8080
cargo xtask build-wasm
8181
```
8282

83+
### Integration Examples
84+
85+
The `examples/integration/` directory contains ready-to-run server examples:
86+
87+
```bash
88+
# Run with Rust + hyper (async, HTTP/1.1 + HTTP/2)
89+
cargo xtask run hyper hello-world
90+
91+
# Run with Rust + tiny_http (synchronous, lightweight)
92+
cargo xtask run tiny_http hello-world
93+
94+
# Run with Node.js + Express (napi-rs native addon)
95+
cargo build -p webui-node
96+
cd examples/integration/node-express && npm ci && node src/index.js --app hello-world
97+
```
98+
99+
Each integration serves the app on `http://127.0.0.1:8080/` with hot-reload file watching.
100+
83101
## Contributing
84102

85103
This project welcomes contributions and suggestions. Most contributions require you to agree to a

crates/webui-node/Cargo.toml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
[package]
2+
name = "webui-node"
3+
description = "Node.js native addon for WebUI framework via napi-rs"
4+
version.workspace = true
5+
edition.workspace = true
6+
authors.workspace = true
7+
license.workspace = true
8+
repository.workspace = true
9+
10+
[lib]
11+
crate-type = ["cdylib"]
12+
13+
[dependencies]
14+
napi = { workspace = true }
15+
napi-derive = { workspace = true }
16+
webui-parser = { path = "../webui-parser", default-features = false }
17+
webui-handler = { path = "../webui-handler" }
18+
webui-protocol = { path = "../webui-protocol" }
19+
serde_json = { workspace = true }
20+
21+
[build-dependencies]
22+
napi-build = { workspace = true }
23+
24+
[dev-dependencies]
25+
webui-test-utils = { path = "../webui-test-utils" }

0 commit comments

Comments
 (0)