Using wasm instead of javascript in frontend

A while back I asked if wasm could feasibly be used in place of js for browser frontend stuff, and I was a little surprised to find that people didn't seem to think it was a great idea. I got suggestions ranging from "Don't try to use wasm as a direct js replacement, use a wasm-based framework instead that has done all the low-level work for you" to "use typescript instead".

I recently chose to ignore that advice and wrote a small prototype where I used wasm bindgen as a base to rewrite some of our js frontend modules. The intention was not to make anything production-ready; I was just interested to see how feasible it was.

To be honest, I kind of understand why people were a little lukewarm about the idea. You end up in an awkward situation where you're trying to rely on Rust's strict typesystem to save you from yourself, but you're interfacing against a dynamically typed language/runtime that is weak on the guard-rails front. And you often find yourself receiving a type that isn't quite right, so you need to typecast it. It's pretty obvious why this happens, I just realized after a while that I wished it didn't happen so often. I understand the suggestion to use TypeScript instead far better now.

But at the same time, it's not as bad as it could be either. It's a little bit like unsafe -- you write wrappers around the dynamic stuff, and try to hide it behind more idiomatic Rust code, and once you get over a certain hurdle, it does feel a lot better. And the gloo crate makes some things far less annoying to work with.

The experience made me randomly curious: Has anyone made the switch to using Rust/wasm as a js replacement for their front-end stuff in production? I'm know people are using things like leptos, but I'm curious if anyone is using Rust/wasm as a direct replacement for writing plain js, and how happy (or sad?) they are with it.

1 Like

AFAIK WASM can't directly access the DOM and instead has to go through Javascript. Has anything this changed? If not then you can't avoid Javascript

AFAIK WASM can't directly access the DOM and instead has to go through Javascript. Has anything this changed? If not then you can't avoid Javascript

You can't avoid having javascript somewhere in the bundle, but you can use libraries like web-sys or dioxus that provide that javascript for you. Going through javascript doesn't cause much performance overhead for rust. It can perform on par with raw javascript. Sledgehammer in this benchmark is written in rust

Wasm-bindgen and web-sys are very low level for dom manipulation, but they do provide an interface without interacting with javascript directly. I find gloo and other wrappers pretty comparable to typescript in terms of ergonomics

WASM is a compelling technology for many reasons. But it still has a lot of sharp edges, some of which you had to discover the hard way. It's very common to ignore advice (just try some relevant search terms in your preferred search engine!) and I don't think anyone really knows of a universal "fix" for it.

My biggest complaint with WASM is that the raw ABI at the boundary is just pointers and numbers. You need a lot of infrastructure to serialize and deserialize when crossing the FFI boundary. I feel like the Component Model is a pretty good step in the right direction for addressing this issue, especially where multiple languages are involved (not just JavaScript on the outside and Rust on the inside; the ability to mix and match languages is one of the more promising aspects of WASM).

For web apps specifically, "just use leptos/yew/dioxus/..." is sound advice. These are kind of large packages, but they are doing some heavy lifting to make the FFI boundary ergonomic.

2 Likes

If the alternative is using javascript for web in a sane way (i.e., the thing is mainly html, with a css to make it look good and a little javascript for some extra behavior), then doing that with wasm will require more javascript for communicating with the wasm that for the actual functionality, so you should probably just use javascript for that.

If, on the other hand, the alternative is writing an app in javascript with react or somehing like that, and it has nothing to do with web other than that the app is running in a browser, then yes, it would probably be better to write an app with something like egui and compile it to wasm.

1 Like

I've built something in Dioxus and seeing how hard even the most basic things are I think these libraries need a big disclaimer and realistically they should be merged together.

I think the best would be to create an API to call react directly from rust and not bother trying to do anything in Rust land (given how difficult it seems to be).