Skip to content

Production builds

Three steps, and they have to happen in this order:

Terminal window
cargo test # regenerate bindings/
wasm-pack build --target web --release
npm run build # your bundler

cargo test is what runs your TsFile export and your exporter’s #[ts(export)] tests. Skip it after changing a key enum and your TypeScript will describe the previous shape.

Only the key enums need it. Changing a runner body does not.

Use --dev while developing:

Terminal window
wasm-pack build --target web --dev

The difference is not only optimisation. Debug builds record where each reactive value was created, so a panic blames your line:

panicked at src/lib.rs:265:39:
called `Result::unwrap()` on an `Err` value: BorrowConflict

Release builds compile that tracking out. You get a smaller binary, and no source paths ship in your wasm.

That is worth knowing in both directions: debug builds are much easier to diagnose, and release builds do not leak your file layout to anyone who reads the binary.

A wasm panic tears down the module. The page has to be reloaded. There is no recovering the state.

So a panic in development is not a message you can dismiss. Fix it, reload, carry on.

The crate and the npm package share an ABI_VERSION, checked when the bridge starts.

[ahoi] bridge ABI mismatch: the wasm module speaks ABI v2,
but this JS bridge expects v1.
Align the `ahoi` crate and npm package versions.

It fails immediately and says what to do, rather than surfacing later as a confusing runtime error.

Practically: upgrade ahoi and @acheul/ahoi-js together. If you pin one, pin both.

A wasm module carries live state, so it cannot be swapped into a running page.

In Vite, force a full reload when your wiring module changes:

if (import.meta.hot) import.meta.hot.accept(() => import.meta.hot!.invalidate());

Without that you get a stale module and confusing behaviour after edits.

Note this is about the wasm side only. Your components hot-reload normally.

wasm-pack --release runs wasm-opt for you.

The bulk of a small ahoi module is the reactivity runtime plus whatever your own code pulls in. Serialisation is usually the biggest lever you control: a converter that moves less data across the boundary makes a smaller and faster module than one that moves whole structs.