Using WebAssembly in a ReactJS App

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.
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.