DEV Community

The Practical Developer
The Practical Developer

Posted on Originally published at practicaldevblog.blogspot.com

WebAssembly Explained: Near Native Speed Inside the Browser

WebAssembly, often shortened to Wasm, is a way to run code in the browser at near native speed, in a format that is not JavaScript. It was built for the parts of a web app where JavaScript is too slow or the wrong tool: image editing, games, video processing, and software originally written in another language. Instead of rewriting that software in JavaScript, developers compile it to WebAssembly and run it in the browser.

A WebAssembly module is a compact binary format that browsers can load and run safely. It runs in a sandbox, like JavaScript, so it cannot read your files or reach the network on its own. It can only do what the JavaScript around it allows, by calling functions JavaScript provides and by letting JavaScript call its exported functions. That boundary is deliberate. WebAssembly is a guest in the browser, powerful inside its sandbox and powerless outside it.

The smallest example is a function that adds two numbers, written in the text format for WebAssembly. This format is the human readable form of a module, and it shows the structure clearly.

(module
  (func (export "add") (param i32 i32) (result i32)
    local.get 0
    local.get 1
    i32.add))
Enter fullscreen mode Exit fullscreen mode

Read it as a recipe. The module contains one function, exported under the name "add". It takes two parameters, both 32 bit integers (i32), and returns one 32 bit integer. local.get 0 and local.get 1 push the two parameters onto a stack, and i32.add pops them, adds them, and leaves the result on the stack, which becomes the return value. In a real project you would not write this by hand. You would write the function in C, C++, Rust, or another supported language and compile it to a .wasm file, but the module you get has this same shape underneath.

JavaScript loads the module and calls the exported function. Here is the loading code for a module built from the example above.

const { instance } = await WebAssembly.instantiateStreaming(fetch("add.wasm"));
console.log(instance.exports.add(2, 3));
Enter fullscreen mode Exit fullscreen mode

The fetch call downloads add.wasm, instantiateStreaming compiles and creates an instance of it, and instance.exports.add calls the exported function with 2 and 3, printing 5. In practice, a real module exports more than one function, and JavaScript passes it memory and helper functions when it is created. The pattern stays the same: build in a compiled language, load in JavaScript, and call across the boundary only where speed or reuse justifies it.

WebAssembly is not a replacement for JavaScript. It has no direct access to the page, so it cannot change the DOM or handle a click on its own. JavaScript remains the language of the web page, while WebAssembly handles the heavy computation behind it. Used that way, the two complement each other: JavaScript for interaction, WebAssembly for number crunching, and a clear boundary between them.

The honest trade

WebAssembly trades simplicity for speed and reuse. Adding it to a project means adding a build step, a second language, and a boundary to debug across, which is real complexity for a small gain on an ordinary page. Where it pays off is clear: existing native code that would be expensive to rewrite, and workloads like codecs, simulations, and editors where JavaScript genuinely struggles. For most web pages, plain JavaScript is still the right answer, and WebAssembly should stay in the toolbox until the performance problem is real.

Try one small module first

The best introduction is one tiny module: a function written in a language you know, compiled to WebAssembly, and called from a small web page. Measure it against the JavaScript version, and keep WebAssembly only if the difference matters. That discipline, use it where it earns its place, is the whole skill.

Originally published at

https://practicaldevblog.blogspot.com/2026/11/webassembly-explained-near-native-speed.html

Top comments (0)