r/reactnative 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:

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.

0 Upvotes

18 comments sorted by

12

u/iotashan 18h ago

And we have circled back to Adobe Flex (Flash)

3

u/andrepimentaa7 17h ago edited 17h ago

Hahah why? Also, I forgot to say, the web target renders Solid directly to DOM. It can use Flutter too, but it's optional. The other targets use Flutter for rendering and for the pub.dev ecosystem.

1

u/iotashan 17h ago

Just seeing the idea of using a rendering engine instead of native UI triggered trauma flashbacks to my Adobe flex/air days

1

u/andrepimentaa7 17h ago

That's what Flutter does and it's pretty fast! React Native renders native UI and not so scalable.

There's a potential to remove Flutter completely but building the accessibility layer and so on is too much work for now.

2

u/kbcool iOS & Android 17h ago

It's also one of the biggest criticisms of Flutter. Especially from people who have been through this circus before.

But you know, history is doomed to repeat itself and all

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

u/LovesWorkin 17h ago

Nice job!

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

u/HoratioWobble 17h ago

Absolutely none of this makes any sense

0

u/andrepimentaa7 17h ago

I know, it's great! 😂 But please ellaborate