Wasm Builders 🧱

Cover image for Containerize React and WebAssembly (C++) with Docker
Kanin Kearpimy
Kanin Kearpimy

Posted on

Containerize React and WebAssembly (C++) with Docker

Containerize React and WebAssembly with Docker

Javascript is fast with its performance in web development. But for large data manipulation in near-native speed, secure sandbox, and multi-language support to run in the browser, WebAssembly is playing an important role.

C/C++ with Emscripten is one of the initial languages to implement WebAssembly. It requires a lot of setup to compile C/C++ into WebAssembly. Especially number of team members. To support scalability, the developer experience, containerization is main actor.

I’m going to walk you through setup Docker for React and WebAssembly (C++) then deploy it to fly.io

Github: https://github.com/kanin-kearpimy/React-with-WebAssembly-and-Docker

Pre-Installation

  1. react-create-app cli package

  2. Docker cli

Outline

  1. Create React Application.

  2. WebAssembly Hello World (C++ Emscripten).

  3. Integrate Webassembly with React.

  4. Containerization with Docker and Nginx.

1. Create React Application

We create react application with webpack bundling here:

$ npx create-react-app --typescript react-wasm-docker
Enter fullscreen mode Exit fullscreen mode

By default, an app created by command is bind the webpack configuration. We need them to run our compiled webassembly js module. So, I ejected it to a custom few in webpack.

$ cd react-wasm-docker
$ npm run eject
Enter fullscreen mode Exit fullscreen mode

The config/ folder appear and you can go to webpack.config.js to add a couple of lines.

webpack.config.js

These above lines tell webpack to ignore including path and fs. At this state now our react application should be ready. Next, create webassembly hello world

2. WebAssembly Hello World (C++ Emscripten)

We can write several supporting languages with WebAssembly such as Rust, Go, C, C++, and even python. The Webassembly itself has its own language similar to assembly language (explain it here will last for another article)

In react-wasm-docker directory, create another sub-directory name webassembly and create my-module.cpp file within it.

$ cd react-wasm-docker
$ mkdir webassembly
Enter fullscreen mode Exit fullscreen mode

my-module.cpp

Next, we need a shell script to build our .cpp module to .wasm file. So, I’ll create build.sh in the root directory of react-wasm-docker.

build.sh

This bash script will loop through all .cpp extension files in webassembly then compiled them into single js files (with base64 encoded binary wasm). emcc is a frontend for emscripten which optimized our single js files. Then copy all compiled files to src/wasm/

  • --bind : enables embind.

  • STRICT=1 : ignore the support of deprecated options to build.

  • SINGLE_FILE=1 : compile original source into one single js file. originally, it will be one js file and another wasm file.

  • ALLOW_MEMORY_GROWTH=1 : allocate memory for wasm module requiring memory. It is possible wasm module to consume memory more than the default of emscripten (16MB by default).

  • MALLOC=emmaloc : export malloc function (c++ build-in). JS files can import and use to allocate memory.

  • MODULARIZE=1 : compiled js file as a module which we can import as import something from ....

  • EXPORT_ES6=1 : turn JS code into JS6 module.

  • ENVIRONMENT=web : set the default to be run JS file on web browser. WASM can be imported from both web browser and server (like node).

We will compile it with emcc docker image by the below command in the root directory of our project.

$ docker run --rm -v $(pwd):/src trzeci/emscripten ./build.sh
Enter fullscreen mode Exit fullscreen mode

Thank you trzeci!

Now src/wasm/ should show my-module.js That is our wasm file to go.

3. Integrate Webassembly with React

Modify App.ts (or .js) in src/ directory.

App.ts in /src/

This file will import wasm all as myModule and console.log in browser console by calling sayHello() from wasm. Moreover, we create button with Hello Wasm text in HTML. If that button is clicked, then it’ll get a text from helloWasm() and set it in the middle of the page.

Now you can run

$ npm start
Enter fullscreen mode Exit fullscreen mode

You can go to localhost:[port]. The website should display as below.

locally server running React with loaded wasm file.

Now the application is running locally. We noticed there are several steps before reaching this point. How can we shorten it for other team members or scale it in the future? That is where containers come in.

4. Containerization with Docker and Nginx

At the root of our application, creating Dockerfile with instructions below.

Dockerfile

This docker file will multi-state build our project sequently.

  • Starting with building web assembly in our webassembly.

  • Next, move all wasm files to src/wasm and build all React applications.

  • Last, copy all files from the previous step (React and WebAssembly) to Nginx (Revert proxy server for web application).

If you noticed, we involve Nginx in the last step, so we need the Nginx configuration file. Let creating nginx.conf at the root of the application.

nginx.conf

To reduce size of docker image and skip unnecessary files. We need .dockerignore

.dockerignore

Everything is all set. We are ready to build our docker image and run it!

Build docker image

docker build -t react-wasm-docker .
Enter fullscreen mode Exit fullscreen mode

After the image is ready run it!

docker run --name react-wasm-docker-container -p 8080:8080 react-wasm-docker
Enter fullscreen mode Exit fullscreen mode

Now you can go to localhost:8080 The result page show appears below!

Running React and loaded wasm file with Docker container.

Although That’s all for everything, We have further improvement such as

  • WebAssembly is now locate in same repository of React. If project grow bigger, it would be harder to handle. We can implement Monorepo architecture to split them out.

  • This is just a setup project. I’ll apply it in a real project like Image Processing/Computer Vision/Microservices.

    All codebase is at Github: https://github.com/kanin-kearpimy/React-with-WebAssembly-and-Docker

Reference

Connect with me!

Top comments (0)