JS Snippets
Often when developing a crate you want to run on the web you'll want to include
some JS code here and there. While js-sys
and
web-sys
cover many needs they don't cover
everything, so wasm-bindgen
supports the ability to write JS code next to your
Rust code and have it included in the final output artifact.
To include a local JS file, you'll use the #[wasm_bindgen(module)]
macro:
# #![allow(unused_variables)] #fn main() { #[wasm_bindgen(module = "/js/foo.js")] extern "C" { fn add(a: u32, b: u32) -> u32; } #}
This declaration indicates that all the functions contained in the extern
block are imported from the file /js/foo.js
, where the root is relative to the
crate root (where Cargo.toml
is located).
The /js/foo.js
file will make its way to the final output when wasm-bindgen
executes, so you can use the module
annotation in a library without having to
worry users of your library!
The JS file itself must be written with ES module syntax:
export function add(a, b) {
return a + b;
}
A full design of this feature can be found in RFC 6 as well if you're interested!
Using inline_js
In addition to module = "..."
if you're a macro author you also have the
ability to use the inline_js
attribute:
# #![allow(unused_variables)] #fn main() { #[wasm_bindgen(inline_js = "export function add(a, b) { return a + b; }")] extern "C" { fn add(a: u32, b: u32) -> u32; } #}
Using inline_js
indicates that the JS module is specified inline in the
attribute itself, and no files are loaded from the filesystem. They have the
same limitations and caveats as when using module
, but can sometimes be easier
to generate for macros themselves. It's not recommended for hand-written code to
make use of inline_js
but instead to leverage module
where possible.
Caveats
While quite useful local JS snippets currently suffer from a few caveats which are important to be aware of. Many of these are temporary though!
-
Currently
import
statements are not supported in the JS file. This is a restriction we may lift in the future once we settle on a good way to support this. For now, though, js snippets must be standalone modules and can't import from anything else. -
Only
--target web
and the default bundler output mode are supported. To support--target nodejs
we'd need to translate ES module syntax to CommonJS (this is planned to be done, just hasn't been done yet). Additionally to support--target no-modules
we'd have to similarly translate from ES modules to something else. -
Paths in
module = "..."
must currently start with/
, or be rooted at the crate root. It is intended to eventually support relative paths like./
and../
, but it's currently believed that this requires more support in the Rustproc_macro
crate.
As above, more detail about caveats can be found in RFC 6.