WebAssembly looks quite promising in bringing high performance, near-native speed to frontend applications, all from within the browser.
This opens up entirely new fronts/avenues for frontend application which was previously inaccessible. There are numerous articles and writings on webassembly out there, and this article's scope is not about the workings of WebAssembly but instead about setting it up with Rust and React, so one can use this boilerplate code to build useful applications.
The reason I chose Rust is that Rust as a language is really good and is well suited for systems programming and also I have been exploring Rust for close to a month for another side project of mine but that is for another day.
Create a new app using create-react-app
npx create-react-app my-app
create-react-app is the defacto tool to create a react app which takes care of setting up all the initial configuration and scripts, so developers can focus more on creating applications rather than configuring them
sudo npm i -g wasm-pack --unsafe-perm=true
We will be using this to create a native rust package that is configured to compile to wasm. One can think of it as a create-react-app equivalent for the Rust module.
wasm-pack new <your-native-module-name>
This will create a native rust module
Now, you can restructure the app the way you want, just make a note of the relative path of the native module from the project's root.
Create-react-app takes care of all the configuration, but it does come at a price. We can't modify configurations to suit our needs, because that is the job of create-react-app. But for adding our rust module and WebAssembly into our build, we need to update webpack config.
We don't need to eject create-react-app, there is a way we can do this without ejecting create-react-app; using ‘react-app-rewired’
npm install react-app-rewired @wasm-tool/wasm-pack-plugin --save-dev
add config-overrides.js
Rewrite your scripts config in your package.json file
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test",
"eject": "react-scripts eject"
},
Done, you are all set for creating something useful with react and rust.
Please refer to the github repo below for reference,
Top comments (6)
Lokesh, Hi, thanks for your effort on this project. After completing all of the steps in your article I do an npm start just to check things and get an ELIFECYCLE error when it tries to create the /src/native/build folder. My rust app folder is outside the react app folder.
Thank you for your feedback.
If you want to use a different path, then please try changing this configs accordingly
Is there any reason why you don't want to move the rust code inside src folder?
Now that I have things working(?) I don't get the greeting alert, just the default react screen. Are there other steps that have to be implemented to get the alert? Also I noticed a difference in the structure of your solution and the one used in the wasm-game-of-life tutorial. There they place the Rust code in the root of the app and the React app inside that. can you explain why your approach is different and the advantage of your approach. Thank you so very much for your time.
From the article I wasn't sure where the rust code should be put. I ended up rebuilding my Mac because I wasn't able to compile any wasm rust react tutorial and now things work. Thanks for your efforts and response.
Lokesh, I'm implementing your template into an existing React app but the componentDidMount assignment of a value to this.state.nativeModule doesn't stick:
When I examine the state value of nativeModule right after the import setState it has an object value, however when accessing the state value of nativeModule in the function that accesses the state value of nativeModule it's null.
config-override has the following assignments:
The file that contains this code located at: ./src/BudgetManager/ClientBudget/BudgetTable.js
Any ideas? Could it be because the import isn't happening in the App.js file?
Thanks.
Hello Charles, my sincere apologies for replying to this quite late.
From looking at your code, it looks you need to update the path relative to the file in which you are importing.
Since you trying to import the build in BudgetTable.js, please update the import path in componentDidMount to reflect the relative path to the build file from the directory of BudgetTable.js.