How do I compile to WASM in create-react-app?

Viewed 982

I would like to know the "canonical way" to compile Go to WASM with webpack so that is available in a react app created with CRA.

So far I have tried the following:

  1. Started a new react app with CRA.

  2. Installed webpack-golang-wasm-async-loader via yarn add --dev webpack-golang-wasm-async-loader (https://github.com/aaronpowell/webpack-golang-wasm-async-loader)

  3. Installed react-app-rewired via yarn add --dev react-app-rewired in order to edit the Webpack config without ejecting

  4. Edited the config-overrides.js file with the following:

       const path = require('path');
    
       module.exports = function override(config, env) {
       const goExtensionRegExp = /\.go/;
    
       // add a dedicated loader for WASM
       config.module.rules.push({
           test: goExtensionRegExp,
           use: ['golang-wasm-async-loader']
       });
    
       config.node.fs = 'empty'
    
       return config;
     };
    

    to accord with the config instructions given in the loader README:

      module.exports = {
        ...
        module: {
             rules: [
                 {
                     test: /\.go/,
                     use: ['golang-wasm-async-loader']
                 }
             ]
         },
         node: {
             fs: 'empty'
         }
    };
    
  5. In my App.js file I have the following:

     import React from 'react';
    
     import wasm from './main.go'
    
     import logo from './logo.svg';
     import './App.css';
    
     class App extends React.Component {
    
       async init() {
         const result = await wasm.add(1, 2);
         console.log(result);
    
         const someValue = await wasm.someValue();
         console.log(someValue);
       }
    
       render() {
         return <div>Hello world</div>;
       }
     }
    
     export default App;
    
  6. In my main.go file I have the following:

    package main
    
    import (
         "strconv"
         "syscall/js"
         "github.com/aaronpowell/webpack-golang-wasm-async-loader/gobridge"
     )
    
     func add(i []js.Value) (interface{},error) {
         ret := 0
    
         for _, item := range i {
             val, _ := strconv.Atoi(item.String())
             ret += val
         }
    
         return ret, nil
     }
    
     func main() {
         c := make(chan struct{}, 0)
    
         gobridge.RegisterCallback("add", add)
         gobridge.RegisterValue("someValue", "Hello World")
    
         <-c
     }
    

My directory structure looks like the following:

    |- root
       |- node_modules
       |- public
       |- src
          |- App.css
          |- App.js
          |- App.test.js
          |- index.css
          |- index.js
          |- logo.svg
          |- main.go
          |...
       |...
       |- config-overrides.js
       |- package.json

Upon running yarn start I get the following error:

./src/main.go Error: spawn undefined/bin/go ENOENT

I would very much appreciate any help on how to get this to work, and I am open to using another approach, which is why I did not include the library name in the title.

0 Answers
Related