why i use web assembly

WebAssembly (abbreviated “WASM”) is one of my favorite pieces of technology. It pushes the boundaries of what web applications are and what they can do. Did you know that today, you can just npm install @ffmpeg/ffmpeg and have a WASM build of FFmpeg that runs entirely in your browser? Those ad-flooded online file converters that everyone uses (because they’re just one web search away, really) can now work entirely on the client and become “offline file converters”!

However, @ffmpeg/ffmpeg is just one of the many use cases for WebAssembly (porting existing native code to the web platform). For many, WebAssembly is mostly a way to get an extra performance boost. Figma for example, has built a custom vector graphics renderer in C++, and while running languages like C++ in the browser predates WebAssembly1, using it cut Figma’s load time by 3x.

WebAssembly also has very interesting isolation properties that make it very useful outside of the browser as well. Companies like Wasmer are betting on WebAssembly to change the way we distribute cross-platform applications and deploy cloud services. Had it appeared in the 2000s, we may have never had Docker!

But perhaps surprisingly, none of these are the reason why I use WebAssembly today.

web assembly as the engine of application state

Let’s go back to our file converter example. Now, I’ve never built an “online file converter” myself but I’m pretty sure it works something like this:

  1. You upload a file to a server.
  2. The file gets stored in a temporary location.
  3. The server performs the conversion, possibly resulting in a new temporary file being created somewhere.
  4. The server notifies the app (somehow) that the file is ready and provides a link to download the converted file.

As the application goes through these steps, it must continuously communicate its progress to the user. This would typically be represented as a status message such as “uploading,” “conversion in progress” or “file ready.” For longer operations, users expect a progress bar to report… well, the current progress of the operation. All of this in real time!

Displaying the current state of the application can introduce a lot of complexity and there are many, many ways we could solve this:

As with most things in software engineering, each solution comes with a different set of tradeoffs: polling is easy to implement but can be inefficient, streams are instantaneous but require a bit more work, emails are reliable but might end up in spam, and your buzzwords might be out of fashion by the time you ship.

Now what if instead, we used WebAssembly to perform the conversion directly on the client? This comes with its own set of challenges, surely — challenges that probably deserve an article of their own. But no server round trips would be necessary to know what state the application is in. It is also much cheaper to host: the entire application can just be a static site serving HTML, CSS, JavaScript, WebAssembly and maybe some images for looks. Maybe you won’t even need ads anymore 😃! (surely this is going to rid us of ads, right? …right?)

web apps vs desktop apps on the web

Saying all web apps should give up their servers and switch to WASM would be silly (I am silly 😋!). You often need a centralized server to act as a trusted authority between users. Or as a data store that clients can access from any device. If your application is just a bunch of <form>s that submit data to a server, which then authorizes the request before running some SQL on a database… yeah WebAssembly isn’t going to particularly change the way you code. And that’s okay!

But if you’re building a “desktop app,” it might be very beneficial for you to use WebAssembly to also provide a web version of your app.

WebAssembly is missing $feature which means it will be slow for us! We need maximum performance and all the features!!!

One of the original goals of WebAssembly was to provide a better format than JavaScript for compilers to target when building for the web. And while it can achieve close-to-native speed, matching the speeds that can be reached with native code can be difficult. Plus, outside of performance considerations, you’re still limited by what web APIs and browsers allow you to do (at the time of writing, Safari still doesn’t support the Web MIDI API).

But that’s okay.

Now here’s the real deal: nobody starts as a regular user. That, and you are probably competing with many other solutions. When I look for a tool to do something quick, I do not want to be downloading and installing an entire program. I will probably only use it once, and if it isn’t exactly what I was looking for, it would have simply made me waste my time.

But we can’t afford maintaining two versions!

Ah yes, I am glad you point that out.

web assembly as a universal binary format

Finally, we reach the juicy part. My favorite way to use WebAssembly is as a way to share code between platforms. Write the core logic of your application in Ru… a language that can easily compile to native code and WebAssembly 😊. In this architecture, most of your code is shared between the “native” and the “web” variants of your app. Maybe some platform-specific features will need to be turned on or off with compile-time flags, but if you’re building a cross-platform app, you are probably already dealing with different code paths for different platforms anyway. With WebAssembly, the web just becomes another platform to target!

But I still have to build an entire frontend just for the web!

Not if you also use web technologies to build the GUI of your “native” apps 🙃

(this is the part where I’m happy about not having a comment section)

A personal favorite of mine in this space is Tauri, an alternative to Electron that uses the system web view instead of shipping the entirety of Chromium with your app. Tauri’s architecture splits your app in two processes: a “core” process, running native code with full access to the operating system, and a “webview” process, which renders the UI using web technologies and the system’s native web view. If that scares you, remember that Figma, a ui design tool, took over the market with an app built on web technologies. Same for Visual Studio Code, Slack, Discord, Microsoft Teams, and an increasing number of apps nowadays. Always bet on the web!

does it work though?

Well, this is how we’re building Nema Studio, a cross-platform, cloud-based and collaborative Digital Audio Workstation (DAW). Figma was a very big inspiration for us. Our situation is a bit different though; in the music industry, producers tend to rely a lot on native plugins distributed in proprietary formats (mainly Steinberg’s VST and Apple’s Audio Units). You can’t just ask them to let go of their favorite plugins, which they probably have spent several hundreds of dollars to get (…right?). However, supporting these formats on the web would be a massive undertaking, and probably require several years of effort to develop what would essentially be Wine for the web.

But that’s okay.

Our bet is that people who are just getting into music production or who just want to try our solution don’t care about supporting all of their favorite plugins, right out of the box. What matters is the 80-90% of features that can work in the browser. If they end up liking it, they will download and install the standalone version anyway, for which supporting native plugins will be much easier.

So far it’s hard to tell if this has “worked” for us, because the project is still in its infancy. But the road ahead looks very promising, and if this vision resonates with you, we’re currently looking for investors to help the project reach its goal of becoming “the Figma of music” 😊

  1. We used to transpile it to a subset of JavaScript called asm.js… 🫠

Published on