top | item 34197613

React Native is not the future

280 points| samwillis | 3 years ago |blog.standardnotes.com | reply

330 comments

order
[+] crossroadsguy|3 years ago|reply
There is no better way to build a mobile app than a native app. This was shown yet again when I tried Standard Notes few days ago for the nth time. It still is sluggish and slow and felt like having too many jerks and clunks. Downright unusable for a major notes app in 2022.. well 23.

Among Joplin, Obsidian, FS Notes, Bear and few more Standard Note was the worst experience by a margin. Not to mention they still not allowing local raw files citing “but encryption”, or maybe they’ve moved to another reason now.

Another example of how developers can become blissfully oblivious of what users find good and start confusing it for what is “good” for developers themselves.

[+] jitl|3 years ago|reply
This sounds exactly like Notion’s mobile app tech stack roughly 4 years ago - a web app running in a React Native wrapper webview. We really struggled to get that architecture to perform well, in particular for local caching, although improved React Native bridge performance might make it more feasible these days.

What we noticed is that we’d incur substantial performance bottleneck for anything that needs to move data to/from native because of the number of encode/decode steps and “bridge hops”. For example to read a row from SQLite, count the bridge hops:

Webview JS -> Java: postMessage to read a row from SQLite

Java -> React Native JS: hey, a postMessage happened, what to do?

React Native JS -> Java: please select * from … where …

Java -> C: ok really run this SQL

Then the stack of conversions repeats on the way back to the webview:

SQL C -> Java -> RN JavaScript -> Java -> Webview JavaScript

The other thing that plagued us performance wise was boot-up speed. At the time (before Hermes JS VM for React Native), we’d have to wait for RN’s JS to boot, figure out our cache status, then boot the webview JS. And then the webview JS would do the bridge dance above to pull data from SQLite to render. Slow - 40 seconds on low end Android slow.

Today we are still mostly a web app, but our wrapper is pure native code. We cold start to a native view and boot the web app in the background. Our throughout & latency to native APIs is substantially faster without the extra bridge hops into and out of the RN JavaScript VM. We managed the original architecture swap from RN -> true native wrapper with a team of three - myself, our first iOS engineer, and our first Android engineer. We do have a large mobile team now though.

There’s some more FAQs and answers about this on Twitter here: https://twitter.com/jitl/status/1530326516013342723?s=46&t=x...

One thing I’d add is that deciding to use a webview wrapper is quite common for multiplatform rich text content editors. Google Docs, Dropbox Paper, Quip, Coda, Notion all use this architecture on iOS and Android because implementing an editor is extremely complex. It’s much more expensive to implement an editor 3x than say implementing a few list views and a form 3x.

[+] SturgeonsLaw|3 years ago|reply
That's what puzzled me about the article. Why even have React Native in the mix if all you need is a webview and some code to hit native APIs? Is it ease of build/deployment? Developer QOL/familiarity?

I think your way of doing things would provide a better experience for users and I'm not sure what value RN is adding here.

That said I am not a JS or mobile dev so I might be missing something obvious.

[+] samwillis|3 years ago|reply
That's super interesting, I've read your previous comments about adopting SQLite. With WASM SQLite nearly ready and the origin privet file system API becoming available, do you expect to adopt that in the browser? And if so would you then align the mobile app closer to the web app by sharing that code?

A while back I was working on a notes app, tying to go the single codebase route with Capacitor. The biggest problem I found was with the text selection cursor on iOS. It sits on a layer above all other elements and even appears outside of scrolling overflow, so it would appear over toolbars, really nasty UX. Did you come up against that? As far as I could tell the only solutions were to have a native UI and only use with webview for the editor (that immediately meant writing the UI twice), or create a custom carrot and selection indicator (nasty!).

[+] no_butterscotch|3 years ago|reply
> our wrapper is pure native code. We cold start to a native view and boot the web app in the background. Our throughout & latency to native APIs is substantially faster without the extra bridge hops into and out of the RN JavaScript VM. We managed the original architecture swap from RN -> true native wrapper

Does this mean you boot the web app in a native WebView in the background (not visible), while showing a [splash?] screen until the web-app sends a signal from the web-view to java (or swift?) that it's ready?

Or have you started to build out native-views too? eg. Splash screen, some other super top level screens, etc?

[+] infensus|3 years ago|reply
Huh. At work, I did the same for a WYSIWYG editor we had to implement, but it always felt wrong for me. After looking for a native editor library I was surprised how little I could find. I can sleep a little better knowing that even the heavy hitters resort to webview sometimes
[+] dchest|3 years ago|reply
Even the first iPhone OS used WebView for all text inputs before they implemented "native" components. Literally, every text control was a WebView. Turns out they are really great for text editing :)
[+] Joeri|3 years ago|reply
This is an architecture I’ve noticed most (if not all?) large cross-platform mobile apps land on: a native core to quickly get the user to an interactive state and have smooth navigation, that then gives way to some kind of web technology for the actual feature screens.
[+] skrebbel|3 years ago|reply
How do you boot the webview in the background? I tried this once but couldn’t figure it out.
[+] CosmicBagel|3 years ago|reply
As someone who uses this off an on amount, I was really disappointed when I opened the app to the new web app. It was slow, janky, required me authenticating multiple times (biometric then username and password). I'm now looking for alternatives because "as fast as possible" is an important feature for me. I keep the app on my android home row, not because I use it a lot, but because when I need it, I need it instantly. Massive downgrade for the user imo, this only benefits the developer.
[+] throw03172019|3 years ago|reply
It sounds like they are migrating portions to native first.
[+] gloosx|3 years ago|reply
React Native, which was meant for writing amazing native apps, is just misused as a browser web-view thing. I am an expert in this field. Just never use React native to open single WebView. Never try to turn your website into mobile app like this. If it's a website, it's a website. If you need app make app. React, Electron and React Native enables you to make apps using Javascript, which is same as your website, it means you can have the same business logic between web and native app, same language it all written in, team talking on the same language, only the rendering logic will be different, which is huge saves. But it's not Flutter. It was not meant just to present webviews with your webpage. There is a Browser for that. Finally there is a PWA for just exactly that.

Amazing stuff which React + Electron + React Native enabled - abstracting JS from Web to App - is so much crooked by folks trying to turn it inside out

React Native is not the future – for folks who don't understand how to use it. In fact they hate using it wrong. For me – it's the future, i can use only one language to create an Android, iOS, Windows, Linux and Mac native apps. (of course, i would never try to fit it into a single front-end codebase, this is pure madness)

[+] ilmor|3 years ago|reply
It may be ”single language”… until you have to dive into the insides of a React Native library at which point you also have to know at least Java AND Objective-C. Add to that Windows-specific language(s) if your library will want to support Windows.

And let’s not even think about those cases when a feature is written with not all the platforms in mind. I once had to fix a bug where a developer did not have access to an iOS simulator to test their pull request… so they had merged it in without support for iOS.

[+] extheat|3 years ago|reply
Most importantly platforms like RN substantially lower the barrier to entry for making mobile apps, and cross platform ones at that. Whenever you lower the barrier to entry to something you inevitably attract low quality, low effort content that can obviously damage the perception of the broader platform. Setting that aside however, the development agility that RN provides I think is priceless. Most apps don’t need maximum performance, or the usage of niche platform specific APIs and so the time you’d spend working with two standalone codebases can be reinvested in your actual product and not mental overhead.
[+] supermatt|3 years ago|reply
> of course, i would never try to fit it into a single front-end codebase, this is pure madness

If its a single app for multiple platforms, and you are sharing code and views, why wouldnt you fit it in a single codebase? Surely to do otherwise would be unnecessarily complicated?

[+] Kiro|3 years ago|reply
I run a fairly popular mobile web app and the most common request is for me to release it as a native app. I try to tell them that the app would just be a web wrapper and that they wouldn't get any different experience than from running it in the browser, but it doesn't matter. Even after showing them that they can install the PWA they just say "I'll come back when you release it as an app".

My point is that users don't care if just showing a website in a WebView is misused technology. They want an app regardless and telling them "a website is a website" is futile.

[+] jitl|3 years ago|reply
How would you make a multi-platform rich text editor in React Native?
[+] mrbombastic|3 years ago|reply
One codebase sounds great but I always feel devs try to ignore that there just are significant differences between platforms that you must address if you want a well integrated app. Writing separate codebases in native iOS, Android, and web has a huge amount of waste but you can achieve higher quality and os integration, writing react native and react on web means you get just 2 codebases and higher dev productivity but at the cost of pain in libraries which typically also means less native integration, the solution proposed here means 1 codebase and even less native integration. If it is right for you great but like everything it is tradeoffs, pick your poison.
[+] danielvaughn|3 years ago|reply
Agreed. Although the economic reality is that it’s borderline impossible for a company to develop a cross-platform native product unless they have significant amounts of money. Cross-platform is a terrible necessity to that end.
[+] esperent|3 years ago|reply
On the other hand, I have used some web apps that, when I "Install as an app" on Android, work pretty well.

Sure, there are a couple of annoyances mostly related to notifications and how it works when switching between apps, but these are quite minor parts of the app - sure, they're annoying and need to be fixed but it's also important to acknowledge that the other 99% of the app was running correctly and with decent performance on my mid range phone. I think that the remaining issues, including perform, are fixable and will be fixed over the next few years.

You might not write one fully unified code base but you'll at least be able to use 99.9% of the same code with just a little bit of glue on top to make user accounts and notifications work on other platforms.

[+] waspight|3 years ago|reply
The thing is that most paying customers are most often on iOS, so target that experience while using react native and you will get some Android users for free. Android users are less likely to pay anyway.
[+] sureglymop|3 years ago|reply
Tried it out on Android and it feels janky. It just feels like a web app and it's not working well. To just give one example, if I click on the header of a note, a menu with "options" shows up. But Android also selects the text in the header and pops up a menu with "Cut, Copy, Paste, etc." which is exactly on top of that menu I was actually trying to get to...
[+] moughxyz|3 years ago|reply
Eh, these are easy fixes. We're making progress daily on making it feel more "native" (i.e recently added present/dismiss animations). Try the demo[0] in your mobile browser, should feel pretty smooth. We've tested extensively on a whole range on devices and performance wasn't an issue. It's really the animations (or lack thereof) that make or break perception of "jankiness." What we have now is our first solid functionality-oriented release; next releases focus on tidying up the edges.

[0]: https://standardnotes.com/demo

[+] todd3834|3 years ago|reply
We went forward with this exact solution years ago at a company I worked for. In our case our mobile usage was actually really low compared to web. It just didn’t make sense to invest in native development. So we found React Native with web views to work pretty well. We also tried React Native Web, it was a lot newer and kind of an experiment back then. It was cool that we could get it to work but the web results were a little crazy when you care about semantic markup and SEO. It might have changed a lot since then.

More recently I worked on a team that wrote a lot of business logic in C++ to share across android and iOS. We ended up compiling it to WASM and we were able to build a web interface pretty quickly. A lot of languages are trying to make this easier. Kotlin standing out to me as an easy learning curve and prioritizing this. Challenge there is not using Java platform specific libraries on the shared stuff.

I do think there is something to be said for sharing pieces of the UI too.

I think the future looks bright for multi platform development. There is still some work to be done but it’s all heading in the right direction in my opinion.

I think you’ll have iOS, Android and Web specific code mixed with multi platform pieces. Both business logic and UI.

[+] todd3834|3 years ago|reply
As always it’s going to depend on the app. The Tesla mobile app in React Native works perfectly fine for me on iOS.

At the same time web views for YouTube would probably suck.

So many situations and so many options… again I’m very optimistic about the direction things are goin.

[+] stmw|3 years ago|reply
This is an important technical discussion, one that the community needs to keep having to reduce unnecessary work and get more cross-platform support. There is a lot to be learned from (and reused) from history.

For example, part of the post here is "When web-land wants to access the device keychain, it sends a message to native-land, and native-land responds with a primitive value. Neither native-land or web-land ever have to think about "messages" though. They're just function calls. Web-land has no idea that its function calls are being converted to postMessage calls behind the scenes."

That is very similar to Microsoft COM, DCOM and COM+, which all appeared at the points when Microsoft had to cope with levels of complexity similar to those in the browser and mobile platform diversity observe todday.

ref: https://en.wikipedia.org/wiki/Distributed_Component_Object_M...

[+] riveralabs|3 years ago|reply
What are your users saying? Especially mobile users. Are they expecting a native experience? Engineering decisions that sacrifice user experience usually don’t have a happy ending. As a native iOS developer the best feedback I can get is when somebody tells me that my app looks like it was developed by Apple. I like using vanilla controls as much as possible. But as previously mentioned its all about tradeoffs.
[+] billllll|3 years ago|reply
I don't have personal experience with this, but React Native Web claims to solve this issue: https://necolas.github.io/react-native-web/, not sure if anyone has had experience with this. Of course, you will have issues with dependency hell/package maintenance.

Another great option seems to be Flutter web. I was really impressed by the "batteries included" approach to Flutter, and Dart has a pretty comprehensive standard library. This is in contrast to React's "just find a random package on npm and pray it doesn't bite you in the future."

Obviously rewrites are expensive, but I personally think both approaches are worth considering versus abandoning native components completely. WebView isn't without problems (and also, you don't need React Native to use WebView).

[+] deergomoo|3 years ago|reply
While the engineering is impressive, I just can’t get on board with how Flutter works.

Imitating native components seems both incredibly wasteful and also very fragile considering Google has an attention span comparable to a puppy.

[+] ericlewis|3 years ago|reply
combining RN and RNW is a pain in practice. It can be done, but not easily.
[+] robertoandred|3 years ago|reply
Sounds like he's just inventing a slower, less native version of React Native.
[+] yawnr|3 years ago|reply
Yeah seriously. Just a worse version of the bridge. IMO the cart is leading the horse on this one. Might be more convenient for their dev team to just have a web codebase (though I’d argue if they took the time to transition their web codebase to react native web they’d see the same benefit), but it will definitely hurt UX.
[+] hokumguru|3 years ago|reply
Really do check out Turbo Native from the Basecamp team. They’ve taken this hybrid web approach a step further with a bridge and native navigation. It is quite difficult actually to distinguish between their apps and real native UI, the library is astonishingly good.
[+] stanislavb|3 years ago|reply
And, what is more, it’s heaps easier to develop and maintain compared to React.
[+] stevenhuang|3 years ago|reply
Interesting tech. Looks like it's developed by hey.com, and their email app on Google Play store is only 9MB, which is impressive.

From what sparse commentary I could find online, looks like this is a middle ground between web dev and native dev. It allows reusing server logic to emit html markup for mobile UI, but requires platform developers to put in the necessary native pieces piecemeal (sensible choice considering the leaky abstractions in react native).

https://play.google.com/store/apps/details?id=com.basecamp.h...

[+] Izkata|3 years ago|reply
> Quite simple really: a bridge between web-land and mobile native-land. Our new mobile app still uses React Native, but is literally just 1 component: a function that renders a webview.

I don't know about the wrapper, but the entire app being a webview is how Peapod (grocery delivery) has been for years.

[+] ndomanop|3 years ago|reply
I've also been wondering why people still use ReactNative despite the availability of much simpler stacks.

For me I use React to create User interface for all platforms then ship it as a mobile app using native webviews on Android and iOS, also I can use Electron to create a desktop version. Good thing is that these webviews offer Javascript Interfaces where you can access all native functionality you need.

With a little bit of craftiness you can make your React Code (User interface) detect whether it runs on web version, mobile version or desktop version then make it behave according to what you want.

I choose React for UI coz it's damn simple though you can use any other javascript based UI library.

[+] diimdeep|3 years ago|reply
The only way to survive with a single code base is to go the way of gamedev, to own the substrate you are running on completely. From rendering of fonts to user input. This, of course, depends on the complexity of software. App in this blog post is not really that hard compared to the effort any game would need to go to render on screen. C'mon, it is just a text editor, there is not much of anything there really. All this just shows the state of modern development of too many abstractions for really nothing in exchange except a slow, overengineered fashion hype train. Surprised, there is no mention of WebAssembly in there. (edit typos)
[+] akmarinov|3 years ago|reply
“And then we wanted to write a widget or use the dynamic island and we realized we can’t, so we just delivered a subpar experience, but hey - who cares about user UX when our dev UX is so great”
[+] codeptualize|3 years ago|reply
I don't see why that wouldn't be possible, they are still using React Native so they still can use native functionality where necessary.
[+] teucris|3 years ago|reply
So, essentially Phonegap/Cordova again? I always liked that model. I’m not entirely clear why it fell out of favor.
[+] matchbok|3 years ago|reply
With the right libraries and clean code, going native for iOS/Android is usually the solution. Building UI/networking/etc quickly in Swift/Kotlin just isn't an issue anymore. RN/Flutter won't be used in 5 years.
[+] Ian_Macharia|3 years ago|reply
Strongly disagree. Both frameworks save on dev time to a very significant degree. I actually foresee better cross platform solutions being introduced in 5 years
[+] tested23|3 years ago|reply
Ios and android development as they exist today will die once governments mandate then end of the app store monopolies.
[+] jacobp100|3 years ago|reply
Have you tried SwiftUI? It’s not replacing RN any time soon
[+] gauddasa|3 years ago|reply
With tons of effort put on browsers to adhere to web standards and seamlessly interface with different kinds of hardware and platforms, the nasty hard work has already been done. How many times will the wheel be reinvented? It is consumers who should openly demand for web applications and resist efforts pushing for app alternative. This will help the consumers hide their backs and developers save their backs.
[+] krzat|3 years ago|reply
On desktop this is already settled and most of everyday stuff is done through websites or electron apps.

I suspect that Apple/Google will never let this happen due to 30% tax they steal from devs.

[+] scrame|3 years ago|reply
But then how would a crappy fly-by-night startup pull in all your local data and sell it off when the VC money runs out?
[+] college_physics|3 years ago|reply
I have read the post and 60 comments but the "future" is as clouded as ever. I wonder if there was ever a period where developers had such difficulty identifying how to best deliver applications.
[+] rubicon33|3 years ago|reply
There is no difficultly in identifying how to best deliver applications. The issue is entirely resources.

If you want to deliver the best applications, there is one answer - native.

If you want to deliver the best application given a small team or other constraints like time, then you have a plethora of hybrid options at your disposal (react native, flutter, etc.)

But at the end of the day the fact remains that almost every app written in a hybrid framework, would be better, smoother, and less of a frustration at scale, than hybrid.