Psst! This is cross-posted from the LandTech blog. Oh, and we're hiring!

React native is a cross platform app development framework, primarily used for building apps for iOS and Android, almost entirely using Javascript / React. It allows Javascript developers to use the tools and techniques most familiar to them to create full-featured, native applications which look and feel like their Swift / Java counterparts.

A few months ago, we launched our first mobile product using React Native. LandInsight GO is a cross-platform companion app to the main LandInsight web app, allowing users to explore and save potential development sites while out of the office, as well as access their existing LandInsight saved sites.

In this post I’ll be talking about some of the key technologies used to build the app, decisions made around them, and some of the pain points encountered along the way.

Expo vs Native

Expo is a framework, toolset, and collection libraries aimed at making React Native development a smoother experience than in its basic form. The main draw is that you can very quickly build an app without needing to install any Native SDK tooling (ie Xcode, Android Studio). This is great for fast prototyping and validation of an idea for an app. They even support building and publishing to iOS and Android app stores. This comes with a drawback, however, in that you cannot install extra native dependencies (without extra complication).

We knew quite early on that we would need to use Mapbox’s native map library, so unfortunately Expo was a no-go, and we went fully native.

JavaScript vs Flow vs TypeScript

This decision is probably worthy of a blogpost on its own, and the pros/cons of static typing could be debated at length. When we started building our app, the status quo in React Native was plain JavaScript (and JSX), Flow was the only supported static type checker, thanks to Babel, and TypeScript required quite a complicated two-part build process. The decision at the time was to run with Flow due to its relatively simple setup. We had just started experimenting with Flow in our back-end Node.js code, so it was an easy decision to make.

By using Flow, we get instant feedback when calling a function with incorrect argument types, and refactors are a lot easier (and safer!). However, the typechecking process in Flow can become very slow, with the background process using vast amounts of memory. This isn’t a problem commonly encountered by TypeScript, and generally the tooling seems to work better (Visual Studio Code in particular), so in hindsight we would have been better served by using TypeScript instead.

Today, React Native has almost drop-in support for TypeScript. The language in general has much wider adoption then Flow, and an more active community. We have since migrated our back-end Flow code to TypeScript, and will migrate our React Native Flow code to TypeScript soon as well. If I were to start a new React Native project today, I would go with TypeScript over Flow (or plain JavaScript).

Build process

Because we opted for a native build instead of Expo, we are responsible for the entire build / test / deployment process. To do this by hand, this would involve building locally using the React Native command line tools, and uploading the generated native binary files to the App Store and Google Play Store. But we can do better! Nobody likes doing these time consuming, manual tasks. Our entire web application stack is continuously deployed so why settle for less? I had read about the magic of Codepush, which allows developers to push updates to their React Native apps over the air, bypassing the infamous App Store review process. Codepush integrates seamlessly with Visual Studio App Center, which is Microsoft’s CI platform. By using App Center, every commit to master kicks off a new build for both Android and iOS, which is pushed to the respective app store platforms if the build succeeds. App Center is almost trivial to install, and vastly simplifies the process of setting up CI/CD for React Native projects.

The builds themselves aren’t exactly fast. If you’re used to the typical Node.js or Webpack build times, prepare to be disappointed. React Native isn’t particularly lightweight, and once you’ve thrown a few native modules into the mix, expect to see build times exceeding 15 minutes. This isn’t a criticism of App Center, but it does mean that having a local testing process is far more necessary than simply relying on the CI platform to tell you if the build is broken. For testing, we went with Facebook’s open source framework Jest. Unit tests are run as part of the build process to prevent a broken app from making it into our customers’ hands!

iOS vs Android

React Native is a cross platform framework. One codebase can be used to output native apps for many different platforms. This was one of the main reasons why we chose React Native over pure native code, however it wasn’t without its own set of problems.

It’s fair to say that while iOS and Android apps built with React Native are similar, they are not identical. The same code running on iOS will have a different look and feel to that of Android. Native modules might also behave differently, as they have to be written separately for each platform. These small differences add up, and resulted in quite a jarring development experience.

The main piece of advise I would give to anyone looking to build a cross platform React Native app would be to test on both platforms early and often. It’s no use building your app 100% for iOS, and hoping that it will work for Android (because it won’t). At the very least, set up CI for both platforms. Make sure you can build for both iOS and Android, because it will save you headaches (and a lot of coffee) further down the line.

Conclusion

React Native is a brilliant tool for JavaScript developers to get straight in to mobile development. The ecosystem is constantly evolving, and adoption is ever-growing. With that, the tools and services around building production apps are also becoming more mature. With a bit of time up-front spent setting up a CI pipeline, for both Android and iOS, you can be sure to be on the road to success when building your own cross platform app.

In future posts, I’ll discuss some of the other questions I asked myself when building the app. If you’re interested in getting stuck in with cutting-edge technology like React Native, then join us! We’re hiring!.