Note: we've announced Wasm events in NYC and SF; details at the end!
There’s a trope in the web development world that WebAssembly has not lived up to the hype.
Andy Wingo wrote an excellent post last year that gets into the technical nuance of this, and opens it with:
I need to talk about WebAssembly’s dirty secret: despite the hype, WebAssembly has had limited success on the web
It's true. WebAssembly hasn’t toppled web development on its head. Seven years into being able to build for the web in (theoretically) any language, most people building most things on the web are still using some flavor of JavaScript. The vast majority of web developers have never touched a Wasm compiler.
In fact, even the professional Wasm community is largely focused around use cases of Wasm out of the browser as a generic platform-independent bytecode.
In spite of that, I keep running into people quietly but successfully using WebAssembly, in the browser, in production.
I want to talk about the disparity between the perception of Wasm as overhyped tech among web developers with the fact that Wasm has become almost table stakes for a certain class of apps.
It used to be that “web development” meant developing applications that were delivered over hypertext. These were categorically different from desktop applications, in terms both of their capabilities and their architectures.
That discipline of software development still exists. News sites, blogs, e-commerce, and social media are inherently hypertext. The web frameworks have evolved, but this variety of web development is not radically different from building an e-commerce site in 2004.
But there’s another genre of “web sites” that are not inherently hypertext. These are the desktop-class applications that use the browser mainly as a vehicle for getting onto your desktop with as little friction as possible. Think Google Docs, or Figma.
Early on, this category of apps was very web site-like. They embraced hypertext, because you kinda had to. Early rich text editors used a contenteditable <div>
. Predecessors to Figma piggybacked on the browser’s SVG renderer.
The developers who built these early apps may have been writing more JavaScript, but otherwise had a lot to talk about with people building a blog. The surface area of browsers was small-ish, and everyone was calling the same APIs. We all shared the same disdain for Internet Explorer 5.
Over time, browsers shipped more “building block” APIs: WebGL, Canvas, WebSocket. These could mostly be ignored by the people building “hypertext” apps, but allowed a new discipline to splinter out from web development.
I emphasize this distinction because it has everything to do with who gets value from adopting WebAssembly.
If you are developing an inherently hypertext app, WebAssembly is not meant for you. I mean, I'm not here to gatekeep, you can still use it if you want! But the problems it exists to solve are likely not the problems that you have.
Andy again:
WebAssembly has not been a Web success for DOM-heavy apps. Nobody is talking about rewriting the front-end of wordpress.com in Wasm, for example.
Every success story I've heard about WebAssembly in the wild has been for the “desktop-class application” category. And even in those cases, it's often not to the exclusion of JavaScript, but in a hybrid role.
One pattern I’ve observed, especially with graphically-intensive apps, is a hybrid JavaScript/WebAssembly model.
JavaScript (often React) is used to render the “chrome” UI. That JavaScript code forwards events to an “engine” written in WebAssembly, which owns the core document data structure and also owns a <canvas>
element which it renders to.
Some examples I’ve collected of this architecture:
Splitting an app down the middle between two languages is a bit clunky, but it ends up being a pragmatic choice. The UI chrome can be developed using existing tools, and you can hire from a large pool of developers. The “engine” can be written in Rust or C++, which have better ergonomics for the byte-packing work needed for GPU rendering.
Side-stepping the JavaScript garbage collector also allows for more efficient use of the limited memory given to each browser tab, so I especially see WebAssembly used in applications that need to handle large amounts of data.
Another area where WebAssembly is gaining steam is in data sync engines. Modern data synchronization tech can be computationally-complex and memory hungry, especially at a large scale. On my trip to local-first conf, I counted some element of WebAssembly in about half of the tech presented. As I wrote at the time:
WebAssembly has raised the bar for the sophistication of what you can run in the client, a theme that kept quietly popping up:
Electric SQL runs a trimmed-down Postgres database on the client.
Automerge implements its core data model in Wasm.
PowerSync runs sqlite on the client in Wasm, which it syncs with Postgres on the server.
Overtone, a music listening app, achieves next-frame query latency by running SQLite on the client in Wasm via LiveStore.
The benefits of writing a sync engine in WebAssembly also came up in my chat with Luke at Sequence:
As we started working on the backend side, we built a Rust version [of out sync engine], and found we couldn't keep the two of [the protocols] in sync. So we pulled the trigger on going all-in on the Rust version, compiling that to WebAssembly, and using that on the client side. So what's cool is that our rendering engine that's running on the server, and the view rendering that's happening on the client, they're both working on the same code that is creating the project state, through WebAssembly.
Other folks are getting a lot of mileage out of compiling SQLite to Wasm: Notion and SQLSync come to mind. Our own nascent Aper Rust sync library is also built for Wasm.
On September 5th (next Thurs), we are hosting some talks in NYC from people using WebAssembly in the browser:
We will also be running an event on October 30 in SF. Stay tuned for details (and reply to this email if you are in SF and have something to talk about)
Hope to see you at one or both!
Until next time,
Paul