WASM in Create-React-App 4 in 5mn (without ejecting)
Nicolas Rannou
Posted on December 22, 2020
First word
In this post, we will write some rust code, compile it to WASM and run it from a CRA4 application without ejecting.
Rust to WASM FTW
Why Rust? It's cool. There is a lot of hype around it so I decided to give it a go. The rust book and rust by examples were pretty useful to get an understanding of the basics.
Once I got my head around the basic concepts, time to look into the conversion to WASM. There is a lot of nice documentation out there (from the Rust official documentation of course ;)).
The recommendation is to use wasm-pack. That allows you to build and ship an importable WASM module in less than 2mn.
Create the project
$> wasm-pack new my-wasm-project
$> cd my-wasm-project
Package and public (details)
$> wasm-pack build --scope nicolasrannou
$> cd pkg
/*make sure the package.json includes the right files. At the time I write this post some .js and .wasm files were missing.*/
$> npm publish --access=public
CRACO
To load the exported module I chose CRACO because it appears Create-react-app-rewired is not really maintained anymore and doesn't work well with CRA4.
Adding dependencies in your CRA4 project
$> cd my-cra4-project
$> yarn add @nicolasrannou/my-wasm-project
$> yarn add @craco/craco
$> yarn add wasm-loader
Do not forget to update package.json
by replacing react-scripts
by craco
.
Setup the config file
$> cat craco.config.js
const { addBeforeLoader, loaderByName } = require('@craco/craco');
module.exports = {
webpack: {
configure: (webpackConfig) => {
const wasmExtensionRegExp = /\.wasm$/;
webpackConfig.resolve.extensions.push('.wasm');
webpackConfig.module.rules.forEach((rule) => {
(rule.oneOf || []).forEach((oneOf) => {
if (oneOf.loader && oneOf.loader.indexOf('file-loader') >= 0) {
oneOf.exclude.push(wasmExtensionRegExp);
}
});
});
const wasmLoader = {
test: /\.wasm$/,
exclude: /node_modules/,
loaders: ['wasm-loader'],
};
addBeforeLoader(webpackConfig, loaderByName('file-loader'), wasmLoader);
return webpackConfig;
},
},
};
Import the WASM code
$> cat App.tsx
...
useEffect(async () => {
const promise = await import("@nicolasrannou/my-wasm-project");
promise.greet();
}, []);
...
š Until next time!
Posted on December 22, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.