Quick Links

WebAssembly is a new way to run code on the web. With huge tech companies behind it, it's poised to revolutionize the way we write web applications, but comes with its own quirks and limitations. Are WASM frameworks a viable competitor to JavaScript libraries like React?

What Is WebAssembly?

WebAssembly, or WASM, is the second universal programming language that all web browsers can understand and run. However, you're not going to be writing scripts in WebAssembly yourself---it's a low level assembly language, designed to be very close to compiled machine code, and very close to native performance.

Wasm can be used as a portable compilation target for other languages

The magic of WebAssembly is that it's low level enough that it actually is an easy compilation target. Any reasonably fast language must go through a compiler at some point, even JIT compiled languages like JavaScript, and usually that means compiling to x86 or ARM machine code to run on modern processors.

However, you can also compile to a different format; usually this ends up being a "lower level" language that's closer to the eventual machine code. For example, Java compiles to Java bytecode which is sent to the JVM runtime, and C# compiles to Microsoft Intermediary Language (MSIL) which is sent to the .NET runtime. You can even "transpile" languages, from one high level language to another, most commonly extensions like TypeScript to JavaScript, but also weirder ones you wouldn't expect, like Python to JavaScript, though that is usually messy and bug ridden.

WASM is just an intermediary language that is easy to compile to. In fact, it's almost exactly the same concept as Java bytecode and C# MSIL---both of these formats make it easy to run the same code cross platform, using the same format running on specific runtimes made for each platform.

What this means in practice is that JavaScript is no longer the only language you can run on the web. Web browsers can run any language now, if that language has a WebAssembly compiler.

Even traditional desktop languages like C++ and Rust can be compiled down to WASM with relative ease; AutoDesk was able to port their 35 year old C/C++ codebase over to WASM in a few months, and Google ported Google Earth, both of which render complex 3D scenes and run at near-native performance. The Unity game engine also can run in WASM.

WASM currently runs in 94% of user browsers, with IE, UC browser, and Opera Mini support being the main things holding it back, as per usual. However, it's backed by developers from Mozilla, Microsoft, Google, and Apple, and its support in modern browsers is fast-moving. Like most web standards, it's currently managed by the W3C standards organization.

JavaScript Isn't The Only Option Anymore

Great, so what does this mean for everyone? Well, while running DOOM 3 in a web browser is certainly a cool demo, it's not exactly game changing.

Until now, JavaScript has been your only choice to make your web pages interactive. Whether you love it or hate it, it was never designed to be used like it is today. It was a scripting language designed to do trivial tasks like making dropdown menus animate, and over 25 years has been hacked together to run modern-day workloads. Only through the use of state-of-the-art JS engines and JIT compilation optimizations can it even be compared to native speeds.

And so, as web pages grew to become full web applications, JavaScript client frameworks like React, Vue, and Angular propped up to meet the demand. Of course, there are still server-side frameworks---you're reading this from WordPress, a PHP framework---but client frameworks offer huge performance increases. With a client framework, the DOM is updated automatically after pressing a button or interacting with the app. Even realtime server-rendered frameworks must make a network request to change anything, and in the worst case, must refresh the entire page.

The innovation that the web really needs is proper competitors to frameworks like React, written in languages that aren't JavaScript.

While all of the web's frontend code is written in JavaScript, the backend code is often not. In high performance datacenter workloads, it's often beneficial to use proper desktop languages like C#, C++, Rust, and Go. After all, these can literally save you money by requiring fewer servers to meet the same demand.

However, it also costs you money in development time, since now you have to deal with interoperability between your C# backend, and your JavaScript frontend. Simply not being able to share code, models, and libraries may increase your development complexity by up to 2x what it would be with a unified system. This reason alone is why NodeJS server backends are so popular, despite sounding like a terrible idea 20 years ago.

Having the ability to write C#, C++, Rust, and Go code that runs on the server and client would open the door to many more options, and remove the need for JavaScript as a programming language almost entirely. In the WASM client framework Blazor, JavaScript usage is reserved for interoperability with existing client packages, and basic scripting.

How Do WASM Client Frameworks Work?

Since WebAssembly is just a way to run code in a sort of "WebAssembly environment," you can think of it like running a Docker container. For example, Microsoft's Blazor framework (by far the most popular WASM client framework so far) has two modes of operation:

  • Blazor Server, which runs all the processing and rendering on the server, and sends updates to the HTML DOM over a WebSocket, and
  • Blazor WebAssembly, which does the exact same thing, except now the processing and rendering is done on the client, through a .NET runtime compiled for WASM.

In the latter case, the WebSocket connection is replaced with a direct link to the DOM, through JavaScript as WebAssembly currently has no way to modify the DOM directly without calling JS APIs. You also need JavaScript in any case to "bootstrap" the WASM app, so JS is not going away anytime soon.

Beyond that, WASM client frameworks work in general like any other framework, and the exact details will depend on the implementation.

For example, Blazor keeps an internal state and triggers re-rendering of the app when a button is clicked or input is made. It constructs new HTML using C# code running on WASM, and then sends that HTML to the JavaScript APIs to apply to the DOM. Doing this on WebAssembly takes processing load off the server and makes the client fast and responsive. Even DOM access through JavaScript is a bit slower, it's still leagues faster than the alternative---DOM access over the internet.

How Much Faster Are We Talking?

The question of "how much faster is WASM?" is hard to pin down. It's clearly faster overall, there's no doubt about that, but in some cases it's more complicated than that.

DOM access is still a problem as it must be done through JavaScript, so it's going to be as slow as JavaScript. This is getting fixed soon though. Sometimes, JavaScript can be faster in specific benchmarks that the WASM compiler might be struggling with, simply on account of the fact that JS has 25 years of compiler iteration behind it.

For high-performance applications that need a lot of processing power, like games and applications, WASM is usually anywhere from 1.5x - 2x faster. But it might be the same speed. It also might be 20% slower than JavaScript. It also might be 10x faster for some functions. There are benchmarks out there showing all of these results, so the only thing that can be said for sure is that your mileage will vary.

Compared to native code, it's likely to always be slower than the language it's compiling from. So while it's probably going to be fast, there are a lot of caveats, and you shouldn't be using WASM with the expectation of getting native performance on the web.

With that all being said, WASM doesn't need crazy performance to be revolutionary. It just needs to work, not be slow, and support many languages.

What Frameworks Work Right Now?

The most important one by far is Blazor, being developed by Microsoft. It's the first WASM client framework being backed by a major company, and will probably be the catalyst for WASM to finally get the mainstream adoption it deserves.

Blazor WASM is only a year old, with Blazor Server being released 3 years ago, but the great thing about Blazor is that it's just an extension of ASP.NET, a 20 year old web framework that Microsoft has been constantly improving. You can use many frontend libraries already written for ASP.NET, and it's likely to be the only framework backed by a web package manager rivaling NPM.

This isn't some side project either---Microsoft has been pushing Blazor as much more than just a web framework; it's their next application programming model. They're working on Blazor Desktop, releasing in late 2021, which works a lot like Electron does to run the same Blazor web apps on the desktop. They clearly care a lot about it, which is great news for WASM in general.

If you'd like to learn more, you can read our guides on what Blazor is, and how to get started using it.

The other production-ready framework is Yew, built on Rust, a modern language similar to C++, except with memory safety due to the weird way it handles references. Yew is fast, supports a component based model like React, and has interoperability with JS APIs.

asm-dom is a library written for C++, that doesn't do more than hook up C++ code to the DOM. Obviously you will need to bring-your-own-framework here, but most developers crazy enough to write web apps in C++ will likely do that anyway. It also has support for falling back to asm.js, an early version of what WebAssembly was trying to be. It's basically a subset of JavaScript restricted to only using integers (i.e., only bytes, not objects), which makes it easier to transpile C++ code to, as that's basically all C++ code uses at the end of the day. Having this support isn't very useful though as there are very few environments that won't support WASM but will support asm.js.

Vugu is a framework written in Go, supports components and is modeled after Vue syntax, but is still experimental. There's also Vecty, which also a popular Go framework.

The Future Of WebAssembly

This has all focused on client web frameworks using WASM to manipulate the DOM and build applications. But, you can also just port entire desktop applications to the web. That's what Uno does---uses WASM to run Universal Windows Platform (UWP) apps directly in a web container, which also comes with the added benefit of being completely cross-platform. It's actually a bit uncanny how well this works, and really feels like you're using a native Windows app. You can check it out yourself in their gallery.

There's a lot more to the WASM ecosystem than just these. If you'd like to learn more, you should read through the awesome-wasm compilation on GitHub, which lists a bunch of popular projects.

The most notable one that we didn't mention here is WASI---a way to run WebAssembly portably on any system using a standardized system interface. As WASM becomes more and more performant, WASI could prove to be a viable way to run any kind of code on any kind of system, similar to how Docker works but without the restriction on OS. In fact, Solomon Hykes, the creator of Docker, has endorsed it wholeheartedly:

WebAssembly is only a few years old. It still has plenty of room to grow, and is still picking up speed. It's not unreasonable that five years from now, frameworks like Blazor and Yew will be just as common as React, Angular, and Vue.

This could be argued to be fragmenting the web ecosystem, but WASM is cross platform. WAPM, a WASM package manager, may become the go-to way to share libraries between frameworks of different languages.

In any case, web frameworks running on WebAssembly have huge potential, and with Microsoft personally backing one, we're confident that they're the future of the web.