Behold, the buzzwords:
- Rust / WASM / wasm-bindgen
- React
- Monorepo / Yarn workspaces
- Webpack 5 / create-react-app 5
- Typescript
The main goal here: To use Rust + WASM in a react app, inside a monorepo.
TLDR: visit the final product! https://github.com/cmdcolin/rust_react_monorepo_template. It is also deployed live here https://cmdcolin.github.io/rust_react_monorepo_template
2025 update: While this article covers create-react-app, the Vite version is simpler and easier. I made a simple Vite app in https://github.com/cmdcolin/logistic_chaos_map
Steps to create this type of integration from scratch
Create repo
mkdir template
cd template
git init
Create root package.json
Then put this in the monorepo’s root package.json
{
"private": true,
"workspaces": ["hello-wasm", "app"]
}
This sets our repo up as a “monorepo” with two “workspaces”. one will be the
wasm code, in hello-wasm, one will be an instance of create-react-app
Add a create-react-app instance inside the monorepo
npx create-react-app --template typescript app
This will make an app subfolder inside our monorepo
Download the hello world rust wasm-bindgen example and put it in a folder named hello-wasm
Download https://github.com/rustwasm/wasm-bindgen/tree/main/examples/hello_world to the hello-wasm folder
This link can help https://download-directory.github.io/?url=https%3A%2F%2Fgithub.com%2Frustwasm%2Fwasm-bindgen%2Ftree%2Fmain%2Fexamples%2Fhello_world
Add some extra fields to the package.json in the hello-wasm folder
{
"name": "hello-wasm",
"version": "1.0.0",
"files": ["pkg"],
"main": "pkg/index.js"
... rest
}
Modify the hello-wasm example to return a value instead of making an alert
I changed the rust code to return a String value instead of making an alert box
#[wasm_bindgen]
pub fn greet(name: &str) -> String {
format!("Hello {}", name)
}
Build the hello-wasm pkg
Go into the hello-wasm folder and run yarn build. This creates a directory
named pkg which has .wasm files and .js files. Now, the hello-wasm
folder is effectively a node package. We could publish this to NPM (see
footnote 1)
Add the hello-wasm package to the app dependencies
Add "hello-wasm":"^1.0.0" to the dependencies array in app/package.json.
This will refer to our local monorepo’s rust wasm package!
Create craco config for create-react-app
As of writing, with webpack v5/create-react-app v5, you have to customize
the create-react-app to add extra webpack flags.
So, yarn add @craco/craco in the app folder, then create this
craco.config.js
module.exports = {
webpack: {
configure: config => {
const wasmExtensionRegExp = /\.wasm$/
config.resolve.extensions.push('.wasm')
config.experiments = {
syncWebAssembly: true,
}
config.module.rules.forEach(rule => {
;(rule.oneOf || []).forEach(oneOf => {
if (oneOf.type === 'asset/resource') {
oneOf.exclude.push(wasmExtensionRegExp)
}
})
})
return config
},
},
}
Note: this thread helped me to create the craco config https://github.com/Emurgo/cardano-serialization-lib/issues/295
Also see footnote 2 for more info
Final step: Use async import() to import the hello-wasm greeting
We use a useEffect hook to import the code asynchronously, and can call our
rust function, greet, from javascript!
function App() {
const [greeting, setGreeting] = useState<string>()
useEffect(() => {
;(async () => {
try {
const wasm = await import('hello-wasm')
const greeting = wasm.greet('Colin')
setGreeting(greeting)
} catch (e) {
console.error(e)
}
})()
}, [])
return (
<div>
<h1>rust monorepo wasm demo</h1>
<h2>Greeting from wasm: {!greeting ? 'Loading...' : greeting}</h2>
</div>
)
}
In order to greet an arbitrary person, I modified this slightly in the live demo. See https://github.com/cmdcolin/rust_react_monorepo_template/blob/master/app/src/App.tsx
Run the app!
Go into the app folder, and then run yarn start
Result!
A screenshot of the app, showing the string “Hello Colin” which is generated via rust and wasm

Conclusion
My main aim was to demonstrate creating a “simple” monorepo setup showing how you can integrate Rust+WASM and React. Feel free to ask me any questions and go check out the repo!
https://github.com/cmdcolin/rust_react_monorepo_template
Other resources
This article is quite helpful also, but uses a file:/ reference in their
package.json while my approach uses a monorepo, it is fundamentally quite
similar though!
https://tkat0.github.io/posts/how-to-create-a-react-app-with-rust-and-wasm
Footnote 1: The hello-wasm folder IS a npm package with wasm files
The hello-wasm folder can be published to NPM by itself. When consumers of the
package import the module, they would receive pkg/index.js from the main
field in package.json, and then pkg/index.js in turn imports the
index.wasm file. Then it is up to the consumers bundler to package that
correctly.
Footnote 2: Bundlers and wasm
As of writing, I am using webpack v5 (part of create-react-app v5), which
has “native support” for wasm. Still, it is hidden behind a flag called
“experiments” (see first google result for webpack wasm here
https://webpack.js.org/configuration/experiments/) so I use @craco/craco to
modify the webpack config of create-react-app v5 to add this.
Note also: The first time I wrote this, I used webpack v4, which used a
slightly different workflow (used a special webpack loader called
wasm-loader)
You can also likely use similar techniques described in this article to
incorporate into next.js since it also uses webpack. If you have info on how
other bundlers use wasm, feel free to leave a comment.
Footnote 3: Why do I have to use async imports?
Fundamentally, the .wasm file has to be fetched asynchronously before it can
be run (it is not in my experience e.g. embedded as binary data inside a js
file) which means it would be difficult to use the wasm code as a synchronous
import.
There are hints that this may be possible but it would rely on the bundler embedding the wasm code in the js itself, or maybe top-level-await. If anyone has more info, feel free to leave a comment!
Footnote 4: Build setup
The hello-wasm package does not automatically recompile when we are running
e.g. yarn start in the app folder. Therefore, changes to the rust requires
you to manually run yarn build in the hello-wasm folder. Just something to
be aware of
Footnote 5: My first experience with trying to make this work was rocky!
I first created an example of rust+wasm+react almost two years ago when creating a fractal viewer https://github.com/cmdcolin/logistic_chaos_map and it has some development notes on the stumbling blocks I faced https://github.com/cmdcolin/logistic_chaos_map/blob/master/NOTES.md
Footnote 6: I thought you said typescript too
Yep! The hello-wasm example generates typescript .d.ts files! Check out the
hello-wasm/pkg/ folder after you build it! This was none of my doing, just a
built-in feature. PS: I highly recommend inspecting the pkg folder that is
produced in the hello-wasm build to help understand the details. I also
recommend reading the https://rustwasm.github.io/wasm-bindgen/ docs and if you
are getting started with rust, read the Rust Book along with doing rustlings
https://github.com/rust-lang/rustlings
Footnote 7: Another resource
This article was posted on reddit and is also a great resource especially about sync vs async webpack loading schemes for wasm
https://canvasapp.com/blog/building-modern-web-apps-with-rust-wasm-and-webpack/
Footnote 8: Vite version
2025 update: While this article covers create-react-app, the Vite version is simpler and easier. I made a simple Vite app in https://github.com/cmdcolin/logistic_chaos_map