Using WebAssembly in a ReactJS App

28/03/2020 Filip K

What is WebAssembly?

WebAssembly (abbreviated Wasm) is a binary instruction format for a stack-based virtual machine. Wasm is designed as a portable target for compilation of high-level languages like C/C++/Rust, enabling deployment on the web for client and server applications.

Alongside HTML, CSS and Javascript, it is the fourth language to run natively in browsers and supports the 4 major browser engines – Firefox, Chrome, Safari and Edge.

WebAssembly allows you to run code at native speed that is able to work with the JavaScript context and access browser functionality through the same Web APIs accessible from JavaScript. It basically allows you to run your code in native speed inside a browser.
You can learn more in-depth information about WebAssembly here:

Which languages can I use it with?

As mentioned above, it runs alongside Javascript. The code itself, however, is written in C, C++ or Rust.

Creating a Hello World in WebAssembly

Setting up

If you’ve never used Rust before, you need to install the standart Rust tool chain.You can find it here.

After you’ve installed the Rust tool chain, you need to install the wasm-pack and cargo-generate which lets you make a Rust project quickly by using a pre-existing git repository as a template.

Install cargo-generate with this command:

cargo install cargo-generate

Creating the Project

First, we need to clone a project template with this command:

cargo generate --git https://github.com/rustwasm/wasm-pack-template

Now let’s have a look at some of the files.
The main file we’ll be using is src/lib.rs. It is the root file that is going to be compiled into webassembly. It uses wasm-bindgen to connect with JavaScript. It imports the window.alert JavaScript function and exports the greet Rust function, which alerts a greeting message

Now, we need to compile our application to webassembly to be able to use it in our project. We do that by running  wasm-pack build

Using WebAssembly with React

first, we start with creating a react app.

npx create-react-app webassembly-react

Out of the box, create-react-app will not support WebAssembly. We have to make some changes to the underlying webpack config that powers the app. Unfortunately, create-react-app doesn’t expose the webpack config file. So, we’ll need to pull in some dev dependencies to help us out. react-app-rewired is going to allow us to modify the webpack without ejecting, and wasm-load will help webpack handle WebAssembly.

yarn add react-app-rewired wasm-loader --dev

Once this is done, you should have a fully functioning app, now we can make some tweaks to our webpack.

We need to add a config-overrides.js file to the root of our app. This file will allow us to make changes to our webpack file without rewriting it.
FilipK999

At this point, if you run yarn start, you will not be using the webpack config changes, since we need to modify the package scripts. We need to make some changes to package.json in order to take advantage of the changes we just made. 

Put this in your config.json:

If you’ve done everything correctly, you should be able to run yarn start and the app should load.

Importing a WebAssembly module into the app

Now that we have set up our React app and built the webassembly file, we need to import it. We need to do that asynchronously.

Once that is done, we can access webassembly in our app through state. Note that you need to await the module each time you call a function.

WebAssembly vs JavaScript – just how faster is it?

The most obvious reason for using WebAssembly in your JavaScript app is for making it faster. But is that really happening? Well it depends on your use case. If the processes you’re running in WebAssembly aren’t really that time intensive, it’s going to have the opposite result! It’s caused by WebAssembly having to be loaded into the app. That takes some time, and JavaScript usually manages to complete the process way earlier than WebAssembly gets imported. I have created an example for this. (You can find the repo here)

In this app, I’ve created two simple functions. One functions calculates the factorial of 200 and the other one calculates the factorials of the first 40 numbers in the Fibonacci sequence. You can try pressing the buttons for yourself, a graph is going to show you the time it took for the process to complete.

We can see that calculating the factorial of 200 was actually way faster done in JavaScript. How is that possible? Loading the wasm module takes some time. And if the function itself is not time heavy enough, JavaScript is going to get it done way faster than the wasm even gets loaded.
The second fucntion is obviously a bit more complex than the first one. For this one, it’s actually worth using WebAssembly. While computing the factorials of the first 30 numbers in the fibonacci sequence takes JavaScript about 500 milliseconds, WebAssembly is done in less than a millisecond, which is a massive difference.

Summary

Using WebAssembly in your web application is really useful if you need to make CPU-heavy or time heavy calculations fast. Getting it up and running is quite tedious and hard, since the language is pretty new and there haven’t yet been created any libraries or templates that make this process easier.

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna.