Rust Web Assembly - Using Stdweb to Build a Client side Application with Rust and WASM

in utopian-io •  8 months ago



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


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


  • Intermediate


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


Proof of Work Done

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:  

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.


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
Chat with us on Discord.


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

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.