Rust Web Assembly - Using Stdweb to Build a Client side Application with Rust and WASM
Repository
https://github.com/rust-lang/rust
What Will I Learn?
- You will learn how to use Cargo Web
- You will learn about Stdweb
- You will learn about the Rust Web API from Stdweb
- You will learn how to use the js! and console! macros
- You will learn how to make event listeners in Rust
- You will learn how to draw on canvas elements with Stdweb
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 Web Assembly Video tutorial, we take a look at the stdweb
library for Rust. This library has certain pros and cons when compared to the wasm_bindgen
library that we've been using thus far. The stdweb
library forms the basis for many of the web assembly frameworks and libraries that exist in Rust. This includes the Yew framework that we've looked at in the past. In this project, we build a bunch of event listeners to capture key and mouse events and we build some functions to allow us to draw on a 2d canvas.
Using Stdweb and Cargo Web to Build a Project
The stdweb
library has many of the same design goals as the wasm_bindgen
library. How it achieves these goals however, is vastly different. Stdweb exposes a full native set of Web based APIs for interfacing with web browsers where as with wasm_bindgen
the developer needs to specify which parts of the web API they want to use. As a result of this, smaller projects tend to be more resource heavy in stdweb
unless you strip out unnecessary elements of the API. Stdweb
has many nice features built directly on top of it; this includes the ability to write JavaScript code inside of the Rust application using the js!
macro and the ability to access various top level objects using the console!
macro.
In our example, we make use of the js!
macro to write a simple "hello world" application and we also make use of the console!
macro to be able to streamline access to the console object. These macros help the library maintain the Rust language feel while still providing the ability to build flexible APIs and projects. You can see how the lines in the js!
macro are structured with a syntax that is like any normal JavaScript application.
Making Event Listeners for the Mouse and Keyboard
This library also exposes many event based types which we can use to create listeners. This includes IEvent
, KeyDownEvent
, KeyUpEvent
, MouseDownEvent
, MouseMoveEvent
, MouseUpEvent
as well as many others. These types and functions follow the conventions of their JavaScript counterparts. This means that building applications using the stdweb
library is very familiar for developers who are well versed in JavaScript and front-end development without giving up the advantages of using Rust as a language.
In this sample project, we add event listeners to the window
object. We are able to gain access to this window
object through the web module from inside of the stdweb
library. We add the event listeners by using closures and first class functions. In this application, we create event listeners for key up and down, mouse up and down and mouse movement. Notice how similar this syntax is to a typical JavaScript program.
Accessing HTML Canvas from Rust
Along with the ability to create event listeners and use macros to access various parts of the web API; stdweb
gives developers the ability to gain access to the canvas API. This includes the ability to access the canvas context with a CanvasRenderingContext2d
type and a CanvasRenderingContext3d
type. The canvas itself can be expressed using the CanvasElement
type as well.
In our project, we use this canvas API to draw multiple boxes. We first draw three boxes using a draw_box
function and the context which we access using an HTML selector. We are then able to also attach this canvas draw_box
function to our MouseMoveEvent
event listener so that when a user moves their mouse inside of the Canvas element on the HTML document, it draws small squares under the mouse pointer.
The source code for this project can be found here
Video Tutorial
Curriculum
- Intro to Rust Web Assembly with Rust's Wasm Bindgen Library
- Rust Web Assembly - Building a Simple Markdown Parser with Rust's Wasm Bindgen
Excellent video tutorial @tensor. I liked the way you introduce concepts then give a little side-note about its function and uses. Almost like a guided nature tour. Your practical knowledge of the bird and plant life is outstanding and your ability to put these creatures to work for you is equally outstanding.
Thank you for the great video tutorial.
Cheers,
Bucky
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]
Again, thanks for reviewing my contributions. I like the metaphor haha.
Hey @tensor
Thanks for contributing on Utopian.
We’re already looking forward to your next contribution!
Want to chat? Join us on Discord https://discord.gg/h52nFrV.
Vote for Utopian Witness!
Curious how long it takes to compile when someone building full scale web site/app purely in Rust.
Ah yes, have you measure the bundle size of JS file as a result of compile using wasm-bindgen and/or stdweb? I found many garbage when compiling without wasm-bindgen and stdweb (pure wasm, no js binding). Also found out the bundle size can be reduced significantly when enabling LTO.
There are quite a few tools that you can use to vastly reduce the bundle size with both libraries. In fact, you can just pull out most of the Rust functionality that you don't need and you can get it down to <100 kb with even very large projects. Of course this doesn't account for some of the more wasm specific tools which can reduce the size much further.
Compilation timing in Rust is average id say when compared to other AoT based languages. Its not as fast as Go for instance, but it is much faster then Java.
When I start to do some larger projects with WASM, I will start showing off some of the techniques and tools to optimize performance and bundle size of WASM projects built from Rust. I am also considering doing some computation benchmark tutorials but we will see about that one.
Nice! For the tools to reduce the bundle size, I have tried using wasm-gc and Binaryen. The most intriguing (and the best) one is Binaryen that I can't still figure out which configuration is the best for some use case.
Get More Upvote - FREE