I messed up the first iteration. Badly.
When I started building Kreotar's developer toolkit (JSON formatter, Base64 encoder, hash generators - you know the drill), I thought "hey, let's just use standard JavaScript string manipulation." Fast forward to processing a 50MB JSON file, and I watched the main thread freeze like a deer in headlights. The browser tab became unresponsive for 8 seconds. Users were angry. I was embarrassed.
That's when I went all-in on WebAssembly.
The WASM Architecture Behind the Tools
Instead of parsing heavy text operations in JS, I compiled Rust code to WASM for the heavy lifting. Here's the core architecture:
rust
#[wasm_bindgen]
pub fn format_json(input: &str, indent: usize) -> Result<String, JsValue> {
let value: serde_json::Value = serde_json::from_str(input)
.map_err(|e| JsValue::from_str(&format!("Parse error: {}", e)))?;
let formatted = serde_json::to_string_pretty(&value)
.map_err(|e| JsValue::from_str(&format!("Format error: {}", e)))?;
Ok(formatted)
}
import { wrap } from 'comlink';
import wasmWorker from './wasm.worker?worker';
const useWasmTool = () => {
const [processing, setProcessing] = useState(false);
const processData = async (input, operation) => {
setProcessing(true);
try {
const worker = new wasmWorker();
const wasmModule = wrap(worker);
const result = await wasmModule[operation](input);
return result;
} finally {
setProcessing(false);
}
};
return { processData, processing };
};
Why This Matters
The Base64 encoder handles 100MB files in under 2 seconds. The JSON formatter validates nested structures without crashing the tab. The hash generators (SHA-256, MD5, etc.) process files locally - your data never touches my server.
I learned the hard way that JSON.parse() has limits. WASM doesn't magically fix everything, but when combined with Web Workers, it creates a truly non-blocking experience.
The "oops" moment: I initially tried to pass massive strings directly between JS and WASM. Memory copying killed performance. Switching to SharedArrayBuffer for large payloads changed everything. Here's the pattern that actually works:
const processLargeFile = async (fileBuffer) => {
const wasmMemory = new WebAssembly.Memory({
initial: 256,
maximum: 512,
shared: true
});
const result = await wasmModule.process_buffer(wasmMemory);
return result;
};
What I'm building next: A client-side regex tester that can handle multi-line 10MB log files without lag. Because waiting 5 seconds for a regex match is unacceptable.
What's your WASM use case? I'm curious if others are hitting these same JS performance walls.
Top comments (0)