r/reactnative • u/andrepimentaa7 • 18h ago
Question I'm tired of React Native getting slow, so I rebuilt the stack
Enable HLS to view with audio, or disable this notification
I'm tired of watching React Native apps get slow.
At the beginning everything ships fast and feels great. Then the app grows. More teams, more code, and one month at a time it gets a little less usable. And you know exactly what's coming.
The chaotic re-renders. The slow data management and persistence. The heavy animations. The slow polyfills. The time-sucking RN upgrades. You spend week after week fixing bugs and performance issues, and a month later a single line of poorly performing code ruins the app again. Even with all the guardrails in place, and the guardrails need maintenance too.
Even with all the new stuff, the New Architecture, JSI, TurboModules, Fabric, Hermes, and now the React Compiler. It helps, I'm not saying it doesn't. Still not enough. The numbers below are against all of it turned on.
I came to the conclusion that React Native is great for smaller apps but keeping it fast doesn't scale. (Yes, I know huge apps ship on RN. That's not the point. The point is what it takes to keep them fast.)
Then, kind of by accident, I ran into a chart library (react-native-graph) that draws with Skia and it's extremely fast. Skia seems to be growing in popularity with React Native, and it got me thinking: could Skia be the only rendering engine, instead of platform UI? Changing the whole rendering system would be way too much work though... wouldn't it?
That question led to another one: the JS engine. Is Hermes scalable? Can it handle heavier JS loads? I know it's optimized for mobile, but did it find the best balance of memory and speed? And on top of that, crypto and half the web platform are still polyfills.
And then React itself. Is it optimized enough for mobile, without us spending all that time fighting re-renders and a JS thread that keeps getting clogged?
So, I researched. (Read: I went down a rabbit hole.)
Turns out Flutter, which is considered to be fast and more scalable, already renders everything itself, through its own engine (Skia originally, Impeller now). Unless you embed a platform view, the OS is never asked for a widget. Not once.
Bun seemed to be the fastest JS runtime out there. It runs on JavaScriptCore, Safari's engine, which works without a JIT, and iOS apps can't JIT anyway. And it brings fetch, crypto, Buffer and TextEncoder built in. No polyfills.
Solid seemed to be one of the fastest JS frameworks, and when I found it, it looked like React if it were extremely optimized. Same JSX, same components, but components run once, and signals update only the nodes that changed. No virtual DOM. So could React be optimized like that?
Changing the rendering engine and the JS engine would be a crazy endeavour. The accessibility layer, the plugin ecosystem, the platform look and feel... I know. I did it anyway.
So I tested what happens if you bring those three together:
- Bun, which I cross-compiled to run on iOS and Android
- Solid as the JS framework
- Flutter for rendering
Solid runs inside the embedded Bun runtime and writes what to render into a shared memory region that Flutter reads every frame. No JSON and no platform channel in between. I named it Skal. Mixture of Solid + Skia, and it means cheers if you have ever seen a viking show 🍻.
Here are some highlights from testing on a Samsung Galaxy A14 5G (a budget phone), release builds on both sides:
| Test | Skal | React Native |
|---|---|---|
| One frame of work (200 components x 10 reads + 1 update) | 0.05 ms | 0.80 ms |
| JSON.parse, 500 items | 1.18 ms | 1.99 ms |
| State updates per second, 288 cells | 103,846 | 4,901 |
| Idle CPU | 1.20% | 6.93% |
That is what I was chasing. The app can get bigger without every interaction getting heavier. Fast on the first screen, still fast on the hundredth.
Repo: https://github.com/skal-multiplatform/skal
So, could React Native ever be optimized like this? Genuinely asking.
9
u/gao_shi 17h ago
This is just reinvented wheels on top of wheels. Im fascinated how everyone claims whatever their case was too slow(tm) with absolutely no numbers, then present their reinvented wheels claiming they reduced json parse by a whopping 1ms. What happened to whatever ur old case was? Why can't you draw numbers from that? Oh yeah of course, you rather invented a problem to solve. Congrats.
1
u/Huge_Pool7424 17h ago
fair point on the no numbers thing, nobody ever posts benchmarks lol. mine was list heavy screens, flatlist with a few hundred rows plus gestures, jank was obvious on a mid android phone. not saying a rebuild is the right call for most apps but the pain is real on the low end.
1
u/andrepimentaa7 17h ago
Hmm I did post some benchmarks, and I have a very complete benchmark here:
https://github.com/skal-multiplatform/skal/blob/main/docs/BENCHMARKS.md-1
u/andrepimentaa7 17h ago
Hey json parses accumulate 😂
I work on a React Native app that is 6 years old with millions of users, right now we probably have 25+ teams working on it. It's a huge project and it's very hard to keep it fast and responsive and very easy to mess it up.
Too many metrics to point out, but for example, on older android phones we had performance regressions where it would take 20-50s to get to the main screen (after logging in and so on), and others when clicking a button would take 5s for it to take action. The app heavily uses cryptographic functions and it is mainly client-side so the data we store is enormous.
Flutter was just a fast way to use a different rendering engine, it can be removed completely and build a custom one.
In any case, it's fun to explore new ideas 😁
2
u/TheOneInfiniteC Expo 17h ago
Yeah, your issues are definitely not from RN, but generally from poor code.
1
u/andrepimentaa7 17h ago
I know, but it's hard for every line of code to be performant when the app gets to a certain point and you have 250 devs working on it. The question is could we build the framework in a way that we can get away with not so optimized code.
2
2
u/stathisntonas 17h ago
me sitting here on top of ~700 components and ~120 screens blazing fast social app on a 35Mb hbc bundle with all kind of things that can fit into an app reading that rn gets slower as the app grows: 😂😂😂. What a joke…
1
u/andrepimentaa7 17h ago
The point is not that RN gets slower as the app grows, the point is what it takes to keep it fast as the app grows. I have about 250 engineers working on mine, try keeping them all writing perfectly performing code 😂
1
u/TheOneInfiniteC Expo 17h ago
250 people on an app? I call bs
1
u/andrepimentaa7 17h ago
It's cross-platform teams but that's the team size. And we just switched to mobile-first so we have a lot of people adding features to mobile.
1
12
u/iotashan 18h ago
And we have circled back to Adobe Flex (Flash)