wasm-bindgen
Facilitating high-level interactions between Wasm modules and JavaScript
Top Related Projects
📦✨ your favorite rust -> wasm workflow tool!
Emscripten: An LLVM-to-WebAssembly Compiler
A lightweight WebAssembly runtime that is fast, secure, and standards-compliant
🚀 Fast, secure, lightweight containers based on WebAssembly
A TypeScript-like language for WebAssembly.
The WebAssembly Binary Toolkit
Quick Overview
wasm-bindgen is a project that facilitates high-level interactions between Wasm modules and JavaScript. It allows developers to import JavaScript functionality into Rust and export Rust functionality to JavaScript, making it easier to use Rust-generated WebAssembly modules in web applications.
Pros
- Seamless integration between Rust and JavaScript
- Automatic generation of TypeScript definitions
- Support for complex data types and async functions
- Reduces boilerplate code for Wasm/JS interoperability
Cons
- Learning curve for developers new to Rust or WebAssembly
- Potential performance overhead for certain operations
- Limited support for some advanced JavaScript features
- Dependency on external tools and build processes
Code Examples
- Exporting a Rust function to JavaScript:
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
- Importing a JavaScript function into Rust:
#[wasm_bindgen]
extern "C" {
fn alert(s: &str);
}
#[wasm_bindgen]
pub fn greet(name: &str) {
alert(&format!("Hello, {}!", name));
}
- Working with complex types:
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub struct Point {
x: f64,
y: f64,
}
#[wasm_bindgen]
impl Point {
pub fn new(x: f64, y: f64) -> Point {
Point { x, y }
}
pub fn distance(&self, other: &Point) -> f64 {
let dx = self.x - other.x;
let dy = self.y - other.y;
(dx * dx + dy * dy).sqrt()
}
}
Getting Started
-
Add wasm-bindgen to your Cargo.toml:
[dependencies] wasm-bindgen = "0.2"
-
Use the
#[wasm_bindgen]
attribute on functions and structs you want to expose to JavaScript. -
Build your project with:
wasm-pack build --target web
-
Import and use your Wasm module in JavaScript:
import init, { add, greet, Point } from './pkg/your_project.js'; async function run() { await init(); console.log(add(2, 3)); greet("World"); const p1 = Point.new(0, 0); const p2 = Point.new(3, 4); console.log(p1.distance(p2)); } run();
Competitor Comparisons
📦✨ your favorite rust -> wasm workflow tool!
Pros of wasm-pack
- Provides a complete toolchain for building and publishing Rust-generated WebAssembly
- Simplifies the process of creating npm packages from Rust code
- Includes built-in testing and documentation generation features
Cons of wasm-pack
- May have a steeper learning curve for developers new to Rust and WebAssembly
- Requires additional setup compared to using wasm-bindgen directly
- Can be slower for small projects due to its comprehensive nature
Code Comparison
wasm-bindgen:
#[wasm_bindgen]
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
wasm-pack:
#[wasm_bindgen]
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
wasm-pack build
The code for the function itself is identical, but wasm-pack requires an additional command to build the project for WebAssembly use.
Summary
While wasm-bindgen focuses on providing low-level bindings between Rust and JavaScript, wasm-pack offers a more comprehensive solution for building and publishing WebAssembly modules. wasm-pack builds on top of wasm-bindgen, adding features like npm package generation and testing tools. However, this comes at the cost of increased complexity and potentially slower build times for smaller projects.
Emscripten: An LLVM-to-WebAssembly Compiler
Pros of Emscripten
- Broader language support, including C and C++
- More mature and established ecosystem
- Extensive toolchain for compiling to WebAssembly
Cons of Emscripten
- Steeper learning curve
- Larger output size compared to Wasm-bindgen
- Less seamless integration with JavaScript
Code Comparison
Emscripten (C++):
#include <emscripten.h>
EMSCRIPTEN_KEEPALIVE
int add(int a, int b) {
return a + b;
}
Wasm-bindgen (Rust):
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
Emscripten requires explicit use of EMSCRIPTEN_KEEPALIVE
to export functions, while Wasm-bindgen uses a more declarative #[wasm_bindgen]
attribute. Wasm-bindgen's approach is generally more ergonomic for Rust developers.
Emscripten is better suited for projects with existing C/C++ codebases or those requiring its extensive toolchain. Wasm-bindgen, on the other hand, offers a more streamlined experience for Rust developers and typically produces smaller output sizes. The choice between the two often depends on the project's language requirements and the developer's familiarity with the respective ecosystems.
A lightweight WebAssembly runtime that is fast, secure, and standards-compliant
Pros of Wasmtime
- More comprehensive WebAssembly runtime with broader use cases
- Supports multiple programming languages beyond just JavaScript
- Offers standalone CLI tool for running and debugging Wasm modules
Cons of Wasmtime
- Steeper learning curve for simple JavaScript/Wasm integrations
- Requires more setup and configuration for basic web projects
- May be overkill for small-scale or web-only applications
Code Comparison
Wasmtime (Rust):
use wasmtime::*;
let engine = Engine::default();
let module = Module::from_file(&engine, "example.wasm")?;
let store = Store::new(&engine, ());
let instance = Instance::new(&store, &module, &[])?;
wasm-bindgen (JavaScript):
import init, { greet } from './pkg/hello_wasm.js';
async function run() {
await init();
greet('World');
}
Wasmtime provides a more low-level API for working with WebAssembly modules, while wasm-bindgen focuses on seamless JavaScript-Wasm interop for web applications. Wasmtime is better suited for complex, multi-language projects, while wasm-bindgen excels in simplifying Wasm usage in web environments.
🚀 Fast, secure, lightweight containers based on WebAssembly
Pros of Wasmer
- Supports multiple programming languages, not just JavaScript
- Can run WebAssembly modules outside the browser environment
- Provides a more comprehensive WebAssembly runtime ecosystem
Cons of Wasmer
- Higher complexity and learning curve compared to wasm-bindgen
- May have more overhead for simple browser-based WebAssembly use cases
- Less focused on JavaScript/browser integration
Code Comparison
wasm-bindgen:
#[wasm_bindgen]
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
Wasmer:
use wasmer::{imports, Instance, Module, Store};
let module = Module::new(&store, wasm_bytes)?;
let instance = Instance::new(&module, &imports! {})?;
let add = instance.exports.get_function("add")?;
let result = add.call(&[Value::I32(5), Value::I32(37)])?;
wasm-bindgen focuses on seamless JavaScript integration, making it easier to use WebAssembly in browser environments. It automatically generates JavaScript bindings for Rust functions.
Wasmer provides a more versatile WebAssembly runtime, allowing execution of WebAssembly modules in various environments and languages. It offers more control over module instantiation and execution but requires more setup code.
Both projects serve different use cases, with wasm-bindgen being more suitable for browser-centric applications and Wasmer for broader WebAssembly runtime needs.
A TypeScript-like language for WebAssembly.
Pros of AssemblyScript
- Easier learning curve for JavaScript developers
- Supports a wider range of programming paradigms
- Offers a more familiar syntax for web developers
Cons of AssemblyScript
- Less mature ecosystem compared to Rust
- May have performance limitations in certain scenarios
- Smaller community and fewer resources available
Code Comparison
AssemblyScript:
export function add(a: i32, b: i32): i32 {
return a + b;
}
wasm-bindgen:
#[wasm_bindgen]
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
AssemblyScript provides a TypeScript-like syntax, making it more accessible for JavaScript developers. It allows for easier integration with existing web projects and supports object-oriented programming. However, it may not achieve the same level of performance as Rust in certain scenarios.
wasm-bindgen, being based on Rust, offers better performance and memory safety guarantees. It has a more mature ecosystem and a larger community, providing more resources and tools. However, it has a steeper learning curve for developers not familiar with Rust.
Both projects aim to simplify WebAssembly development, but they cater to different developer preferences and project requirements. The choice between them often depends on the team's expertise, performance needs, and existing codebase.
The WebAssembly Binary Toolkit
Pros of wabt
- Broader scope: Supports multiple WebAssembly-related tools and utilities
- Language-agnostic: Works with various programming languages, not limited to Rust
- Mature project: Longer development history and wider adoption in the WebAssembly community
Cons of wabt
- Lower-level tooling: Requires more manual work and understanding of WebAssembly internals
- Less seamless integration: Doesn't provide automatic JavaScript bindings like wasm-bindgen
- Steeper learning curve: May be more challenging for developers new to WebAssembly
Code comparison
wabt (C++):
#include "src/binary-reader-ir.h"
#include "src/binary-writer.h"
#include "src/ir.h"
void example() {
wabt::Module module;
// ... manipulate module ...
}
wasm-bindgen (Rust):
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn example() {
// ... Rust code ...
}
wabt focuses on low-level WebAssembly manipulation, while wasm-bindgen provides high-level Rust-to-JavaScript bindings. wabt offers more flexibility across languages, but wasm-bindgen simplifies Rust-WebAssembly integration. Choose based on your project's specific needs and language preferences.
Convert
designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
wasm-bindgen
Facilitating high-level interactions between Wasm modules and JavaScript.
Guide (main branch) | API Docs | Contributing | Chat
Built with ð¦ð¸ by The Rust and WebAssembly Working Group
Install wasm-bindgen-cli
You can install it using cargo install
:
cargo install wasm-bindgen-cli
Or, you can download it from the release page.
If you have cargo-binstall
installed,
then you can install the pre-built artifacts by running:
cargo binstall wasm-bindgen-cli
Example
Import JavaScript things into Rust and export Rust things to JavaScript.
use wasm_bindgen::prelude::*;
// Import the `window.alert` function from the Web.
#[wasm_bindgen]
extern "C" {
fn alert(s: &str);
}
// Export a `greet` function from Rust to JavaScript, that alerts a
// hello message.
#[wasm_bindgen]
pub fn greet(name: &str) {
alert(&format!("Hello, {}!", name));
}
Use exported Rust things from JavaScript with ECMAScript modules!
import { greet } from "./hello_world";
greet("World!");
Features
-
Lightweight. Only pay for what you use.
wasm-bindgen
only generates bindings and glue for the JavaScript imports you actually use and Rust functionality that you export. For example, importing and using thedocument.querySelector
method doesn't causeNode.prototype.appendChild
orwindow.alert
to be included in the bindings as well. -
ECMAScript modules. Just import WebAssembly modules the same way you would import JavaScript modules. Future compatible with WebAssembly modules and ECMAScript modules integration.
-
Designed with the "Web IDL bindings" proposal in mind. Eventually, there won't be any JavaScript shims between Rust-generated wasm functions and native DOM methods. Because the Wasm functions are statically type checked, some of those native methods' dynamic type checks should become unnecessary, promising to unlock even-faster-than-JavaScript DOM access.
Guide
ð Read the wasm-bindgen
guide here! ð
You can find general documentation about using Rust and WebAssembly together here.
API Docs
MSRV Policy
Libraries that are released on crates.io have a MSRV of v1.57. Changes to the MSRV will be accompanied by a minor version bump.
CLI tools and their corresponding support libraries have a MSRV of v1.76. Changes to the MSRV will be accompanied by a patch version bump.
License
This project is licensed under either of
- Apache License, Version 2.0, (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Contribution
See the "Contributing" section of the guide for information on
hacking on wasm-bindgen
!
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this project by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
Top Related Projects
📦✨ your favorite rust -> wasm workflow tool!
Emscripten: An LLVM-to-WebAssembly Compiler
A lightweight WebAssembly runtime that is fast, secure, and standards-compliant
🚀 Fast, secure, lightweight containers based on WebAssembly
A TypeScript-like language for WebAssembly.
The WebAssembly Binary Toolkit
Convert
designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot