From a lot of Rust and WASM
WASM-PACK is optional.
WASM-Pack does a few things: 1) It compiles your code using wasm32-unknown-unknown, 2) It runs the wasm-bindgen cli (matching whatever version of wasm-bindgen you’re using) to generate JS glue 3) Lastly, it runs wasm-opt on the final webassembly
The reason that wasm-pack wasn’t the right fit for me was that I wanted to build multiple tightly coupled libraries and manage the output folder structure including removing the generated package.json. My setup consists of a cargo workspace with three crates: client, shared, and service-worker. Using a cargo workspace means that running cargo build from the top folder builds all three projects into a single target folder and generates a single cargo.lock file. Next step is to run wasm-bindgen-cli on those sources and output them to a folder named wasm. Lastly, I run wasm-opt on the finished wasm-modules. Installing the tools that wasm-pack runs automatically isn’t hard, just use
cargo install wasm-bindgen-cli and
go get -u github.com/gonowa/wasm-opt to install both tools (assuming you have Rust and Go installed). Compiling with
wasm32-unknown-unknown is fairly easy by setting the build target item in your .cargo config file. As you can see, I’m doing most of the same steps as wasm-pack, just slightly differently. I have a script which does these steps here.
WASM-Bindgen is pretty powerful.
WASM-Bindgen can handle pretty sophisticated interfaces. I mostly end up just passing Uint8Arrrays into and out of the wasm module because my projects consist mostly of crypto keys, strings, and images. Frankly, if I could return multiple values than I wouldn’t need a single interface type but since I can’t return tuples to / from JS, I did end up using a simple type to represent a js keypair with public and private key fields. Using js-sys I can dynamically cast to that type from a generic JsValue. The cast performs an instanceof check so if you’re not using classes than make sure your object works with instanceof. Because wasm-bindgen is pretty efficient with the whole in / out of wasm memory stuff I’ve fully switched to letting it manage the interfaces and no longer use pointers manually to pull in and our of the wasm instance’s memory.
Before I learned about
js_name I thought I wouldn’t be able to use wasm-bindgen because I needed to import some js to wasm, but js_name I can do just that.
For target web, changing js that is imported by module requires a recompile
Not a big deal, but it’s bitten me a few times. wasm-bindgen copies the code from the es6 modules that you import into the target directory when using the web target (I don’t use bundlers during development so if you do then you might not encounter this problem). This makes the paths easier but does mean that if you change the modules that you import from you’ll need to re-run wasm-bindgen.
no-modules is required for service-workers
It’s not ready or even working, but if you want to see a glob of code that spans a client and service worker feel free to look at my web3.0 project.