React Native vs Objective-C / Swift

By Malcolm Diggs, Head of Engineering

Posted in react native, javascript, ios, swift, objective-c, reactnative, react

The task in front of us was fairly straightforward: build one consumer-facing iOS app, and a suite of back-of-house iOS tools for employees to use. All we had to figure out was how. Should we build them in Objective-C? Swift? Or use a webview-based compiler like Phonegap or Titanium? Or, should we go far out on a limb and embrace React Native?

In the end, we decided to do the latter. and the decision came down to 5 factors:

1. Instant Deploy

If you come from a web-development background, you probably find the app-store-delivery process insanely cumbersome and slow. I know I do. 1-2 weeks to get an app approved/rejected, and then another 1-2 weeks to get your subsequent updates deployed. This flies in the face of “Continuous Delivery”, a concept we’re attempting to embrace whole-heartedly. It also means we’re crippled in our ability to fix bugs in a timely manner. React Native has a great solution to this problem: They take advantage of a special clause in the iOS Developer Program Requirements.

[3.3.2] An Application may not download or install executable code. Interpreted code may only be used in an Application if all scripts, code and interpreters are packaged in the Application and not downloaded. The only exception to the foregoing is scripts and code downloaded and run by Apple's built-in WebKit framework or JavascriptCore, provided that such scripts and code do not change the primary purpose of the Application by providing features or functionality that are inconsistent with the intended and advertised purpose of the Application as submitted to the App Store.

In plain english, this means that React Native apps are allowed to self-update themselves on the fly (using services like AppHub or CodePush). When we commit new code, we can push our update to every user instantly, no waiting for app-store-approval. This might seem like a small thing, but the consequences are vast:

  • We will not have to worry about some users using old/outdated versions of the app. Every single user will be on the same version of the app. The app experience for users will improve continuously over time (several times a day) rather than only-after they opt-in to an update every few weeks.
  • The above means that we won’t need to maintain several live versions of the API. We’ll only need one version (the latest version) live at any give time, because no app will be requesting old/deprecated services. The burden this lifts off the backend team is huge.
  • We’ll be able to fix bugs immediately. If a user reports an issue, we can address it and get a fix out the door (and working on their phone) the same day.
  • The feedback loop for A/B testing and new product features will be much shorter. Normally, if we wanted to test a new feature, we’d have to plan the test, ship it to the app store, wait a couple weeks, then collect data, and then push another update which removes the test/feature (and then wait a couple weeks for the test to stop running). This is no longer a problem. If we have a test we’d like to run, we can push it today, collect data, and remove the test as soon as we no longer need it.

2. Faster Development Cycle

Not only is Javascript a higher-level language than objective-c/swift (and thus quicker to produce applications in), but with React-Native we won’t have to wait for xCode to compile our changes as we work. If you’ve ever developed a traditional iOS app, you know that the ~30 seconds you have to wait after making a change (before you can see that change compiled in your simulator) can really add up. Waiting for 30 seconds over and over again can kill your momentum, and just generally piss you off. React Native doesn’t face this problem. You can see your updated app in the simulator in less than a second after you save your changes.

3. 85% Reusability for Android

The estimates vary, but reports from the field estimate code reusability across platforms at roughly 85% or better. We’re rolling out entirely on iOS at first, but when we get ready to do Android, we should only have to rewrite about 15% of our apps. This is a huge time-saver. For perspective, that kind of time-savings would shorten a 2-month build cycle to just over a week. Pretty significant.

4. 100% Javascript House

Our backends and web-frontends will likely be entirely javascript (node.js APIs and Angular SPAs). If we use React Native for our mobile apps, then our mobile team will be working in Javascript as well. This is more than a novelty or a badge of honor for javascript-gurus. This has real-world impacts:

  • Anyone on the team can pitch in on any part of the stack at any time. As long as every engineer is strong in JS, they’ll be able to build mobile, web, or backend components.
  • We can allocate resources where they need to go. If we need more help on mobile during a sprint, we can re-assign front-end web engineers or backend engineers to the mobile team, and vice-versa. Every developer will be useful on every project. This pushes the Scrum tenet of “Generalizing Specialists” to a new level.
  • We’re going to get really really good at Javascript. Every bit of knowledge that each developer gains can directly affect the productivity of every other developer. We’ll be able to get in the habit of training each other on new techniques and creating know ledge-bases and style guides that are useful to everyone.
  • As we build out our applications, code-sharing will be much higher than on traditional teams. If the backend folks create an NPM module that does XYZ, that can ported and used on mobile as well. Only one person has to solve a problem. Once that’s done, everyone can benefit from it. We can focus our recruiting efforts on one area. We no longer need to worry about recruiting “backend” devs, or “frontend” devs, or “mobile” devs. We just need to focus on recruiting javascript folks. This is a lot simpler and raises the chances that we’ll find someone when we need them.

5. The Old Counter-Arguments are Outdated

There were a few solid (and convincing) counter-arguments in the Swift vs React debate, but all the ones I’ve researched are actually outdated. Some people still claim (wrongly), that you have to bridge to objective-c as soon as you want to do anything fancy like use the camera or gps. This used to be true, but react-native is an open-source project that is growing and changing constantly. These days, there are prebuilt modules for the features I mentioned, and pretty much everything else you’d need to do. I’m sure there are still some native capabilities that don’t exist on React-native yet, but the vast majority of use-cases have been covered. And as far as I can tell, all the use-cases we have planned for our builds have been covered.

There also used to be claims that react-native performance was slower than a true native app. But, as the project has grown, this also seems to no longer be the case. React video/animation components regularly reach 60 fps without dropping frames, and react has pages in their docs addressing the proper way to build components so that they work quickly. It seems that (like all javascript applications), there are slow ways to build things, and faster ways to build things. But that isn’t the framework’s fault, it’s the developer’s responsibility to know what he/she is doing, and how to make the best use of the tools at their disposal.

For all those reasons and more, we’re going with React Native. We couldn’t be more excited to get started building these apps. I’ll be sure to post up again soon as we explore the platform and start shipping apps to production.