Repository
https://github.com/rust-lang/rust
What Will I Learn?
- You will learn about the Wasm bindgen library in Rust
- You will learn how to create shims for JavaScript Functions and Objects
- You will learn how to interface with JavaScript via Web Assembly
- You will learn how to compile Rust to Web Assembly using Wasm Bindgen
- You will learn how to create a library for Web Assembly using Rust
Requirements
System Requirements:
- Visual Studio Code or any other Text Editor with Rust language plugins
- The Rustup command line tool and the nightly Rust compiler
Required Knowledge
- Some understanding of JavaScript and Node.Js
- Some basic understanding of Rust
- A fair amount of knowledge on web technologies and how they work
Resources for Rust
- Rust Website: https://www.rust-lang.org/
- Web Assembly Website: https://webassembly.org/
- Awesome Rust: https://github.com/rust-unofficial/awesome-rust
- Wasm Bindgen Repo: https://github.com/rustwasm/wasm-bindgen
Sources
- WASM Logo: https://webassembly.org/
Difficulty
- Intermediate
Description
Outline and Overview
In this Rust Tutorial, we take a look at the basics of building a library using Rust with Web Assembly. More specifically, we take a look at the Wasm Bindgen library and the various tools that come with it. Wasm Bindgen allows developers to build libraries in Rust which can be referenced through JavaScript or TypeScript as though it was a native library or module. This is achieved by compiling the Rust library into Web assembly and by creating shims that connect the Rust code to functions and objects in the JavaScript layer.
Coding the Web with Rust and WebAssembly
Web Assembly or WASM, is a binary instruction format; that features a lisp-like syntax; which may run on a stack-based virtual machine. The basic idea is to be able to write code in a higher level language like Rust or C++ and then compile it into a portable specification which is very efficient on the Web as well as other target virtual machines. One of the main ways of creating WASM code with Rust is to use a library called wasm_bindgen. Wasm bindgen features a CLI which generates optimized Web Assembly code as well as JavaScript shims and TypeScript Typings. This library can be referenced like any other node module or JavaScript library.
Above is the WASM generated by the wasm_bindgen CLI. As you can see, the code looks like a mixture of Machine Assembly and Lisp. By using such low level instructions, we are able to gain a large amount of performance and optimization for the web platform. There are also various tools which can further optimize the WASM code by striping out functionality that is not used by the library or project.
Shimming from One Language to the Next
A Rust Bindgen library features two major sections. The first section is for defining the type annotations and functions that will be exported into the library from the JavaScript virtual machine. Functions like log()
, alert()
body()
and querySelector()
can all be easily implemented using these Shims. In this way we are able to directly reference a JavaScript function from our Rust code without having to redefine the functionality. This also applies to any JavaScript objects such as document
and console
.
In this image, we have the external block that was used in this example library. In it, we define various types such as HTMLDocument
and Element
which allow us to reference objects like the document
object. We then are able to use declarative macros to point functions which we create in this interface towards their native JavaScript counterparts. In this example, we use createElement
, body
, appendChild
, innerHTML
and alert
to support the functionality of our library.
Writing Native Code for the Client
The second major part of a Rust Bindgen library is native Rust code that we want to turn into Web Assembly. We are able to use almost all of the features of the language to build our library. We use Declarative macros to define which functions we want to compile into Web Assembly. We can also reference the shimmed functions which we defined in the extern
block above.
Here we have the native code that was used in this project. The first function called run_alert
simply formats a string and then passes it into the JavaScript alert
function. This function takes in a string from the JavaScript layer and then it is concatenated onto the string that is hardcoded in our Rust layer. The second function, create_stuff
builds a block of HTML by creating a div
and a p
tag. We then add some text to the inside of the p
tag using the innerHTML
JavaScript property. All of this takes place in the Rust/WASM layer.
The source code for this project can be found here