Published on

WASM Quick Tour

Authors

@Author: Garfield Zhu

WASM Quick Tour

WASM is interesting to me because it puts another runtime into the browser. It does not need to replace JavaScript. Rust can keep the data and do the calculation, JavaScript can still do the browser things.

The old Rust and WebAssembly book is still useful. It is a legacy book now, but the flow is easy to follow: wasm-bindgen exports the Rust API, wasm-pack makes the package, and JavaScript connects it with the canvas and events.

The Game of Life project is a good small example. Rust owns the universe and moves it to the next generation. JavaScript reads the memory and paints the cells. Click a cell, pause it, reset it. The boundary becomes visible.

The playground

This is the little playground I like. Click cells to make a pattern, pause it, and reset the world when it becomes too chaotic. The frame counter shows the split. WASM updates the state, JavaScript schedules and paints each frame.

If the embedded view does not load, open the playground directly. The source is in the wasm-game-of-life folder.

How I put WASM in this MDX page

I did not put the Rust package inside Next.js for this demo. I build it in the Aloha.zone.io repository with wasm-pack --target web. GitHub Actions copies the package and the small web page to GitHub Pages. Then the MDX uses an <iframe> to show that page.

For the blog, I only need three things: a fixed URL, garfieldzhu.github.io in frame-src, and a normal link if the iframe cannot load. The not-prose wrapper keeps the game layout away from the article style.

This split is simple. The WASM app has its own build. The blog does not load Rust during server rendering. It is another page, but it works.

Runtime soap opera: Wasmer vs. Wasmtime

The old runtime notes have a small soap opera too. The two names are Wasmer and Wasmtime. Both run WASM outside the browser, both want WASI to be useful, and both think their way is the sensible way. So, naturally, there are two.

The story in Wasmer issue #142 is basically this: the Wasmer team tried Wasmtime early, felt it was hard to use and quiet, then started Wasmer. Later, the projects grew in different directions. Wasmer wanted a universal and pluggable runtime: different compiler backends, custom ABIs, and an easy library for other apps. Wasmtime moved with the Bytecode Alliance, putting more weight on standards, WASI, correctness, and a clear embedding story.

Then came the benchmark episode. Wasmer showed faster numbers with LLVM. Other people showed Wasmtime winning with Cranelift. Then someone said the chart was being read wrong. Coremark, startup time, compiler backend — every actor had a graph. Not exactly a calm family dinner.

The current comparison is less dramatic but more useful: Wasmtime leans toward a standards-led runtime for WASI, the Component Model, and production embedding. Wasmer leans toward a wider deployment ecosystem and more runtime choices, including Singlepass, Cranelift, LLVM, and SDK/registry workflows. My major conclusion is simple: pick Wasmtime for the calmer standards road, Wasmer when the configurable backends or product ecosystem are the point. This is my personal preference, not an objective ranking. Run your own workload before turning an old benchmark into a religion.

GPT investigation result: Wasmer vs. Wasmtime

This is a GPT-assisted comparison checked against the linked project documentation. It is a reading aid, not an independent benchmark or an objective winner announcement.

QuestionWasmtimeWasmer
Main shapeA focused standalone runtime and embedding library, backed by the Bytecode Alliance.A runtime plus a broader package, registry, SDK, browser, and edge deployment ecosystem.
Compiler choicesCranelift is the normal optimizing compiler; Winch and other strategies cover fast startup or portability.Singlepass, Cranelift, LLVM, and other engine choices are exposed for different speed/startup tradeoffs.
WASI and componentsStrong emphasis on WASI, the Component Model, standards, and conformance.Supports WASI-oriented workflows and its WAI/bindgen ecosystem, with more freedom in how the application is packaged.
EmbeddingRust, C/C++, Python, .NET, Go, Ruby, and other host integrations are first-class documentation paths.SDKs and host integrations are part of the product story, alongside the standalone CLI.
The tradeoffLess product surface to think about; a good default when the runtime itself should stay boring.More knobs and deployment options; useful when those options are the actual requirement.

The old Wasmer issue #142 is useful as history: it captures the projects explaining why they were not the same project, followed by a very enthusiastic benchmark argument. It is from 2019, so I would not use its numbers as current facts.

Sources: Wasmtime, Wasmtime compiler strategies, Wasmer runtime features, Wasmer CLI, WASI releases, and the Aloha.zone.io runtime notes.

Next plan: WASM inside MDX

The iframe works, but it is still another page. For a more interactive article, I want to make the WASM a real MDX component:

  1. Keep the Rust crate and wasm-pack --target web output small.
  2. Add a client-only WasmGameOfLife React component and register it in components/MDXComponents.tsx.
  3. Let the component handle loading, canvas, buttons, and errors. The MDX only uses something like <WasmGameOfLife />.
  4. Put the component between short explanations. Each step can change the Rust state and show the result right away.
  5. Keep a fallback link. Test the production build, mobile layout, and a browser with WebAssembly disabled.

This will make the article more playful. It also couples the MDX build, browser React code, and WASM package together. I think that is a good trade for the next version.

My current idea is simple: WASM is not a replacement for the Web. It is one place to run the part that benefits from Rust. The frontend still owns the browser experience.