Introduction  /  What is WebAssembly

What is WebAssembly

I know I said it's going to be a practical and interactive course. It is, promised, but before that, we need to cover some ground and understand what WebAssembly is, how it stands out, and what it's not. This will help you with your mental model for WebAssembly.


For a long time, JavaScript has been the only natively supported programming language on the Web. However, the web is evolving at a rapid pace and Web applications are becoming increasingly more sophisticated. This has sparked an appetite for portable, secure, small and high-performance code on the Web. In 2015, Mozilla announced they joined forces with Google, Microsoft, and Apple engineers to create a new standard called WebAssembly (short Wasm). WebAssembly can be described as a platform-independent, low-level assembly-like language with a compact binary format that is safe and fast to execute with near-native performance. In addition, it serves as a compilation target for the Web. Let's unpack each of these characteristics individually:

Binary Format

In short, a binary format is a number-based representation of the source code that is easy to understand for machines.

Compilation Target

WebAssembly is a compilation target, which means that native code (such as Rust, C++, or Golang) gets compiled into WebAssembly. However, there's something in between called the Intermediate Representation (IR). This IR is then compiled into WebAssembly bytecode.

An intermediate representation is any representation of the code or program between the source code and the target language (often machine code). For example, with Node.js you can print V8's bytecode of JavaScript code using --print-bytecode. V8's bytecode is also an IR generated by Ignition, an interpreter, before the bytecode is then turned into optimized machine code by V8's optimizing compiler called TurboFan.

While many languages compile to WebAssembly through an IR, it's worth noting that WebAssembly Text Format (WAT) can be compiled directly to WebAssembly bytecode in a single pass, without requiring an intermediate representation.

The reason that it's compiled into an IR first is because a compiler (such as LLVM) supports many input languages and many compilation targets. By using an IR, the compiler can apply performance optimizations on the IR, which means it can reuse the same optimizations for every combination of input languages and compilation targets.

Many languages use LLVM to compile to Wasm, but there are also plenty of languages that use their own custom compiler. Here's a list of languages that currently compile to WebAssembly.

What's great about Wasm and that it's a compilation target is that it allows us to run native code on the Web and other environments, which wouldn't be possible otherwise. It goes in tandem with JavaScript and creates a beautiful synergy.

The fact that WebAssembly is a compilation target doesn't, however, mean we can't write it by hand. It would be painful if we had to write bytecode, but luckily there's a textual representation called WebAssembly Text Format (WAT). More on that later.

Platform-Independent

WebAssembly is language-, hardware-, and platform-independent, meaning it executes on a variety of devices (including IoT devices), operating systems and instruction sets, on the Web, and off the Web.

Low-Level

WebAssembly is low-level because it provides little abstraction over machine code. I am saying little because WebAssembly is not quite machine code but it's bytecode that is much closer to the hardware than for instance JavaScript, which is a high-level programming language that is not compiled (at least not ahead of time) into either bytecode or machine code. While most browser engines compile JavaScript just in time (JIT), WebAssembly is compiled into bytecode ahead of time (AOT).

Compact

The binary format is designed to be small and fast to download which improves startup performance. WebAssembly's binary format is fairly compact and even smaller than compressed and minified JavaScript. The smaller it is, the faster it can be transmitted over the network, and therefore reduce load times, save bandwidth and improve overall site performance.

Safe

We all want our code to run fast, but we also shouldn't neglect safety. It's necessary to prevent programs from compromising user data or system state, especially when compiling memory-unsafe C or C++ programs to WebAssembly or when leaving the browser's security sandbox. Wasm is designed with security in mind.

Fast

WebAssembly allows for a faster startup time because its bytecode is a dense representation of module information that allows for small files, and enables fast decoding. It can be natively decoded much faster than JavaScript can be parsed. The reason is that binary formats are generally faster to parse, especially ones that are designed specifically for fast decoding like WebAssembly.

Furthermore, WebAssembly is statically typed, and the low-level code emitted by, e.g., LLVM, is optimized ahead-of-time. This means that many optimizations are already done during compilation, rather than having to be performed at runtime like with JavaScript.

While downloading and parsing are unavoidable, performance may also depend on factors such as the VM fully optimizing the code before executing it. However, modern engines like V8 use a baseline compiler to start execution quickly while performing more advanced optimizations in the background. This tiered compilation approach helps balance startup time with peak performance.

In addition, WebAssembly has predictably good performance because it can be optimized well without runtime information (see ).

Debugger
    • Not paused
    • Not paused
    • Not paused
  • Not paused