
How Discord achieves native iOS performance with React Native - reimertz
https://blog.discordapp.com/how-discord-achieves-native-ios-performance-with-react-native-390c84dcd502
======
trevorah
React Native is excellent for web teams that are creating a new mobile app. If
your team has more experience with React than native iOS/Android, then it's a
no-brainer.

However, in my experience you get diminishing returns once your app has passed
v1 and your customers expect more after the new-ness wears off. You find
yourself spending more and more engineering effort to make your RN app to feel
as good as existing mature native-first apps, which is especially frustrating
as you are solving problems that native-first app developers never had to
solve in the first place. They got the solutions for free with the native
sdks.

This plateau of developer effectiveness is hard to get away from as your app
becomes so coupled to RN and your team invests so much into RN tooling and
skills that it feels like a sunk cost.

I do not envy the Discord apps team.

~~~
adatavizguy
I use react native svg with low level d3.js utils to produce data
visualizations with a utility class that holds all the animation values across
components and screens which is sort of a hack but very clean for animating
several pseudo svg components.

For me it isn't about look and feel so much as being able to quickly manage
massive amounts of data for interaction and data viz. I use the ramda lenses,
sagas, redux, and selector stack to manage state of the data. It is clean and
quick to develop. Everything is memoized with selectors only changing if the
reference to the object it is using on the state tree changes.

Nobody can work data the way I can with React. It makes sense.

~~~
nazka
Hum! I didn't know Ramda, very interesting... Thank you for sharing your stack
:)

------
reimertz
I almost got an tear in my eye reading this, being heavily invested in React-
Native and the worries I’ve felt since Airbnb abandoned the ship.

I’ve always loved the framework and the beauty of being able to write native ,
cross-platform applications as a web developer. And what they are doing right
now, trying to get rid of the js-thread bottleneck in 2020 excites me a lot!

> “While it was closed it always had a spinning animation in the background
> chewing away at CPU — death by the smallest cut!”

I spent an entire day doing the same! I had a spinner running in the
background that ate 30% of my battery! I felt so stupid back then. :)

Thanks Discord for sharing this, the community really appreciates it!

~~~
londons_explore
A spinner running in the background consuming CPU is _two_ bugs...

The non-obvious one is why is the framework consuming any CPU time at all on
something not visible? When an element tries to animate, and the whole element
is covered/offscreen, the framework should simply pause the animation. When
the element becomes visible again, it's simple to calculate how long the
element has been invisible, and fast-forward the animation to that frame.

~~~
ericlewis
I’ve seen this happen especially with Lottie. And what basically happens here
is the actual drawing isn’t actually handled by react-native since the library
is itself a native view to either platform. Therefore, react-native has no
idea it’s wasting any resources because it’s not technically “in charge” of
what exactly the native view itself is _doing_. It certain scenarios where it
might be “covered up”, such as all JavaScript based views (which are
essentially just UIViews in iOS) then iOS itself also doesn’t know to stop
this animation either (view compositing is quite popular).

However, if using something like native navigation, where view controllers and
their life cycle get handled by iOS then it _will_ correctly end an animation.

I have no idea if this is true for Android. But I have witnessed it on iOS and
fixed this issue in react-native apps on quite a few occasions.

The ultimate downside to frameworks like this is they imo, don’t know enough
about the content they’re showing to make great choices for users. But at the
same time, it’s not fully desirable to attempt to assume. That’s the platforms
job. And that’s an obvious catch-22. How should you know this if you aren’t a
native app builder?

~~~
mrkcsc
The strongest RN teams and engineers I've seen tend to be those that either
already have or are willing to acquire knowledge about how native app
development works under the hood.

It greatly augments your ability to write elegant solutions to hard problems.

Some argue this is a large cost to bear - however I'd say it's one that is
very reasonable to acquire. Having experience and knowledge in several
languages/frameworks helps make one stronger engineer.

------
tov_objorkin
Once i have a dream about RN application for iOS/Android without Xcode and
AndroidStudio.

Started with Expo, great tool if you don't have native modules. But i have,
very complex search library in Rust. After few attempts the code was converted
to asmjs (RN doesn't support wasm). So i have JS-only codebase that works on
Expo. Livecoding (a bit slow beause of large js codebase) and easy deploymnet
on all platforms.

After release users starts complain about performance. RN fetch API doesn't
support binaries, everything passed back and forth as base64. Some low-mid
tier phones got stuck for few minutes. Also RN fetch doesn't support progress
and a lot of other thing.

Decision was to start using native libraries. Ehh, goodby sweety Expo...

The lesson was learned, if you have complex application don't expect too much
without heavy investment. JS is ugly and unpredictable as usualy. Overall
experience is ok/mehh, but not great.

For the next project i give Qt5 a chance.

~~~
tracker1
May want to also look at MS/Xamarin development, I know a few people that
really like it. Though, RN seems a bit more popular. For that matter, in what
ways is JS unpredictable? Generally combined with Redux or something similar,
I've found it to be fairly consistent and predicatble.

~~~
tov_objorkin
About five years ago i have a dream, that i can abandon all this peasant C/C++
development and jump into mono/xamarin train. As a main product we have Linux
ARM/MIPS karaoke machine with optional remote control via desktop/mobile apps.
The idea was to use same code every where.

\- Tooling for Linux was horrible, like really! \- Alien mobile UI look and
feel \- One can not simple build mobile app for desktop. \- New shiny search
engine prototype doesn't fit into low tier Phone RAM. \- Mono Hello world
application on MIPS device with 128RAM uses about 28 mb of RAM. \- 400 MHz cpu
have really hard times with GC, nogo for soft-realtime. \- No seamless
integration with native code, using libs like ffmpeg is crazy hard. \- F# was
2nd citizen in that time!

Now things changed, but still imho Linux is not a good choose for .net, also
MS force you to use Azure/Cloud/etc infrastructure.

~~~
tracker1
I was thinking in the context of mobile.. TBH, depending on my needs, I'd
probably just fallback to an electron app for desktop at this point. Not good
for lighter systems though.

.Net doesn't force Azure/Cloud at all. I know all the MS demos tend in that
direction, but you can absolutely use it all internally. I've worked on
several backends targeting docker and linux with .Net core at this point. Even
ARM as a target is decent. GUI, no idea on that, I tend to prefer
react+redux+material-ui there.

------
bsaul
I recently tried to start a react native / typescript project, but the
ecosystem confused me a lot. The various different tool recommended to create
a project, some project templates not even compiling, the tons of different
utilities required to process source files.. All that and not a single
reliable source of documentation, made me feel it would be a real nightmare to
maintain on the long run.

~~~
sergiotapia
You are not wrong. It is a nightmare to maintain, and if you already took the
leap you best keep that project updated as soon as possible or you will be
fucked beyond repair.

There has to be a better way to write mobile applications. Is that Ionic? I
don't know.

~~~
latchkey
Seriously, take a stab at building an app in Flutter.

~~~
bsaul
Never had performance issues on scroll ? The demo app on the ios app store has
lagging scroll performance for a simple app on an iphone X

~~~
latchkey
I don't have any pages that scroll. =) It is all single pages for now.

That said, who knows what the demo app was done with. If there is lagging
scroll performance, it could be a lot of things.

I will say that figuring out where the performance problems are would be
pretty enjoyable in IDEA. The tooling there for performance is quite good.

------
jpincheira
Very interesting to read how they were able to overcome their performance
issues and didn't know they were such a small but effective team.

For us at Standups[1] RN has been just instrumental. As a small team, we are
able to ship features, just like Discord, vertically all across the stack.
Having 1 language in common (TypeScript) all across your stack is the best for
small teams/startups. We share most of our code.

For those of you interested in how to share code vertically using
TypeScript[2], check out this guide by Bruno Lemos, super helpful, great value
there for startups and especially tech solopreneurs.

[1] [https://standups.io](https://standups.io)

[2] [https://dev.to/brunolemos/tutorial-100-code-sharing-
between-...](https://dev.to/brunolemos/tutorial-100-code-sharing-between-ios-
android--web-using-react-native-web-andmonorepo-4pej)

------
js2
Some people, when confronted with having to develop a mobile app on Android
and iOS, think “I know, I'll use React Native.” Now they have three problems:
Android, iOS and React Native.

My company has both natively developed Android and iOS apps, as well as a few
RN apps. I'm in the developer tooling part of the company. Indeed, the RN apps
did allow those teams to add developers who had only JavaScript coding
experience. But at the cost of a lot of additional complexity elsewhere in the
company. Now we effectively have to support three platforms in our build
system, in our SDKs, and so forth.

I'm fairly confident that it is not a net win. Those RN developers eventually
have to learn the weird idiosyncrasies of both Android and iOS besides the
idiosyncrasies added by RN itself. They now have bugs that show up on only one
platform because RN Android is using a different JS engine than RN iOS.

There's just a gigantic amount of complexity added by RN on-top of the
gigantic amount of complexity you already get with Android and iOS.

In the end, at best you end up with a mediocre cross-platform app. I think RN
probably has a sweet spot: a small to medium sized app developed by a sole or
maybe a few developers. Once you're big enough to have teams of developers, I
think RN is a mistake.

With respect to this article, the amount of work and expertise in both RN and
iOS necessary to achieve their performance goals seems pretty extreme ("mobile
performance squad"). And this was all just for iOS? Did any of it translate to
their RN Android app? It's a counter factual so who knows, but I suspect the
performance problems wouldn't have occurred on a native app in the first
place, and if they had, would've been straightforward to track down in
Instruments. They claim all this work is offset by allowing their web app
developers to contribute to the RN app and that it allowed them to develop the
iOS app more quickly, but I have my doubts. As it is, they've got three
developers dedicated to the RN iOS app alone and despite that, still ran into
performance problems.

Again, maybe they have enough shared code and developers to make it
worthwhile, but I dunno.

~~~
jjeaff
I don't think size of app is the concern. It's what your app does. We have a
pretty large CRM style app. React Native is a huge help. Since it's just forms
and table displays mostly, there isn't a lot of platform specific code we have
to create. Maybe 10 or so edge cases where we maintain some differing RN code
to make things work well on both platforms.

~~~
tluyben2
We do mostly Line of Business (LoB) apps and depending on the required target
platforms and desired quality, we usually use Forms, Avalonia (recently) or
Livecode. As CTO, I have a small budget for research, so every 6-12 months I
try a project in something else by timeboxing something trivial and hiring an
expert in another technology to see how that goes.

In our experience RN loses, for our kind of applications (so I am not saying
this is universally true!), from all 3 the above mentioned technologies in
cost, time to implement and long term stability. We have apps running for many
years while requiring fixes/feature additions in the meanwhile and that cannot
cost a lot as they are small features/fixes. Requiring to refactor/fix things
after updates of the platform is just not an option as we do not have many
resources. We had incredibly bad experiences (in backend tech, so apples/pears
but still) in that regard with Ruby/Rails and js/npm; that is great for big
dedicated teams with continues development. We had great experience with
ASP.NET (old+new) and Django; stuff just works after years and not much
knowledge is needed to go from one major version to another (it did not take
us much work to go from asp.net to asp.net core for instance).

Flutter definitely seems promising ; the foreign function interfacing is much
better than RN (imho) and it just seems less like a mess. We will keep
evaluating Flutter while working on/with Xamarin Forms (apps), Avalonia
(desktop) and Livecode (everything).

This is for LoB applications like you seem to target as well; for consumer
facing apps, we write native on all platforms, but that really does not happen
often in my line of work.

------
wdb
Sounds like React Native causes more work then necessary. Business logic can
be easily shared between different platforms, Android, macOS, Windows and iOS.
Always the most time is spend to make the app behave right for each platform,
so that’s only bit which differs. I am happily writing apps in Swift for
Android and iOS

~~~
blunte
Watching some videos illustrating writing iOS React Native apps using
Clojurescript, with REPL changes updating app display in real time (well,
"live") is what makes me interested in RN. Were it not for that, I don't see
why Swift is such a bad thing. I know that maintaining two separate code bases
for iOS and Android is theoretically bad, but I imagine if the apps are
architected well it shouldn't be such an issue.

~~~
rsynnott
> I know that maintaining two separate code bases for iOS and Android is
> theoretically bad

I'm not sure _why_ this should be theoretically bad. It depends what you're
going for, of course, but cross-platform GUIs are typically... not good.
There's a lot to be said for separate GUIs with shared business logic IMO.

~~~
ericlewis
It’s theoretically bad because you’re theoretically wasting your time and
resources. In practice that doesn’t have to be true. But I merged two teams
together via react-native in hopes to make them more productive and it
absolutely worked.

Android is no longer a laggard with features, which was also a big goal of
ours.

That said, if I were to go back and time and know how much of my own time
would be spent _fixing bugs in react-native_ just to keep the team productive,
I might have made a different choice.

Edit: should also be known that I’m no longer helping with fixing RN bugs, and
the team still messages me on occasion to ask questions or for help to fix
things. This was absolutely not the position I was trying to leave that team
in.

Edit edit: my leaving the team wasn’t within my control and management didn’t
realize the level of work to Keep the Lights On nor did the particularly care.

------
nothis
Why, in the "Battery Heat" section is there a link on the small d in Discord
that leads to
[http://watchanimeattheoffice.com/](http://watchanimeattheoffice.com/), which
apparently redirects to discordapp.com. So weird!

~~~
eternalny1
> Why, in the "Battery Heat" section is there a link on the small d in Discord
> that leads to
> [http://watchanimeattheoffice.com/](http://watchanimeattheoffice.com/),
> which apparently redirects to discordapp.com. So weird!

Pssst ...

[https://twitter.com/discordapp/status/1088195791355703296](https://twitter.com/discordapp/status/1088195791355703296)

------
beders
Amazing job by the discord team having the patience with the available tools
to analyze these problems and the stamina to dig deeper and deeper. Well done!

It is quite interesting to see that the re-frame and fulcro authors were on
the right track adding their own 'componentNeedsUpdate' layer which is very
fast and will minimize the repainting React has to do. (Mostly thanks to
immutability)

~~~
mrkcsc
Thank you for the kind words!

------
Justsignedup
I'm just gonna say. Great writeup and a good example case in performance
optimizations.

Now please make discord in windows start up faster than it takes to boot
windows. That's right cold starting my computer and logging in takes less time
than starting discord.

~~~
enraged_camel
Why not just use the browser client?

------
dbg31415
I like Discord a lot, but it's so funky. (Also, wish their support team would
just send a link to allow users to file bugs.)

1) Weird issue where it reconnects you on across multiple devices. I was on my
phone... then switched to computer. Phone was no longer active. About 5
minutes after I got done with the game, Discord on my phone kicked on all by
itself. Phone was sitting in another room, and all of a sudden Discord chat
was being broadcast. (Luckily PTT was enabled so they didn't hear me.) It
shouldn't try and reconnect... once you hang up once, it should know to hang
up across all devices.

2) Can't upload profile or server images more than twice before it triggers
some sort of internal cooldown on uploading images. Just puts you on the same
page and pops a warning, "You have unsaved changes!" but won't let you save.
Quit, wait a few minutes, try again... works. Annoying when you crop something
wrong and have to re-upload. It should always let you upload, or give some
message, "Still sending out your last image to all users, try again in 5
minutes."

3) Can't resize Window via window manager (Magnet on MacOS). I think this is
the only program I have seen that won't let me drag and snap it. Annoying.

------
ThomPete
We were considering using React Native for our task and communication app for
non-desktop workforce, we even started out that way but realised how much
effort we would have to put into getting things working especially since our
interface is a little different and ended but ended up building native for
both Android and iOS. Haven't regretted it a bit.

~~~
chasd00
the cross platform dream is so appealing and I've used Ionic off and on for
years because of it. At the end of each project I say to myself "never again,
i will just learn Swift" ( i already know java ). Then, slowly but steadily,
the cross platform dream takes root and blossoms. Off I go with the latest
Ionic and "this time it will be different".

------
rkangel
It's good to see that they care a lot about TTI and put work into
optimisation, but the desktop app needs the same love. My Windows PC boots to
the desktop in less time than it takes for Discord to then start up. I'm
unclear what it's doing - checking for updates?

This is about my only gripe with Discord though, it's a great service.

------
dannyr
So Discord's iOS app is React Native while its Android app is native (i.e.
Java/Kotlin)?

~~~
mrkcsc
Blog author here - this is correct (mostly Kotlin :)

This is primarily an artifact of history for us. When we first set out to
build the mobile apps, React Native for Android had not yet been open sourced
so we had no choice but to build it in native.

That being said, the Android side of RN has always been more nascent and so
one of the benefits for us has been not having to deal with some of those
early bugs/issues while building our our current iOS app.

It's since become much more mature however - so we may explore RN for Android
again someday.

------
llacb47
Their app is still slow...

~~~
dancemethis1
Grabbing all that user data and metadata has its share of computing cost. But
hey, the higher-ups will profit from it so it's ok.

------
olah_1
In terms of snappy / beautiful messaging apps, nothing beats Telegram imo.

It's made with Qt, I believe.

~~~
ignoramous
The client code is open-source, btw:
[https://github.com/DrKLO/Telegram](https://github.com/DrKLO/Telegram)

------
jammygit
Has anyone ever tried a graphics engine for cross playform desktop apps?
Godot's interface is made in Godot for example.

------
defied
Another good optimization step is to replace the JsC engine for Android with
Hermes.

~~~
saghul
Is it ready for prime time? IIRC it has only been around for the last couple
of releases which makes me worry a bit.

------
xez
what does TTI stand for? I'm having some trouble figuring that one out

~~~
neon_electro
Time to Interactive: [https://calibreapp.com/blog/time-to-
interactive](https://calibreapp.com/blog/time-to-interactive)

------
nfRfqX5n
great work

------
hqrlk
The iOS app of Discord is crappy compared to the Android app. I mean, it's not
bad bad, but it's not good, or at least not as good. I wonder why they decided
to go this route instead of hiring iOS developers?

I could understand if they used the same app for both platforms (like they do
with their Electron app, which is also not as good as Ripcord), but since they
have a native app for Android...

~~~
Assadi
As far as I know, they use react for both. Where did you hear that they had a
native android app?

~~~
hqrlk
Since their iOS and Android apps are different, and the iOS one is built using
React, I just assumed the Android one is native. Why would they build two
different React apps? Isn't the entire point that you can share the code?

~~~
sedeki
The point of React Native is being cross-platform, yes. But you said Android
had a native app.

