Rust Programming
WebAssembly with Rust
Interacting with WebAssembly from JavaScript
In this guide, we explore how JavaScript interacts with a WebAssembly module compiled from Rust. After building your Rust code into WebAssembly, you'll learn how to call Rust functions from JavaScript, exchange data seamlessly between the two, and even access WebAssembly’s memory directly.
The package folder generated by the wasm-pack build command contains all the necessary files to load, initialize, and use your Rust WebAssembly module within a JavaScript environment. Below is an overview of its structure, which includes one directory and six files.
Key Insight
Each file in the generated package plays a specific role in bridging the gap between Rust and JavaScript. Understanding each file will help you make the most out of your WebAssembly module.
Package Structure Breakdown
TypeScript Definition File
This file provides type hints and IntelliSense for your Rust functions when used in TypeScript or in JavaScript environments with type checking support.Main JavaScript Wrapper
The main JavaScript file contains the initialization function (commonly namedinit
) that loads the WASM binary and exposes the Rust functions to JavaScript. It serves as the entry point for invoking Rust functions, handling data conversion, and managing memory.Additional JavaScript Glue Code
This file acts as the bridge between JavaScript and WebAssembly by providing helper functions for managing complex data types such as strings and arrays. It also includes routines for memory allocation and deallocation required by Rust functions.Core WebAssembly Binary File
The core file contains all the compiled Rust code in a binary format that the browser executes. It is loaded by the JavaScript wrapper and accessed via exposed functions.Secondary TypeScript Definition File
This additional TypeScript definition file ensures that TypeScript can recognize and provide type information for WebAssembly memory elements, even if your project does not directly use TypeScript.package.json File
Thepackage.json
file serves as metadata for npm. It details dependencies, versions, and configurations, enabling the WebAssembly module to be published and distributed as an npm package for integration into other JavaScript projects.
Calling Rust Functions from JavaScript
Let's walk through a simple example of calling a Rust function from JavaScript using WebAssembly. In your Rust source code, use the wasm-bindgen
attribute to expose functions to JavaScript. Below is an example of the greet
function:
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn greet(name: &str) -> String {
format!("Hello, {}!", name)
}
After updating your Rust library, modify your index.html
file to load the module and invoke the function. In the HTML snippet below, we pass a sample name (e.g., "Priyanka") to the greet
function. We have also introduced a new function, add
, which returns the sum of two integers. Update your Rust source to include both functions:
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
#[wasm_bindgen]
pub fn greet(name: &str) -> String {
format!("Hello, {}!", name)
}
After making these changes, recompile your project with the following command:
wasm-pack build --target web
Next, update your index.html
file to correctly import and use both functions:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Rust and WebAssembly</title>
</head>
<body>
<h1 id="greeting">Loading...</h1>
<script type="module">
console.log("Loading Wasm...");
import init, { greet, add } from './pkg/my_wasm_project.js';
init().then(() => {
console.log("Wasm initialized successfully");
document.getElementById("greeting").innerText = greet("Priyanka");
// Call the add function and log the result
const result = add(5, 3);
console.log("5 + 3 =", result);
}).catch(error => {
console.error("Error initializing Wasm:", error);
});
</script>
</body>
</html>
Once you compile your project again and open index.html
in your browser, you should see "Hello, Priyanka!" displayed on the page. In the browser console, the following output confirms that the WebAssembly module is working as expected:
- Loading Wasm...
- Wasm initialized successfully
- 5 + 3 = 8
Final Thoughts
This demonstration underscores how accessible Rust functions are within the browser via WebAssembly. The seamless exchange of data types like strings and numbers enhances the development of high-performance web applications.
Watch Video
Watch video content