Intro to Rust Web Assembly with Rust's Wasm Bindgen Library

in utopian-io •  4 months ago

wasm_logo.png

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
Sources

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.

wasm_example.png

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.

wasm_extern.png

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.

wasm_bottom.png

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

Video Tutorial

Proof of Work Done

https://github.com/tensor-programming/

Authors get paid when people like you upvote their post.
If you enjoyed what you read here, create your account today and start earning FREE STEEM!
Sort Order:  

Great start to this tutorial, @tensor. Looking forward to studying more of your lessons in this series.

Your contribution has been evaluated according to Utopian policies and guidelines, as well as a predefined set of questions pertaining to the category.

To view those questions and the relevant answers related to your post, click here.


Need help? Write a ticket on https://support.utopian.io/.
Chat with us on Discord.
[utopian-moderator]

·

Thank you.

I personally though it was a bit of a rough start but I am glad it seems to have worked out.

Thank you for providing source code. It will help me a lot.

·

I always provide source code.

Thank you for covering tutorials about WebAssembly and Rust, this will help Developer interested in WebAssembly to build their own wasm npm package (using wasm-pack). From what I know Rust std library doesn't yet support compiling to target wasm32 and embedded. Regarding that, I'm curious if:

  1. is it possible to create a monorepo project purely in Rust using wasm-bindgen that can be compiled targeting wasm32 and x86_64?
  2. can I create WebComponent purely in Rust using wasm-bindgen?
·

Firstly, the standard library will compile to Wasm32 for the most part. There are a few small features that do not work (pointers for instance) but you can include any of the libraries in the core of rust in your wasm project with bindgen. (You can also include many of the 3rd party libraries as well.)

  1. You can create a monorepo with bindgen and not reference any JS functions.

  2. From what I know you can't fully make a webcomponent in wasm-bindgen, but there are alternatives that do allow for this.

Hey @tensor
Thanks for contributing on Utopian.
Congratulations! Your contribution was Staff Picked to receive a maximum vote for the video-tutorials category on Utopian for being of significant value to the project and the open source community.

We’re already looking forward to your next contribution!

Want to chat? Join us on Discord https://discord.gg/h52nFrV.

Vote for Utopian Witness!