Weāre a quarter into the 21st century, and the browser has quietly evolved into something much more than just a UI layer. It can run complex computations, leverage the GPU, process audio, simulate physics, and even run machine learning models. And yet⦠most of the time, we still treat it like a tool for forms and dashboards.
I wanted to show what happens when we actually take advantage of what the platform already gives us.
The jsday conference in Bologna has just come to an end, and it was honestly amazing. If youāre wondering whether itās worth attending events like this ā it absolutely is. Itās an endless source of inspiration, far beyond what you get from articles or tutorials. If you have a minute, Iād really appreciate a like on my LinkedIn post
![]() |
![]() |
![]() |
|---|
If youāve been following my posts, you probably know that my talk was about WebGPU and WebAssembly, and what we can gain by using them in the browser.
So what are these two technologies, and why does it make more sense to talk about them together rather than separately?
They are complementary by design. WebAssembly runs on the CPU and allows us to execute low-level, compiled code directly in the browser. WebGPU, as the name suggests, gives us access to the GPU ā not in some abstracted, limited way, but in a relatively direct and powerful form.
If you want a deeper dive, Iāve written more about them here:
WASM ā https://dev.to/sylwia-lask/will-webassembly-kill-javascript-lets-find-out-live-demo-43ln
WebGPU ā https://dev.to/sylwia-lask/why-webgpu-feels-like-the-future-of-the-web-live-demo--2bjh
But instead of talking about them in isolation, I wanted to show a concrete example of what happens when you combine them.
Because Iām not a fan of theory without practice, I built a small demo.
š Repo: https://github.com/sylwia-lask/text-goes-boom
š Live demo: https://sylwia-lask.github.io/text-goes-boom/
(Fair warning ā especially the JS canvas benchmark can get your CPU quite warm š
)
What does it do? You type text into an input field. The text is converted into particles. And when you click and drag your mouse across it⦠the text explodes.
Completely useless? Yes. Slightly addictive? Also yes š
Whatās happening under the hood?
First, the text from the input is rendered into an image bitmap using plain JavaScript and Canvas 2D. This is exactly the kind of task where the classic browser APIs are already perfectly sufficient, and thereās no real reason to move it elsewhere ā especially for a demo like this.
Next, the bitmap is passed to WebAssembly. This is where I run a deliberately āsomewhat over-engineeredā algorithm that maps the image into particles. I wanted WASM to actually have something meaningful to do, and letās be honest ā it also just looks cooler this way. Out of curiosity, I benchmarked it against an equivalent implementation written in JavaScript.
As you can see, this is where we get the first tangible gain. WebAssembly is roughly 2ā3Ć faster in this case. And this isnāt even a best-case scenario ā I put quite a bit of effort into optimizing the JavaScript version as well, just to make things fair and not give Rust an easy win.
In this particular demo, the difference doesnāt matter that much because this step only runs once during rebuild. But itās not about this one case ā itās about the order of magnitude. What happens if you need to perform a similar operation hundreds or thousands of times? Thatās where this starts to become very real.
And then comes the part where things get interesting.
The particles are passed to WebGPU ā and this is where the browser really starts to flex.
The āclassicā JavaScript + Canvas 2D implementation starts struggling on my machine at around 40k particles.
Frame rate drops, everything slows down, and you can feel the limits pretty quickly.
Meanwhile, WebGPU⦠doesnāt even flinch.
More than 500,000 particles. Each with its own physics. Smooth animation. Stable FPS.
At this point it stops being a small optimization and starts feeling like a completely different class of capability. The same browser, the same app, the same machine ā but a totally different level of performance, simply by using the right tool for the job.
Where does this actually matter?
This is obviously not your typical frontend CRUD setup. You probably donāt need WebGPU to build a dashboard or a form, and in many cases the real bottleneck is the network, not computation.
But there are entire classes of problems where this approach makes a huge difference: real-time data visualization, physics simulations, graphics-heavy interfaces, audio processing, games, image or video transformations, and of course ā matrix-heavy workloads like machine learning and LLMs running directly in the browser.
And the funny thing is, you donāt need this⦠until suddenly you really do. A product evolves, requirements grow, performance becomes an issue, or you want to move part of the workload from the backend to the client. Thatās when things start getting interesting.
One more thing
If you take a look at the repository, you might notice something important.
This is just a regular React app.
Thereās no exotic architecture, no āfrom another planetā stack. Yes, thereās Rust compiled to WASM and there are WebGPU shaders ā but theyāre simply embedded into a standard frontend setup. The rest of the app looks exactly like something you could start in your project tomorrow.
That was intentional. I wanted to show that this isnāt some distant, experimental playground reserved for niche use cases. Itās something you can already integrate into real-world applications ā incrementally, when you actually need it.
Of course, WebGPU is not yet universally supported, so youāll need a fallback strategy. But at this point, for a large portion of users, thereās little reason not to start exploring it.
Final thought
The browser is no longer just a place where we render UI.
Itās a serious compute platform ā one that already gives us access to both CPU and GPU, right out of the box.
You donāt need WebAssembly or WebGPU in every project. Most of the time, youāll be perfectly fine without them.
But the moment you start hitting performance limits, or your problem shifts from āmoving data aroundā to āactually computing thingsā⦠you might realize that the platform already had the solution all along.
And all you had to do was use it. š








Top comments (29)
Perfect demo! I love your work to seek the performance edge of the browser.
I feel the root of problem is language based. Because the WAT format is not really usefull for direct coding, so the WASM perfect soulution maybe a Rust, but I think worth to spend a time to create a better direct WASM text format, I started the work, but the mordorjs bit slow me down.
The other language is the SHADER which is much problematic to mastered, because whole GPU concept is totally different than a standard CPU based programming language logic. We are standing here the opening gate of threating AI ages, but even do not understand how we can controll our own machines.
For example a good example on a shader toy ( a great place to play with shader )
shadertoy.com/view/ffSSzW
if you take a look this is really hard to understand what is going on hardwer level compared to a simple assembley which is much more straight.
A few years ago I spend a lot of time on shadertoy but honestly right now I cannot able to wrtie a working SHADER code.
This is my minimal javascript shader bootstrap (without dependency - 8 years ago - as VibeArcheologist I have a lot of stuff in my past ):
Thanks a lot for this comment, I really appreciate it š
And yes, totally agree, understanding shaders is hard. Itās a completely different mental model compared to CPU programming, and it takes time to even start thinking in that way. Iām also really curious how this will evolve in the future. My gut feeling is that we wonāt see average developers writing shaders directly, more likely weāll rely on higher-level abstractions or libraries built on top of them.
Iāve actually been thinking about building a small POC around GPGPU myself, but before that Iād like to properly measure the performance, trade-offs, and whether it really makes sense in typical frontend scenarios.
Also, Iām curious, whatās your take on Zig for writing WASM? I havenāt tried it myself yet, but Iāve been hearing quite a lot of good things about it.
This is a great post! I am not familiar with WebAssembly and kind of with WebGPU, but this gave me a basic understanding the importance of it when it comes to mainly performance!
Speaking of performance, how would you determine that you reach your limit and in which therefore need WebAssembly or WebGPU? I can imagine some people will use it right off the bat but if we are talking about needing it, what do I look for and how do I measure it?
Thanks! Hope this makes sense. I might be overthinking the question and that it might be already be answered in the post, but I start asking this since you mentioned "But the moment you start hitting performance limits, or your problem shifts from āmoving data aroundā to āactually computing thingsā⦠you might realize that the platform already had the solution all along."
Thanks, thatās a great question š
I wouldnāt start with WebAssembly or WebGPU right away. First, Iād check where the real bottleneck is. In many apps itās still the network, too much data or too many requests, and in that case these tools wonāt help.
What I look for is whether the app becomes compute-bound. If the UI starts lagging, animations drop frames, or the main thread is busy for too long, thatās usually a sign. Then Iād profile and see which part of the code is actually expensive.
WASM makes sense for CPU-heavy tasks like data processing or transformations. WebGPU is more for massively parallel work like physics, graphics, or large-scale computations.
So the key is profiling first. If the problem is really about computation and not data transfer, thatās the moment when these tools start to make sense š
The WebAssembly + WebGPU angle is where most teams are still leaving huge wins on the table. One underrated slowdown I keep seeing in "fast" React apps: the waterfall of
useEffectfetches that happen after hydration. Moving data fetching to the server component or a single initial payload collapses 3-4 roundtrips into one and usually cuts TTI by 30-50% on mid-spec mobile. WebGPU is the ceiling lift; fetch architecture is the floor nobody talks about. What's the most common "easy to fix, huge impact" pattern you see in audits?Exactly, thatās how it usually looks š
In React apps itās very often about fetch patterns, too many requests, pulling too much data, or just inefficient queries. I also see a lot of cases where everything still ends up in one big bundle, even though on paper thereās ācode splittingā.
These are usually quick wins and can make a huge difference. And then, if thatās already in a good place and the problem is still heavy computation, thatās where WASM or WebGPU start to make sense.
And the gains there can be really significant. We often fight for milliseconds, but here you can get a 2Ć speedup with WASM, and in parallel workloads WebGPU can be 200ā300Ć faster than JavaScript.
I don't even try to switch to Canvas 2D tab š
Haha no way š almost 2.5 million particles and still decent FPS. Thatās insane, this should totally be the cover photo š
And yeah⦠better not switch to Canvas 2D at that point, poor CPU wouldnāt survive that experiment š
Nice Post again. I am following you on LinkedIn now.
But: The article does not say anything about real apps that are slow.
If I look at the Apps I use, that feel really slow, I don't think WebAsembly and WebGPU will help.
Deezer (like Spotify):
Search seems slow, which is a backend problem. They also seem to fetch my favorite artists each time I open them. This all seems to be a caching problem and not a rendering problem.
Aumio (Children's meditation):
I don't know what's so hard about making an app like that. It's a shame that it is so slow, given that it is "only" an audio player. I thought about ripping the tracks just to avoid this unbelievably slow UI. I think there much easier ways to improve performance than switching to this stack.
Roborock (Roomba):
Maybe it's the communication, or the data comes from the robot and isn't cached. But slow map-loading probably also is a caching problem.
What "real" apps do you use that feel slow and might actually benefit from this stack?
At my former employer I evaluated solutions to render 100.000 rectangles that may be transformed in different ways. Rendering was not an issue, once I started using the CSS
transformproperty.I tweaked the drag and drop performance by using the
willChangeCSS property, reducing the amount of GC calls and by not rendering the update each time the drag/move event is fired.Needless to say, that at this point you don't send/render all elements on each frame, but only the changes.
Later these rectangles become buttons, labels and input fields and more. They can be styled using CSS. At this point performance must be reevaluated. But on the other hand: I wonder if there is a graphics library as capable and as performant as the DOM I could use inside WebAssembly/WebGPU š¤
Thanks a lot for this comment, really appreciate it š
I agree with you. Many slow apps are limited by network, backend, or caching, and in those cases WASM or WebGPU wonāt help much.
At the same time, itās not always that simple. A colleague of mine had a talk in Bologna about optimizing an app for Adobe, and even small things like adding a custom header made a difference, because every GET triggered a preflight. So sometimes milliseconds really matter.
For many apps, better caching and fewer requests are the biggest wins. But thereās also a growing class of apps where computation is the bottleneck. You can see it in tools like Figma or Canva, 3D viewers, video or image processing, and AI in the browser.
Also, your example with 100k rectangles is a great one, but it focuses mostly on rendering. In my case, each ārectangleā has its own physics and is updated every frame, which is a very different kind of problem. Thatās exactly the kind of scenario where CPU starts to struggle and GPU-based approaches really shine, especially in games or simulations.
So I see this as one more tool. Not always needed, but very useful when the problem is actually about computation š
I guess this only works on Chrome?
Good question! š
It works the same way as WebGPU support in general, so not just Chrome. Itās available in modern browsers like Firefox and Edge as well.
That said, WebGPU is still not a fully finalized standard yet, and there are some gaps, especially on mobile devices and certain environments like Linux. So weāre not quite at āworks everywhereā yet.
But itās definitely moving in that direction, itās more a matter of time than anything else. Thatās also why I mentioned in the article that having a fallback is still important for now š
Interesting for offline-first apps where you donāt have a backend to lean on.
Itās about choosing the right layer for the job.
š
Exactly! š
And now that we have WebGPU, we can finally actually choose the right layer for the job, not just default to the CPU or the backend.
Every time I try to āoptimizeā something, I realize the problem isnāt React, not JS, not even the backend ā itās that weāre building like the browser is still a thin UI layer.
Meanwhile it can literally run GPU workloads now.
The wild part is most apps donāt feel slow because of one big mistake ā itās death by 100 small decisions:
extra abstractions, unnecessary state sync, over-fetching, ājust in caseā logic.
And suddenly youāre shipping a dashboard that needs a small teamās worth of compute to render a table.
Feels like Wirthās law in action ā software getting slower faster than hardware gets faster ļæ¼
Curious where you draw the line in practice:
when do you actually reach for WebAssembly/WebGPU vs just fixing architecture?
Thatās a great question š
For me, the line is where fixing the architecture no longer helps. Iād always start with the ācheaperā wins first, reducing over-fetching, unnecessary state, re-renders, and general complexity. A lot of apps are slow because of many small decisions, not because they lack WASM or GPU.
But if the architecture is already reasonable and the problem is simply that you need to do a lot of computation, then it becomes a different story. At that point itās less about optimizing code and more about choosing the right execution layer.
So I see WASM/WebGPU not as a replacement for good design, but as the next step when good design is no longer enough š
Excellent work on the demo, the JS WASM WebGPU pipeline really drives the point home.
The 2-3x WASM vs optimized JS benchmark highlights something we all do: we spend hours micro-optimizing code without ever questioning if the runtime itself is the right tool for the job. In data it's the same thing, you can spend 3 days tuning a SQL query when the real problem is you're running computation in the wrong place. The "I optimize what I know" reflex is comfortable but it's often what keeps you from seeing the actual solution.
Exactly this! š
Itās the same on the frontend, we often spend hours optimizing milliseconds, while here you can get a 2Ć gain with WASM and even 200ā300Ć with WebGPU. That really puts things into perspective.
And sure, WebGPU isnāt fully supported everywhere yet, so you need to be mindful there. But WASM? Thatās already widely available and production-ready, and still surprisingly underused for cases where it can make a real difference.
This is the kind of performance article we need more of practical, not theoretical.
The gap between works on my machine and works for users on 3G with a mid range phone is where most apps die. And it's not because developers are bad. It's because dev tools and local environments hide the slowness. Chrome DevTools on a MacBook Pro with fast internet tells you nothing about real user experience.
I've definitely been guilty of shipping something that felt fast to me, only to realize later that users were waiting seconds for things I didn't even notice.
The live demo approach is so valuable. Watching something be slow in real time hits different than reading about it.
What's the one performance issue you see most often in the wild that developers seem to ignore?
Thanks for this bookmarking. š
Thanks a lot, really appreciate it š and yes, exactly ā these problems are very often ignored.
At least with DevTools we have some way to simulate slower network conditions and get a glimpse of what users might experience. Testing on weaker hardware is definitely harder though. That said, this is where things like WASM can actually help quite a bit, especially for heavier computations, because of its more predictable performance. And if you can push work to the GPU, even better ā even a low-end GPU will usually handle parallel workloads much better than the CPU.
But overall, I still think the most commonly ignored performance issues are related to the network layer. In many small and mid-sized apps, itās not the computation that hurts the most, but sending too much data, too often, and sometimes completely unnecessarily.
Some comments may only be visible to logged-in visitors. Sign in to view all comments.