A comprehensive example demonstrating how to integrate Rust-compiled WebAssembly modules with Next.js applications. This project showcases the power of combining high-performance Rust calculations with modern React development.
WebAssembly (WASM) is a binary instruction format that allows code written in languages like Rust, C++, and Go to run in web browsers at near-native speed. It's designed to complement JavaScript, not replace it.
- Performance: Near-native execution speed
- Security: Runs in a sandboxed environment
- Portability: Works across different platforms and browsers
- Language Flexibility: Write in languages other than JavaScript
Rust is an excellent choice for WebAssembly because:
- Memory Safety: No garbage collector, predictable performance
- Zero-cost Abstractions: High-level features without performance overhead
- Excellent Tooling:
wasm-packmakes compilation seamless - Growing Ecosystem: Rich libraries and community support
This repository contains two main components:
βββ math/ # Rust WebAssembly Module
β βββ src/
β β βββ lib.rs # Rust math functions with WASM bindings
β β βββ main.rs # Optional standalone executable
β βββ pkg/ # Generated WebAssembly files
β β βββ math.js # JavaScript bindings
β β βββ math_bg.wasm # WebAssembly binary
β β βββ math.d.ts # TypeScript definitions
β β βββ package.json # NPM package configuration
β βββ Cargo.toml # Rust project configuration
β βββ README.md # Rust module documentation
βββ assembly-next/ # Next.js Frontend Application
βββ app/
β βββ page.tsx # Main application page
βββ components/ # React components
βββ hooks/ # Custom React hooks
βββ types/ # TypeScript definitions
βββ constants/ # Application constants
βββ README.md # Frontend documentation
The Rust code defines mathematical functions and exports them for use in JavaScript:
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn add(a: i32, b: i32) -> i32 {
a + b
}Key features:
#[wasm_bindgen]: Macro that generates JavaScript bindings- Type Safety: Rust's type system ensures reliability
- Memory Management: No garbage collection, predictable performance
The Rust code is compiled to WebAssembly using wasm-pack:
wasm-pack build --target webThis generates:
.wasmfile: The actual WebAssembly binary.jsfile: JavaScript wrapper for easy integration.d.tsfile: TypeScript definitions for type safety
The frontend application loads and uses the WebAssembly module:
// Dynamic import for code splitting
const wasmModule = await import("math");
await wasmModule.default(); // Initialize WASM
const result = wasmModule.add(5, 3); // Use Rust functionThis project features a fully automated build and deployment pipeline:
- Triggers: Automatically detects changes in
math/directory - Build Process: Installs Rust toolchain and compiles WebAssembly module
- Integration: Copies WASM files to Next.js app (
assembly-next/wasm-pkg/) - Auto-commit: Pushes updated WebAssembly binaries to repository
- Seamless Deploy: Automatically deploys when Next.js code changes
- No Rust Required: Vercel only builds pre-compiled WASM files
- Fast Builds: No runtime Rust compilation needed
# 1. Modify Rust code
echo "New function" >> math/src/lib.rs
# 2. Push changes
git add . && git commit -m "Add new feature" && git push
# 3. Everything else is automatic!
# β
GitHub Actions builds WASM
# β
Files copied to Next.js app
# β
Auto-commit with updated binaries
# β
Vercel deploys updated appπ Learn More: See
.github/workflows/wasm.ymlfor workflow details andVERCEL.mdfor deployment configuration.
export const useWebAssembly = () => {
const [mathModule, setMathModule] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
const loadWasm = async () => {
const wasmModule = await import("math");
await wasmModule.default();
setMathModule(wasmModule);
setLoading(false);
};
loadWasm();
}, []);
return { mathModule, loading };
};- Separation of Concerns: Each component has a single responsibility
- Type Safety: Full TypeScript support throughout
- Modern React: Uses latest React patterns and hooks
try {
const wasmModule = await import("math");
await wasmModule.default();
} catch (err) {
console.error("Failed to load WebAssembly:", err);
}- Node.js 18+ for the frontend
- Rust toolchain (for local development only)
- wasm-pack for building WebAssembly modules (for local development only)
π‘ Note: Thanks to automated CI/CD, Rust is only needed for local development. Production deployments use pre-built WASM files.
-
Clone the repository
git clone https://github.com/recepoksuz/Next.js-rust-web-assembly-example.git cd Next.js-rust-web-assembly-example -
Run the application (WASM files are pre-built)
cd assembly-next npm install npm run dev -
Open your browser Navigate to
http://localhost:3000
For Rust changes:
# 1. Modify Rust code
vim math/src/lib.rs
# 2. Test locally (optional)
cd math && wasm-pack build --target web && cd ..
# 3. Push changes - automation handles the rest!
git add . && git commit -m "Update Rust functions" && git pushFor Next.js changes:
# Standard Next.js development
cd assembly-next
npm run dev
# Make changes, then push - Vercel auto-deploys!This example demonstrates basic math operations, but WebAssembly is excellent for:
- Image/Video Processing: Filters, compression, format conversion
- Cryptography: Encryption, hashing, key generation
- Scientific Computing: Complex calculations, simulations
- Game Engines: Physics, rendering, audio processing
- Legacy C/C++ Libraries: Port existing codebases to the web
- Cross-Platform Logic: Share business logic between web and native apps
- Specialized Algorithms: Use domain-specific optimized code
β
CPU-intensive computations
β
Existing non-JavaScript codebases
β
Consistent performance requirements
β
Complex algorithms with lots of loops
β Simple DOM manipulations
β Network requests and API calls
β Small, infrequent calculations
β Code that heavily interacts with web APIs
-
Define in Rust (
math/src/lib.rs):#[wasm_bindgen] pub fn power(base: i32, exp: i32) -> i32 { base.pow(exp as u32) }
-
Rebuild WebAssembly:
cd math && wasm-pack build --target web
-
Update TypeScript types (
assembly-next/types/wasm.ts):export interface MathModule { power: (base: number, exp: number) => number; // ... other functions }
-
Use in React components:
const result = mathModule.power(2, 8); // 256
WebAssembly is supported in all modern browsers:
- Chrome 57+
- Firefox 52+
- Safari 11+
- Edge 16+
WebAssembly runs in the same security sandbox as JavaScript:
- Memory Safety: Cannot access memory outside its designated space
- Same-Origin Policy: Subject to the same security restrictions
- No Direct System Access: Cannot directly access file system or network
- Minimize Data Transfer: Reduce calls between JS and WASM
- Batch Operations: Process multiple items in single WASM call
- Use Appropriate Types: Match Rust and JavaScript data types
- Profile Your Code: Measure actual performance improvements
This example can be extended with:
- Multi-threading: Using Web Workers with shared memory
- SIMD Operations: Single Instruction, Multiple Data processing
- More Complex Data Types: Structs, enums, and custom types
- Error Handling: Comprehensive error propagation between Rust and JS
Contributions are welcome! Please feel free to submit issues, feature requests, or pull requests.
Thanks to our CI/CD pipeline, contributing is straightforward:
- Rust changes: Just modify
math/src/lib.rsand push - WASM builds automatically - Next.js changes: Standard React development workflow
- Documentation: Update and push - changes deploy automatically
This project uses automated pipelines for seamless development and deployment:
- π GitHub Actions:
wasm.yml- Automated WASM compilation - π Vercel Integration:
VERCEL.md- Production deployment guide - π Zero-Config: Push code β Automated build β Deploy
Recep ΓksΓΌz
- GitHub: @recepoksuz
This project serves as both a learning resource and a practical starting point for integrating WebAssembly into modern web applications. Whether you're looking to boost performance or leverage existing Rust libraries, this example provides a solid foundation for your WebAssembly journey.