Skip to content

jkomyno/node-congress-2023

Repository files navigation

Type-safe bindings for Node.js with Rust and WebAssembly

Accompanying code for the talk I presented at Node Congress 2023 in Berlin, Germany

Github Actions License: MIT

Slides for this talk are also available here.

Abstract

This talk will teach you how to write performance-critical Node.js modules without the burden of distributing platform-dependent artifacts and using the C/C++ toolchain. You will discover how to smoothly integrate Rust code into your Node.js + TypeScript application using WebAssembly. You will also learn how to avoid the typical WebAssembly serialization issues, and understand when other alternatives like Neon or Napi.rs are preferable. Together, we will cross the language bridge between Rust and Node.js while preserving the familiar DX you're used to.

Get Started

Requirements

(*) These are the versions used to develop this repository. Older versions might work as well, but they haven't been tested.

Install Dependencies

  • Install dependencies:
    pnpm i

In ./rust:

  • Install the Rust toolchain via Rustup:

    curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
  • Add suppport for the wasm32-unknown-unknown compilation target for Rust:

    rustup target add wasm32-unknown-unknown
  • Install wasm-bindgen:

    cargo install -f wasm-bindgen-cli@0.2.84

    (the specific version is important, as wasm-bindgen-cli doesn't yet follow semantic versioning. This version needs to match the version of the wasm-bindgen dependency in the Cargo.toml files of the Rust crates)

Build & Test

With Docker:

  • Build and run the local Docker image:

    ./build.sh

Without Docker:

  • Run Rust unit tests and build the WebAssembly artifacts:

    pnpm build:wasm
  • Run Node.js unit tests:

    pnpm test:ci

Demos

playground-wasm-bindgen

The local playground-wasm-bindgen crate demonstrates how to use wasm-bindgen to export Rust functions and types (in the form of structs / enums) to TypeScript.

The functions::unsupported module (respectively, the types::unsupported module) contains a set of functions (respectively, types) that are not supported by wasm-bindgen by default, with comments showing the compilation errors that are thrown when trying to export them.

For instance, trying to compile the following code

/// Given a Vec<Vec<i32>> vector, return its length.
#[wasm_bindgen]
pub fn get_nested_array_length(x: Vec<Vec<i32>>) -> usize {
  x.iter().flatten().count()
}

would result in a compilation error like the following:

error[E0277]: the trait bound `Vec<i32>: JsObject` is not satisfied
  --> wasm-bindgen-playground/src/functions/unsupported.rs:27:1
   |
27 | #[wasm_bindgen]
   | ^^^^^^^^^^^^^^^ the trait `JsObject` is not implemented for `Vec<i32>`
   |
   = help: the following other types implement trait `FromWasmAbi`:
             Box<[JsValue]>
             Box<[T]>
             Box<[f32]>
             Box<[f64]>
             Box<[i16]>
             Box<[i32]>
             Box<[i64]>
             Box<[i8]>
           and 6 others
   = note: required for `Box<[Vec<i32>]>` to implement `FromWasmAbi`
   = note: this error originates in the attribute macro `wasm_bindgen`

playground-serde-wasm-bindgen

The local playground-serde-wasm-bindgen crate demonstrates how to use wasm-bindgen combined with serde and serde-wasm-bindgen to export Rust functions and types to TypeScript. This allows you to deal with complex types both in Wasm arguments and return types, at the cost of loosing strongly typed TypeScript bindings.

playground-wasm-tsify

The local playground-wasm-tsify crate demonstrates how to use wasm-bindgen combined with serde and tsify to export Rust functions and types to TypeScript. This allows you to deal with complex types both in Wasm arguments and return types, as well as obtaining strongly typed and idiomatic TypeScript bindings.

Main Dependencies

Please consider starring, supporting, and contributing to the following projects:

👤 Author

Alberto Schiabel

📝 License

Built with ❤️ by Alberto Schiabel. This project is MIT licensed.

About

Accompanying code for my talk "Type-safe bindings for Node.js with Rust and WebAssembly" presented @ Node Congress 2023 in Berlin

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published