For at least 8 years now, I’ve been hearing about the imminent death of frontend - or at least JavaScript. One of the tools that is supposedly going to wipe it out is WebAssembly (WASM from now on).
A long time ago I was told that JavaScript is basically legacy already and that we’ll soon be writing frontend apps in Rust or Go.
Meanwhile - despite my many flaws - I do have one advantage: I can explain things simply and in an interesting way, even if the topic is painfully boring (like cattle farming in Poland in the 80s — trust me 😅).
Online, I mostly found articles either:
- scaring everyone with WASM domination ☠️
- or super technical deep dives that aren’t very beginner-friendly.
So I wanted to demystify WASM a bit and write an honest article about:
- why it won’t kill JavaScript anytime soon
- and when it actually beats JS hard
TL;DR 🧠
Here’s a small live demo with WASM vs JS benchmarks and the GitHub repo.
As you can see:
- JavaScript on its own is already very fast and totally fine for most tasks
- but when it comes to heavy computations, WASM has a big advantage, even without fancy optimizations like SIMD
Do you get similar results on your machine?
Feel free to share in the comments! 😊
⚠️ I intentionally didn’t validate the inputs - be careful, it’s very easy to freeze your browser tab.
Demo: https://sylwia-lask.github.io/wasm-js-bench/
Repo: https://github.com/sylwia-lask/wasm-js-bench
How do we even write WebAssembly code? 🤔
Let’s start with the basics.
Code that gets compiled to WASM is usually written in low-level languages like:
- Rust
- Go
- C / C++
Why not something more convenient, like Python or plain JavaScript?
First, a small but important clarification 🙃
WebAssembly is not native CPU machine code.
It’s a portable bytecode format that browsers later JIT-compile to machine code — very similar to what they do with JavaScript.
So why these languages?
The main problem with Python or JS isn’t “heavy compilers”, but:
- dynamic typing
- large runtimes
- garbage collection
- unpredictable memory models
WASM is designed around a simple, predictable execution and memory model, which fits languages like Rust or C++ much better.
(Yes, WASM GC exists and is evolving - but it’s still far from mainstream in production.)
Why I used Rust 🦀
In my demo I used Rust, mostly because it has a near-zero runtime and gives you very explicit control over memory.
I swear - in its basic configuration it’s really not that hard to set up.
I even managed to do it on Windows!
All I had to do was install the entire Visual Studio toolchain… which is exactly why we love Linux 😌
Rust itself is often described as “TypeScript on steroids”.
It’s obviously not the same thing, but:
- it’s very strict about types
- there’s no
any - which can be annoying at first for TypeScript devs…
…but you quickly start appreciating how many bugs it prevents ❤️
Rust also introduces concepts like ownership and borrowing, but I won’t go into that here.
If you want to dive deeper, dev.to alone has tons of great Rust articles.
Compiling to WASM
The compilation process itself is pretty straightforward and can easily be integrated into your CI/CD pipeline.
If you’re curious what the compiled output looks like and how it’s actually used from JS, check out the repo - I intentionally committed the compiled files so you can inspect them.
Okay, but… when should I use WASM and when JS is better? ⚔️
You can check everything yourself in the demo.
The benchmark code is publicly available on GitHub, so you can verify that I’m not cheating against either WASM or JS 😄
Again: input values are on your own responsibility - it’s very easy to freeze a browser tab.
JavaScript is really fast 🏎️
WASM is insanely fast - but browser engine authors are not sleeping either.
JIT compilation in engines like V8 or SpiderMonkey works insanely well.
So if:
- you’re writing a normal frontend app
- a simple CRUD
- lots of DOM interactions
…plain JavaScript can easily be faster overall.
Even with fairly heavy but straightforward computations.
For example:
n × n matrix multiplication and returning a single number (mod 1 000 000 007)
JS handles this kind of math perfectly fine and often appears “faster” than WASM.
Why appears?
Because we also have to remember about the overhead of crossing the JS ↔ WASM boundary.
The boundary between JS and WASM is expensive - the more often you cross it and the more data you copy, the faster you kill all performance gains.
Where JS starts losing 💥
Things change when we get into really heavy computations.
Take:
n! mod 1 000 000 007
Here JavaScript becomes much slower than WASM.
On this small example the absolute time is still low - but imagine something like:
- physics simulations
- numerical solvers
- large statistical models
The core issue is numbers.
JavaScript uses IEEE-754 double precision numbers, and for very large values it has to switch to BigInt, which is slow.
Rust, on the other hand, happily operates on u64.
That alone creates a massive performance gap.
Interestingly, the results differ depending on:
- browser
- JS engine
- hardware
For example, on my machine the gap is much smaller in Firefox than in Chrome.
What about image processing? 🖼️
WASM is often mentioned in the context of:
- image processing
- video
- audio
And yes — it can be amazing at that.
But here’s a fun surprise 😄
When I tried a very simple benchmark - just applying a Gaussian blur to an image — JS completely destroyed WASM.
Why?
Because I had to copy the entire Uint8Array into WASM memory.
WASM only started winning when I:
- built a full image processing pipeline
- applied multiple filters in a row
- did as much work as possible inside WASM
Lesson learned 👇
“WASM is great for images” is true — but only when the operations are heavy enough. (Ok, some optimizations (like shared memory) can reduce this overhead, at the cost of complexity.)
Even Gaussian blur, which processes millions of pixels, is something JS handles surprisingly well.
Bonus: WASM is not the only tool 🧰
It’s also worth remembering that:
- Web Workers
- OffscreenCanvas
- GPU solutions (WebGPU)
…can sometimes be perfectly fine alternatives.
Not every heavy task automatically needs WASM — sometimes JS + workers is already “good enough”.
So… is JavaScript dying? ☠️
Nope 😄
As you can see:
- JavaScript is very much alive
- modern frameworks are more than enough for everyday frontend work
But when you do have heavy computations:
- don’t be afraid of WASM
- it’s actually a tool for normal developers, not just hardcore systems programmers
WASM is not a replacement for JavaScript — it’s a powerful complement, especially as a compute engine.
Your turn! 👋
What kind of results did you get in the benchmarks?
Feel free to share them in the comments — I’m genuinely curious 😊



Top comments (9)
If you really want to you can write javascript or python that runs in a webassembly runtime like Wasmer or Javy. The penalty with using those solutions is the runtime needs to be downloaded together with your code.
Great point - and yeah, that’s a really good observation 👍
Running JavaScript or Python inside a WASM runtime (like Wasmer, Javy or Pyodide) is absolutely possible and can be very useful, especially for portability and sandboxed execution.
As you mentioned, the main trade-off is shipping the runtime itself - startup time, bundle size and memory usage can easily outweigh the benefits for typical frontend apps.
I personally see those tools more as portability / compute engines rather than a replacement for native JavaScript in the browser, but they’re definitely an interesting part of the WASM ecosystem.
Nice! I like your demo :). I like that you show your prototype (demo) on a website. It make easier for the user to interact!
Thanks so much, Benjamin! 😊
Really happy you liked the demo - making it interactive was exactly what I was aiming for.
Appreciate your comments as always 🙌
you are welcome, Sylwia :). You can call me Ben!
Haha ok, Ben :)
I can't wait for the next post:)
I used WASM 2 years ago, and at that time, I faced too many challenges to add WASM to different runtimes of JavaScript.
Totally fair - the WASM ecosystem was much rougher around that time.
Different JS runtimes had different loading APIs and limitations, and the tooling was still maturing back then.
Out of curiosity: what were the main issues you ran into? Was it bundling, runtime differences (Node vs browser), or something else entirely?
I’d love to hear more details 🙂