DEV Community

loading...
Cover image for WebAssembly with Rust and React (Using create-react-app)

WebAssembly with Rust and React (Using create-react-app)

lokesh007 profile image Lokesh Prabakaran ・2 min read

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,

GitHub logo lokesh-007 / wasm-react-rust

WebAssembly with Rust and React (Using create-react-app)

Discussion

pic
Editor guide
Collapse
chasahodge profile image
Charles Hodge

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.

Collapse
lokesh007 profile image
Lokesh Prabakaran Author

Thank you for your feedback.

If you want to use a different path, then please try changing this configs accordingly

  1. Line 17 in this file: github.com/lokesh-007/wasm-react-r...
  2. Line 18 and 20 in this file github.com/lokesh-007/wasm-react-r...

Is there any reason why you don't want to move the rust code inside src folder?

Collapse
chasahodge profile image
Charles Hodge

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.

Collapse
chasahodge profile image
Charles Hodge

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.

Collapse
chasahodge profile image
Charles Hodge

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:

class BudgetTable extends Component {
...
componentDidMount() {
    import("../../native/build").then(native => {
        this.setState({
          nativeModule: native
        });
    });
    ...
}
Enter fullscreen mode Exit fullscreen mode

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.

    const {
        nativeModule,
    } = this.state.nativeModule;
Enter fullscreen mode Exit fullscreen mode

config-override has the following assignments:

config.plugins = (config.plugins || []).concat([
    new WasmPackPlugin({
        crateDirectory: path.resolve(__dirname, "./src/native"),
        extraArgs: "--no-typescript",
        outDir: path.resolve(__dirname, "./src/native/build")
    }),
]);
Enter fullscreen mode Exit fullscreen mode

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.