Skip to content

federating some Wasm modules with webpack 5 module federation

Notifications You must be signed in to change notification settings

alexUXUI/wasm-federation-demo

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

26 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Federating Wasm Modules

Using Module Federation to dynamically federate Wasm modules across independent applications. In this demo, we will use Conways Game of Life to illustrate how Wasm can be shared.

Up and Running

  1. Make sure you have node.js installed locally
  2. From the root of the project run: yarn && yarn start.

This will start the Host and Remote applications in dev mode.

  1. The Host app is hosted on port 8080
  2. The Remote app is hosted on port 8081

Navigate to your browser and open the Host app running on http://localhost:8080. You should see a few buttons. Click the "Play" button to start the app. Click the "Stop" button (same button) to pause the execution. Press the "Tick" button to step through the execution frame-by-frame, and lastly click the "Reset" button to reset the app.

Module Federation

Webpack's Module Federation Plugin powers the sharing of the Wasm module between our two apps at runtime. Below is a low-fidelity diagram illustrating how webpack is used to share code.

💡 For more on Module federation, see the docs and checkout this write-up.

Diagram

As seen in the diagram above, the Host application imports a Wasm module from the Remote application. Under the hood, this import happens in an async boundary, which is created by webpack and wraps around the react app, giving webpack the opportunity to make an async HTTP call for the Wasm module.

The Wasm module on the left (purple) has a dotted line to represent that the Wasm code does not exist in the Host app until it is federated in at runtime.

Let's see how this is implemented in our webpack configs.

Host configs: packages/host/webpack.config.js

new ModuleFederationPlugin({
  name: "Host",
  remotes: {
    GameOfLifeModule: `GameOfLifeModule@http://localhost:8081/remoteEntry.js`,
  },
}),

Remote configs: packages/remote/webpack.config.js

new ModuleFederationPlugin({
  name: "GameOfLifeModule",
  filename: "remoteEntry.js",
  exposes: {
    "./GameOfLifeModule": "./pkg/",
  },
}),

The Remote app uses Webpack Module Federation to expose the Wasm module for consumption by the Host app. As pictured in the code snipet above, the ./pkg code will be made available through the http://localhost:8081/remoteEntry.js file.

Wasm

The GameOfLife Wasm module, pictured above as GameOfLifeModule, contains the logic for Conways Game of Life. The source code for this particular implementation was borrowed from The Offical Rust Wasm Docs.

The consumption and usage of our Wasm module can be found in the packages/host/app.jsx file on lines 2 and 12.

On line 2 we are importing the federated Wasm module:

import * as GameOfLife from "GameOfLifeModule/GameOfLifeModule";

and on line 12 we are consuming the module:

GameOfLife.then(({ Universe }) => {
  if (!cells) {
    setCells(Universe.new());
  }
});

In the example above, the Wasm Module exports a class Universe which we use to initialize a new Game Of Life. We then set the instance of the new Universe in a slice of react state on the same line, and refernce the Universe as cells throughout the rest of the component. This allows us to use react to control a Wasm module that is being federated into react from a completely stand-alonle remote app.

Local Development

In order to run the Rust->Wasm toolchain, please make sure you have the project dependencies in the next section installed.

Once those are installed, go to packages/remote/webpack.config.js and uncomment the code that has been commented out.

you can start developing on the Remote app or the Host app with yarn start.

💡 For local development of Host app, make sure that the Remote app is also running so that the import of the Wasm module does not fail. You can start both apps by running yarn start in the top-level dir.

Project Dependencies

Install Rust

$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

Source your bash profile after the step above (source $HOME/.cargo/env)

Install wasm-pack

$ curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh

Packages Overview

This mini monorepo consists of two packages. Here is a bit more about each.

Packages/Host

Consumer of federated Wasm module. Uses React to interact with the federated Wasm module but could also be written in plain JavaScript like the Remote.

Packages/Remote

Exposes Wasm module. Wasm module is built with Rust, compiled by webpack wasm-pack loader.

This package was bootstrapped with the Rust Webpack Template project. For more, visit their repo as well as the fabulous docs at the Rust Wasm webiste.


Acknowledgements and Credits

This demo is built upon many OSS projects including:

About

federating some Wasm modules with webpack 5 module federation

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published