First of all, this is a normal Rust binary project. So normal cargo commands apply:
cargo check
cargo clippy
cargo build
cargo test
Moreoever, the major purpose of this project is to provide a WebAssembly (wasm) binding for Apache DataFusion. To build the WASM binary, we need a few more tools:
wasm-pack
: a convenient tool for building, testing, packaging and releasing Rust WASM projects.wasm-opt
(optional) optimizeswasm
binary to reduce the size. Normallywasm-pack
will download this tool for you, but at present it is (not working properly)[rustwasm/wasm-pack#1378]. So you may need to install it manually.- browsers (optional) to test the WASM binary in a headless browser.
Command to install them:
cargo install wasm-pack
cargo install wasm-opt
To build the WASM binary, run:
wasm-pack build --target web
This will generate a pkg
directory containing the WASM binary and a JavaScript wrapper. You can use it as a npm package. The --target web
specifies that the WASM binary is for web usage (inside browser), other options like nodejs
or deno
also exist if you want to use it in other environments.
Unlike normal Rust projects, this project is not suited to be published to crates.io, but npmjs.org instead. To publish a release, you need to:
- Check if everything is well tested and documented.
- Bump the version in
Cargo.toml
- Run
wasm-pack build --target web
to generate the WASM binary - Run
wasm-pack publish
to publish the package to npmjs.org
All the APIs exposed to JavaScript need to be annotated #[wasm_bindgen]
. For example, the core entry point is defined as follows
#[wasm_bindgen]
pub struct DataFusionContext {
// omitted...
}
To log into stdout, use whatever you are familiar with like in other normal Rust libraries. And to log into JavaScript web console, use crate::console::log
, which is a FFI bridged function to console.log
in JavaScript:
console::log("Hey");
Your logic might panic in some cases, when this happens across FFI boundry it would become hard to trace down. Hence we add a special panic hook in lib.rs
which will (ideally) log the panic stack into JavaScript console. Please file an issue if you find it not working.
The WASM target is very strict on aspects that we may not aware of usually. Like, it doesn't allow multi-threading, it requires futures to be Send
, etc. So we need to carefully writing our code, as well as choosing deps. It's hard to avoid using some third-party code that would run into this kind of issue. Here are some tips that might help when it happens:
- Disable unnecessary features whenever possible. Some deps have default features that are not necessary for our project. For example,
opendal
will enable tokio runtime by default and fail to compile in WASM target. We can disable it by specifyingdefault-features = false
inCargo.toml
. - Use
cargo tree
to find out which dep is causing the issue. The Rust/Cargo dep-resolver will, unfortunately, "infect" the whole project with the same feature settings, even the code is not used. E.g.: the default tokio feature fromopendal
will enablert
feature intokio
, and causes all occurrences oftokio
in the dep tree are affected. In this case we can usecargo tree -i tokio -e features
to inspect who is usingtokio
with unexpected features enabled. - Check compile issues frequently with
wasm-pack build --target web --no-opt
, especially when you are adding new deps or features. The--no-opt
flag will disable wasm-opt, which will take lots of time.