R
RUSTY YELLOW PAGES

wasm_lib

A workspace with a WebAssembly module and the library it calls, and a page that loads the module and runs it.


What it generates

  • <name>_wasm — a cdylib crate whose wasm-bindgen export converts between JavaScript's types and the library's
  • <name>_lib — a library crate holding one example method and the unit test for it
  • index.html — a page that imports the generated JavaScript and calls the export

Source: wasm_lib in the templates repository.

A WebAssembly module compiled from Rust has a boundary that only carries numbers, so anything richer has to be marshalled across it. wasm-bindgen generates that marshalling from an attribute, and the crate it generates it for is an adapter: it converts between JavaScript's types and the library's, and does nothing else.

The work therefore sits in a separate library crate, which the module crate depends on by path. That split is what lets cargo test run the tests on the host, in milliseconds, with no browser and no wasm target involved. A test of the binding itself would need wasm-bindgen-test and a headless browser; the adapter is kept thin enough that there is nothing in it worth testing that way.

The module crate declares crate-type = ["cdylib"] and nothing else. An rlib would be needed only if another Rust crate linked this one, or if it carried integration tests, which link a crate the way an outside dependant does. Unit tests inside src/ compile against a cdylib perfectly well.

Two prerequisites beyond cargo-generate, since this template targets wasm rather than the host: the wasm32-unknown-unknown target, added with rustup target add wasm32-unknown-unknown, and wasm-pack, installed with cargo install wasm-pack. The generated README repeats both.

wasm-pack build crates/<name>_wasm --target web --out-dir ../../pkg writes pkg/ at the project root — the .wasm, the JavaScript that loads it, and TypeScript definitions. The web target means no bundler and no Node: the index.html beside pkg/ imports the generated JavaScript directly and calls the export.

Serving that page is not optional. It loads an ES module, and the module fetches the .wasm next to it; opening the file from disk fails on both counts. Any local HTTP server will do.

One deliberate omission: the panic hook that turns a Rust panic into a readable console message is bound to console.error in eight lines rather than taken from console_error_panic_hook. That crate is the usual choice and is downloaded millions of times a month, but it has not been released since 2021 and sits in the archived rustwasm organisation. Binding it directly keeps the dependency list to wasm-bindgen alone.


One-time setup

Two commands, once per machine. cargo-generate is a subcommand of its own rather than part of cargo:

cargo install cargo-generate

Then file this repository under a name, so no command after it has to carry the URL. It writes $CARGO_HOME/cargo-generate.toml, creating the file if it is not there. The name is yours to pick; the commands here use ryp.

printf '[favorites.ryp]\ngit = "https://github.com/NGDeveloper125/rusty-yellow-pages-templates"\n' >> ~/.cargo/cargo-generate.toml

PowerShell

Add-Content "$HOME\.cargo\cargo-generate.toml" @('[favorites.ryp]', 'git = "https://github.com/NGDeveloper125/rusty-yellow-pages-templates"')

Generating it

Crate names default to the project name

cargo generate ryp wasm_lib --name pixel_tool

Or name either crate yourself

cargo generate ryp wasm_lib --name editor -d wasm_name=ui -d lib_name=core

Without that favourite, the repository goes in the command instead.

cargo generate --git https://github.com/NGDeveloper125/rusty-yellow-pages-templates wasm_lib --name pixel_tool