Understanding WebAssembly (Wasm) and Its Role in Modern Web Development

web performanceweb developmentwasm
timeToRead7 min read

Author
Sergey Kualkov is software expert with 10+ years of experience. He has worked in Healthcare, Automotive, Radio, Education, Fintech, Retail E-commerce, Business Sector, Media and Entertainment. Sergey led the development of 20+ products, and successfully re-engineered the business process for established products, which allowed those products to grow the user base and revenue up to 5 times
Understanding WebAssembly (Wasm) and Its Role in Modern Web Development

Every platform and programming language comes with its own set of advantages, features, and drawbacks. One prominent limitation of JavaScript and its execution environment is performance optimization. For developers accustomed to native code, optimizing JavaScript can be particularly challenging, as it requires accounting for a wide variety of browser-specific quirks and optimizations.

Over the years, there have been numerous efforts to standardize JavaScript and its underlying runtime environment, particularly through ECMAScript (the specification for JavaScript). In this context, WebAssembly (Wasm) emerges as an important innovation that addresses some of these performance challenges, offering a way to optimize and efficiently use third-party code in browsers.

What is WebAssembly (Wasm)?

WebAssembly allows developers to write code in statically typed, high-performance languages such as C, C++, Rust, Go, and others. This code is then compiled into the WebAssembly binary format, which is executed in a virtual machine within the browser. The key advantage of WebAssembly is that it operates as a portable, low-level abstract syntax tree, which facilitates faster parsing and more efficient execution than JavaScript.

WebAssembly code can be executed both in the browser and on the server, allowing for broad application in web development. As a result, developers can use the same codebase for performance-critical tasks across different environments.

Key Features of WebAssembly:

  1. Portability: Wasm code can run in any browser that supports it, which includes all major browsers as of 2017 (Chrome, Firefox, Edge, Safari, etc.).
  2. Security: Wasm is designed with a focus on security, ensuring that compiled code is sandboxed, preventing malicious operations.
  3. Performance: Wasm allows code to run at near-native speed, significantly outperforming traditional JavaScript for certain tasks.
  4. Compatibility: WebAssembly is supported by a wide range of programming languages, and it integrates seamlessly with JavaScript, allowing developers to call Wasm functions from JavaScript and vice versa.

What Problem Does WebAssembly Solve?

One of the key challenges in web development is achieving optimal performance for computationally intensive tasks in the browser. While Just-In-Time (JIT) compilation is often used to optimize JavaScript performance, it is not always fast enough for certain use cases. WebAssembly provides a solution by enabling native code execution within the browser at near-native speeds.

The technology has been supported by all major browsers since October 2017, and it has come with several essential requirements for adoption:

  1. Security: The compilation process must not introduce new vulnerabilities or security risks.
  2. Compatibility: WebAssembly must be executable in modern browsers without requiring third-party tools.
  3. Cross-Platform: It should work seamlessly across all supported browsers.
  4. Ease of Use: Developers should be able to integrate WebAssembly into their workflows easily.

Older browsers can still support WebAssembly through asm.js polyfills, ensuring backward compatibility.

Historical Context: What Came Before WebAssembly?

Before the advent of WebAssembly, there were several technologies that attempted to bring native code execution to the web. However, most of these failed to gain widespread adoption due to limitations in performance, security, or cross-platform compatibility. Some of these technologies include:

  • NaCl (Native Client): A Google project that allowed C and C++ code to run in the browser but had limited support and raised security concerns.
  • PNaCl (Portable Native Client): An extension of NaCl that aimed to make native code portable across platforms but still struggled with adoption.
  • ActiveX: A Microsoft technology that allowed components to be embedded in web pages, but it was only supported by Internet Explorer.
  • ActionScript/Flash: While Adobe Flash enabled rich multimedia content in browsers, it suffered from performance issues and security vulnerabilities.
  • Silverlight: A Microsoft technology similar to Flash that also failed to achieve broad adoption.

These technologies were ultimately limited by factors such as platform-specific dependencies, poor performance, or security issues, which led to their decline. In contrast, WebAssembly is designed to overcome these challenges.

The Role of asm.js

Before WebAssembly, asm.js served as a precursor to Wasm, offering a way to compile C/C++ code to JavaScript using the Emscripten compiler. While it enabled near-native performance in the browser for computationally intensive tasks, it still had some limitations, such as large file sizes and slower performance compared to native code.

Wasm improves on asm.js by offering:

  • Better performance: WebAssembly is a binary format, which is much more compact and faster to parse than JavaScript.
  • More efficient execution: WebAssembly allows for faster execution of low-level code, making it a better fit for performance-critical applications.
  • Language support: Wasm supports a wider range of languages, including C, C++, Rust, and more.

An example of asm.js code would look like this:

C Code Example (Before Compilation):

#include <stdio.h>

int add(int a, int b) {
    return a + b;
}

int main() {
    int result = add(10, 20);
    printf("The result is %d\n", result);
    return 0;
}

Compiled asm.js Code:

// This is a generated asm.js file (simplified)
var Module = {
  add: function (a, b) {
    a = a | 0; // Ensure a is an integer
    b = b | 0; // Ensure b is an integer
    return (a + b) | 0; // Perform addition and return result
  },
  _main: function () {
    var result = Module.add(10, 20);
    console.log("The result is " + result);
    return 0;
  },
};

Module._main(); // Execute the main function

While this code may appear unusual, asm.js significantly increased performance (by up to 1000%) compared to standard JavaScript. However, WebAssembly builds on this by providing an even more efficient binary format that is 50%-70% faster than asm.js.

WebAssembly in Practice

WebAssembly offers several key advantages in practice:

  • It uses a compact binary format, making it faster to load and parse.
  • It supports a range of high-performance native languages (e.g., C, C++, Rust, Go).
  • It is executed within the browser and can be called directly from JavaScript, offering seamless integration with existing web applications.

Here’s a simple example of how to use WebAssembly:

  1. Write the C Code (for example file - add.c):
#include <stdio.h>

int add(int a, int b) {
    return a + b;
}

int main() {
    int result = add(10, 20);
    printf("The result is %d\n", result);
    return 0;
}
  1. Compile the C Code to WebAssembly:

Using the Emscripten compiler, you can compile the C code to Wasm:

emcc add.c -o add.wasm -s WASM=1 -O3
  1. Load and Use the WebAssembly Module in HTML:
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>WebAssembly Example</title>
  </head>
  <body>
    <h1>WebAssembly (Wasm) Example</h1>
    <button id="call-wasm">Add Numbers with Wasm</button>
    <div id="result"></div>

    <script>
      const wasmFile = "add.wasm";
      let wasmModule;

      fetch(wasmFile)
        .then((response) => response.arrayBuffer())
        .then((bytes) => WebAssembly.instantiate(bytes))
        .then((module) => {
          wasmModule = module.instance;

          document.getElementById("call-wasm").addEventListener("click", () => {
            const a = 5;
            const b = 7;
            const result = wasmModule.exports.add(a, b);
            document.getElementById(
              "result"
            ).textContent = `Result from Wasm: ${result}`;
          });
        })
        .catch((err) => console.error("Failed to load Wasm module", err));
    </script>
  </body>
</html>

Real-World Use Cases of WebAssembly

WebAssembly has already found practical applications in a range of industries. Some of the most notable examples include:

  1. Game Engines: The Godot engine utilizes WebAssembly for browser-based gaming.
  2. Augmented and Virtual Reality (AR/VR): WebXR and Unity have embraced Wasm for AR/VR applications.
  3. Virtual Machines: WebAssembly can be used to run virtual machines in the browser.
  4. 3D Design Tools: Applications like Figma and AutoCAD use Wasm to enable complex 3D modeling in the browser.
  5. Audio and Video Codecs: Wasm powers high-performance codecs for media playback.
  6. Custom Databases: WebAssembly is used to build custom in-browser databases with better performance than JavaScript.

Read small new about ability of using PHP online

Conclusion

WebAssembly is a powerful tool that significantly enhances the performance of web applications by allowing developers to run native code in the browser. With support for multiple programming languages, a compact binary format, and cross-browser compatibility, Wasm opens up new possibilities for high-performance web applications. Whether you're building games, AR/VR experiences, or computationally intensive applications, WebAssembly provides a modern solution to many of the performance limitations previously faced by web developers.

Author
Sergey Kualkov is software expert with 10+ years of experience. He has worked in Healthcare, Automotive, Radio, Education, Fintech, Retail E-commerce, Business Sector, Media and Entertainment. Sergey led the development of 20+ products, and successfully re-engineered the business process for established products, which allowed those products to grow the user base and revenue up to 5 times