How to Connect Rust lib + Web Assembly + React.js(typescript)

morshedulmunna

Morshedul Munna

Posted on October 29, 2022

How to Connect Rust lib + Web Assembly + React.js(typescript)

Summary

In this article, I’ll introduce followings through creating simple demo application.

  1. How to create a React app quickly with create-react-app.
  2. How to create a Wasm library with Rust.
  3. How to create a Wasm library with Rust.

Create a React App with create-react-app

yarn create react-app myApp --template typescript
Enter fullscreen mode Exit fullscreen mode

or

npx create-react-app myApp --template typescript
Enter fullscreen mode Exit fullscreen mode

then you can run this App in your Local Mechine

cd myApp
npm start or yarn start
Enter fullscreen mode Exit fullscreen mode

Starting the development server...
Compiled successfully!

You can now view react-wasm-tutorial in the browser.

Local: http://localhost:3000
On Your Network: http://192.168.0.153:3000

Create Rust library for Wasm

To Connected Wasm to the React app, you need to follow these steps.

Create Rust library with cargo.

cargo new myApp-lib --lib
Enter fullscreen mode Exit fullscreen mode

Now Implement a Rust function that you want to call from JavaScript.

Simply, we’ll implement add function and call it from JavaScript.

// lib.rs

fn add(a: i32, b: i32) -> i32 {
    a + b
}

#[test]
fn add_test() {
    assert_eq!(1 + 1, add(1, 1));
}
Enter fullscreen mode Exit fullscreen mode

Wrap the function with wasm-bindgen to export it as Wasm.

wasm-bindgen is Rust library that facilitate high-level interactions between Wasm and JavaScript. For example, you can call Rust(Wasm) from JavaScript, and vice versa.

To add wasm-bindgen dependency, you need to add it to Cargo.toml.

[package]
name = "wasm-lib"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[lib]
crate-type = ["cdylib"]

[dependencies]
wasm-bindgen = "0.2.78"
Enter fullscreen mode Exit fullscreen mode

Then, Let’s wrap the function with wasm-bindgen.

use wasm_bindgen::prelude::*;

#[wasm_bindgen]
fn add(a: i32, b: i32) -> i32 {
    a + b
}

#[test]
fn add_test() {
    assert_eq!(1 + 1, add(1, 1));
}
Enter fullscreen mode Exit fullscreen mode

Build as Wasm library with wasm-pack

By using wasm-bindgen, you can build Rust as Wasm. However, To load and run Wasm from JavaScript, You need some JavaScript boilerplate codes (like WebAssembly.instantiate).

To do that, you can use wasm-pack!

At first, you need to install it.

cd ..
cargo update
wasm-pack --version
=> wasm-pack 0.10.2
Enter fullscreen mode Exit fullscreen mode

Then, let’s add npm script to call it by npm run build-lib.

  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
   "build-lib:wasm": "cd myApp-lib && wasm-pack build --target web --out-dir pkg",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
Enter fullscreen mode Exit fullscreen mode

Let’s check the output directory generated by wasm-pack.

You noticed package.json file was generated.

$ tree wasm-lib/pkg
├── package.json
├── wasm_lib.d.ts
├── wasm_lib.js
├── wasm_lib_bg.wasm
└── wasm_lib_bg.wasm.d.ts
Enter fullscreen mode Exit fullscreen mode

So you can install the Wasm library to other project easily. Let’s install it to the React app.

npm install ./wasm-lib/pkg
Enter fullscreen mode Exit fullscreen mode

or

yarn add ./wasm-lib/pkg
Enter fullscreen mode Exit fullscreen mode

Call the Wasm function from the React app.

import and call
import React, { useEffect, useState } from 'react';
+import init, { add } from "wasm-lib";
import logo from './logo.svg';
import './App.css';

function App() {
+  const [ans, setAns] = useState(0);
+  useEffect(() => {
+    init().then(() => {
+      setAns(add(1, 1));
+    })
+  }, [])
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.tsx</code> and save to reload.
        </p>
+        <p>1 + 1 = {ans}</p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

Finaly, you can see this screen.

Advanced topics

In this article, I provided the quick introduction for Rust and Wasm. To use Wasm in production, you should think about the following topics.

  • Logging
  • Multi-Threading
  • Exception handling
  • Call JavaScript from Rust
  • Call Rust struct from JavaScript
  • Testing
  • Cross platform
💖 💪 🙅 🚩
morshedulmunna
Morshedul Munna

Posted on October 29, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related