Unit 7.3 · Tutorial 2
WebAssembly & Microfrontends
Chapter 23 · Capstone Project
~2.5 hours
Advanced
WebAssembly · Microfrontends · Module Federation
Overview
This tutorial explores two powerful architectural patterns: WebAssembly for
high‑performance computation in the browser, and microfrontends for scaling
frontend development across teams. You'll learn to compile code to Wasm,
run it in the browser, and build composable frontend applications using
module federation.
Why this matters:
WebAssembly brings near‑native performance to the web. Microfrontends enable
large organisations to scale frontend development across multiple teams.
1. Introduction to WebAssembly
WebAssembly (Wasm) is a binary instruction format that runs in browsers with
near‑native performance. It's designed to complement JavaScript.
- Performance: Faster than JavaScript for compute‑intensive tasks.
- Language support: C, C++, Rust, Go, and many others compile to Wasm.
- Security: Runs in a sandboxed environment.
- Use cases: Games, video editing, cryptography, data processing.
// Example: Fibonacci in WebAssembly (Rust)
// lib.rs
#[no_mangle]
pub extern "C" fn fibonacci(n: i32) -> i32 {
match n {
0 => 0,
1 => 1,
_ => fibonacci(n - 1) + fibonacci(n - 2)
}
}
2. Compiling to WebAssembly
Rust to Wasm
# Install wasm-pack
cargo install wasm-pack
# Create a new library
cargo new --lib wasm-fib
cd wasm-fib
# Add wasm-bindgen dependency
[dependencies]
wasm-bindgen = "0.2"
# Build the wasm package
wasm-pack build --target web
C/C++ to Wasm
// fib.c
int fibonacci(int n) {
if (n <= 1) return n; return fibonacci(n - 1) + fibonacci(n - 2); } // Compile with Emscripten
emcc fib.c -o fib.js -s WASM=1 -s EXPORTED_FUNCTIONS='["_fibonacci"]'
Go to Wasm
// main.go
package main
import "syscall/js"
func fibonacci(n int) int {
if n <= 1 { return n } return fibonacci(n-1) + fibonacci(n-2) } func main() { c
:=make(chan struct{}) js.Global().Set("fibonacci", js.FuncOf(func(this js.Value,
args []js.Value) interface{} { n :=args[0].Int() return fibonacci(n) })) <-c } //
Build: GOOS=js GOARCH=wasm go build -o main.wasm
3. Running WebAssembly in the Browser
Use the WebAssembly JavaScript API to load and run Wasm modules.
// Load and run Rust Wasm module
import init, { fibonacci } from './pkg/wasm_fib.js';
async function run() {
await init();
console.log('Fibonacci(10):', fibonacci(10));
}
run();
// Or use the WebAssembly.instantiate API
async function loadWasm() {
const response = await fetch('fib.wasm');
const bytes = await response.arrayBuffer();
const { instance } = await WebAssembly.instantiate(bytes, {
env: {
// Import functions here
}
});
console.log('Fibonacci(10):', instance.exports.fibonacci(10));
}
// React component using Wasm
function WasmFibonacci() {
const [result, setResult] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
async function load() {
const { fibonacci } = await import('./pkg/wasm_fib.js');
await init();
setResult(fibonacci(40));
setLoading(false);
}
load();
}, []);
if (loading) return
Loading Wasm...
;
return
Fibonacci(40): {result}
;
}
4. Microfrontends Architecture
Microfrontends apply microservice principles to the frontend. Each team owns
a feature, and applications are composed at runtime.
Benefits
- Team independence: Teams deploy independently.
- Technology diversity: Each team chooses their stack.
- Incremental upgrades: Migrate one part at a time.
- Scalability: Teams scale independently.
Challenges
- Integration complexity: Routing, state sharing.
- Consistency: Design system and branding.
- Performance: Bundle size and loading strategy.
5. Module Federation (Webpack 5)
Module Federation allows sharing code between applications at runtime.
// webpack.config.js (Host App)
new ModuleFederationPlugin({
name: 'host',
remotes: {
shop: 'shop@http://localhost:3001/remoteEntry.js',
cart: 'cart@http://localhost:3002/remoteEntry.js',
},
shared: {
react: { singleton: true },
'react-dom': { singleton: true },
},
});
// Webpack.config.js (Remote App - Shop)
new ModuleFederationPlugin({
name: 'shop',
filename: 'remoteEntry.js',
exposes: {
'./ProductList': './src/ProductList',
},
shared: {
react: { singleton: true },
'react-dom': { singleton: true },
},
});
// Using the remote component in the host app
const ShopProductList = React.lazy(() => import('shop/ProductList'));
function App() {
return (
Host Application
Loading Shop...
}>
);
}