So you want to build a mobile app. Maybe your product is mobile-first, or maybe you have an existing website and want to supplement it with a native app. This is a big decision, since switching between native and hybrid apps down the road means starting over. So how do you decide, especially in the early stages before you’ve even hired a full time engineer?
Note that this is NOT a discussion of whether your product should be a mobile-optimized website or an app. This assumes that you have already made the decision to build an app; that is, something users will download from the App Store which will install an icon their home screen that launches your product. I’ll also only discuss iOS and Android, not the other mobile platforms.
I’ll discuss your three main choices: native, hybrid, and React Native. Other technologies such as Microsoft’s Xamarin and Appcelerator’s Titanium have similar pros and cons as React Native, but I won’t elaborate on them further simply because I am not very familiar with them.
WTF is it?
The gold standard in terms of performance. In the beginning, developing native apps was the only option. Native apps use the tools and frameworks provided by Apple and Google, and must be written in the language(s) those companies provide to developers: Objective-C or Swift for Apple/iOS and Java for Google/Android.
- It’s fast. There’s no denying that engineers can build the most performant apps by going native.
- Robust library support. Since native apps have been around since the beginning of their respective platforms, a rich ecosystem of of libraries and tools have developed for each. This means there are more out-of-the-box tools that save your engineers from having to implement certain functionality by themselves.
- More experienced engineers. Since it’s been around the longest, there are more people experienced in developing native apps than the alternatives. If someone says they’re an iOS engineer or an Android engineer, they are likely talking about native development unless they specify otherwise.
- Zero cross compatibility. Since Android and iOS use different programming languages (Android uses Java, iOS uses either Objective C or Swift), there’s no way to share code between the two. You have to start over.
Hybrid Apps: Cordova, PhoneGap, Ionic
WTF is it?
Cordova, PhoneGap, Ionic, and several others are all essentially web pages wrapped in native apps. They use familiar web development practices, but let you bundle your app so that it is downloadable from the App Store. They also give developers access to functionality that apps have but webpages don’t, like the camera, compass, and push notifications (although some of this functionality is now available to some extent using HTML5).
- Most similar to web development. That’s a pro because (1) there are more web developers than app developers out there, and web developers will be able to learn how to develop apps using these frameworks easily, and (2) many of the tools and libraries available for the web can be used by hybrid apps.
- Cross-platform, including web. Most of the code written can be shared across iOS, Android, and even the web. There needs to be some custom code for each platform, especially if you don’t want them to look and behave identically, but a large portion of the codebase can be written once and used everywhere.
- Faster releases. On iOS especially, when a code change is complete, it has to be submitted to Apple for approval which can take weeks (recently it’s been down to a couple days, but that’s still a long time to wait for an urgent change). You also have to wait for users to upgrade, which might be weeks, months, or… never. Theoretically, hybrid apps allow developers to bypass this and refresh code on the fly. However, you could get in trouble with Apple if you try to sneak something past their reviewers. Their guidance on this has changed over the years, so check on their latest stance before trying it.
- It’s slow. These hybrid apps simply won’t perform as well as the other options. You may not notice it with a simple app running on the fanciest smartphone on the market, but as the app’s complexity grows or when you try it on a lower-end device, you’ll start to notice that the app feels sluggish.
- It lacks native elements. WTF does this mean? I’m glad you asked! The UI elements that make an iOS app feel like an iOS app and an Android app an Android app do not come for free when developing a hybrid app. Think the tab bar on the bottom of many iOS apps and the action bar (the header) present in many Android . Also think about gestures like swiping and pinching to zoom. Much of this can be re-created using Hybrid apps, but it’s a lot harder, especially where the platforms differ from each other. This can make the user feel like they’re viewing a webpage rather than an app, because that’s essentially what they’re doing.
WTF is it?
The youngest entrant in the race, React Native was first released by Facebook in 2015. Proponents claim React Native is the holy grail: almost as performant as native apps yet still cross-platform.
- It’s cross-platform. Like the hybrid solutions, there is some extra work needed to make an app work on both iOS and Android using React Native, but the majority of the code can be shared. This will save your engineers lots of work if they’re developing for both platforms. It is not compatible with the web, however…
- It closely parallels React for the web. React is distinct from React Native – they are not cross-compatible – but they share the same philosophy. Some code and libraries can be shared between the two, but a large portion will need to be re-written.
- It’s easy. The learning curve for an engineer to learn how to create a React Native app is much faster than for learning how to create a native app.
- It’s sexy. The fact that the tech community is excited about React Native shouldn’t be discounted as it helps recruit new engineers.
- It can be extended with native code. If React Native isn’t capable of a certain task or if it can be done more efficiently with native code, it is fairly straightforward to write certain portions of the code using the native language. But these portions will have all the cons of native development, including lack of cross-compatibility. It also means that you need engineers skilled in both React Native and the two native platforms in order to take advantage of this feature.
- It’s new. There are a few reasons this is a negative: (1) It could change substantially in the future, causing re-work for your engineers. Libraries and best practices are still being developed and debated, so the state of the art code that your engineers write today might be considered technical debt in the near future. (2) There’s risk that React Native won’t survive the test of time and will become obsolete. The graveyard of abandoned frameworks is overflowing.
- It’s slower than native apps. While React Native is arguably almost as fast as native apps and will likely continue to get faster, the “almost” will never go away.
- Support for hot new operating system features will lag. When Apple or Google release a new OS feature, native developers can start using it immediately. React Native developers will have to wait until the developers of the platform (eg. Facebook and the Open Source community) support it or write their own native module. For example, I wrote a small iMessage app shortly after Apple allowed developers to integrate directly with iMessage. I tried using React Native in order to experiment with the platform, but ended up building a native module that did most of the work since React Native had poor support for the new iMessage functionality.
That’s all very nice. But which one should I use?
As with all of my posts, I tried to stay as unopinionated as possible and give you the information to make the decision yourself – with your engineer, of course. But my inspiration for this article was several conversations I’ve had recently with non-technical entrepreneurs who were just getting started and were trying to decide which contractors to hire. So I’ll bite. Here’s my opinion on when to choose which option:
- Native: Choose this when speed & performance of the app is your top priority. Others can come close, but none will surpass the snappy feel of a native app. Also tend toward this option if you are happy to iterate on one platform (iOS or Android) without worrying about the other until you have the resources to double your mobile engineering team.
- Cordova/PhoneGap/Ionic: This option will be the cheapest and the one that will get your initial app completed the fastest, especially if you really need both iOS and Android from the get-go. This would be my choice for prototyping, with the understanding that if the prototype is successful, you’re likely to want to start over with one of the other options down the road to optimize the user experience.
- React Native: In my opinion, this is an excellent compromise. You can get near-native performance, relatively fast/cheap development, and cross-platform out of the box. The fact that it can bridge to native code means that you won’t have to completely start over if you needed to optimize some parts of the app for even better performance. This is the riskiest option, however, in that it is very new. The framework might turn out to be a passing fad, and if it does make it, it is likely to change the most rapidly causing re-work for your engineers in order to stay modern.
2 thoughts on “I want to build an app! Should it be native or hybrid?”
Very helpful article. Thank you!
I am using Xamarin and the speed is actually comparable to native for both platform. Yes, it embeds Mono on Android and does AOT for iOS, but it does not matter too much. My company right now is using Xamarin because of MvvmCross, it is pretty much painless to develop generic application across platform. Problem comes when you want to integrate non-standard plugin since it requires you to create a “Binding Library” project – which is does not work sometime.
But anyway, it is edge case. Most use cases can be handled by Xamarin and MvvmCross itself. So far we created custom components/classes/ui/or whatever the name and it work fine (instead of binding library)