React Native — We’re Really Doing This

Max Metral
The Startup
Published in
8 min readOct 16, 2020

It’s been a bit of a whiplash week if not month. As you may have heard GasBuddy was entertaining the idea of rewriting our app in React Native. Since the end of our React Native Week, I think I’ve personally been back and forth on whether to proceed at least twice. At the end of the week, I sent around an email asking for individual responses to the following three questions:

  1. If you were writing the GasBuddy app from scratch today, would you use React Native?
  2. Should we rewrite the GasBuddy app in React Native now?
  3. If we were to rewrite the app, what aspects of the process seem most important? For example, what mix of internal resources vs. external React Native experts? What general order of building features?

I felt that getting individual responses first would reduce the likelihood of groupthink and people feeling like they couldn’t express their full or most blunt opinions. I’ve heard over the years that I can be intimidating. I swear it’s not by design, but I am absolutely an argumentative discoverer. I do believe in the general approach embodied by “passionate beliefs, loosely held.” I try very hard to make sure that doesn’t really mean bombastic certainty that shuts down discussion which is absolutely a suboptimal outcome for any organization. Any of these cliches — Crossing the Chasm, Minimum Viable Products, Agile, 10x engineers, Microservices, and etc. — when applied blindly usually leads to an outcome similar to applying the opposite principles blindly.

I didn’t get universal participation in those questions, but we got a good number of opinions (we’re a small team of about 25 engineers, and even less of us mobile or full stack engineers). Most of the participants in the week were native mobile engineers, namely Swift and Kotlin practitioners of widely varied tenure here at GasBuddy. We had a few full stack or primarily service layer engineers as well. Unsurprisingly, mobile engineers were more likely to be in favor of doing things the way we were currently doing them.

I did not do a good job setting expectations at the beginning of the week. If you’ve come from a typed, compiled language like Swift or Kotlin to Javascript, it can be incredibly jarring. I came to Javascript from C#. C# is hands down the best “mainstream” programming language ever designed (see, there go those PassionateBeliefsLooselyHeld). Generics, the compiler embedded in the runtime, the quality of intellisense, async/await — it’s a beautiful thing. And the tools — OMG I can step from the JS in the browser to the C# in the application server and supporting libraries, to the SQL in the database and back out. I can roll back time, directly set variables, edit code and resume… I AM THOR! What do we have in Javascript? A single thread. console.log. Meaningless stack traces that are two frames deep with a timer event at the top. Mismatched line numbers from all the transpilation going on and the fact that it’s nearly impossible to configure the transpiler properly for all cases. I can’t defend the superiority of any of these things because they are inferior and frustrating.

…But somehow it works. The speed at which you can change things, the certainty that whatever you’re trying to do, someone has done something similar before and it’s probably a node module, the depth of the available tooling are all just hard to beat in other languages. I went back to C# a year ago to transform massive volumes of data for some machine learning experimentation, and the package ecosystem is a complete and total mess. In most cases, it was easier for me to crib some code rather than include a package from NuGet. They were either too big, not for my version (which was .Net Core) or abandoned. Abandoned modules happen in JS too obviously, but the code you need to copy is right there in the open, and probably still runs just fine in modern Node. The simplicity of going into node_modules and just sprinkling some logs in someone else’s code is powerful and easy to learn (all you have to do is realize there is basically no code you can’t change in your JS stack).

Since I didn’t properly explain all this, I think people came in expecting to be productive on day 1 and everything would just “work” during setup and runtime. By this time we already had a complex RN app setup with over 20,000 lines of code built by experienced RN and JS engineers (3 of us). The point of the word “experienced” there is not to flatter us, but to make it clear we had dozens of assumptions borne from years of pain. Our mobile apps have had years to get to a workable README.md that can describe in 5 steps or less how to get a working build. They also have dozens of buried assumptions (God help you if you’re on the wrong version of XCode or Ruby or CocoaPods). We spent a good amount of day 1 finding these assumptions and trying to correct them where necessary.

For example we have a partner that has a private Artifactory repo. I wrote a setup script to try and deal with this (because it’s a damn pain), but it generally assumed you had nothing setup yet. The existing mobile engineers had “half of it” setup, and my script said “you’re all good” when you really weren’t. I sent around two great tutorials (Mac React Native Setup and Windows 10 React Native Setup) from Jamon at Infinite Red, but let’s be honest, I think some developers said TL;DW. That’s a one-time tax and one that will decline over time as we make the project better, but the answers to my questions suggested many interpreted it as a failure of the ecosystem.

We made github issues for dozens of tasks we felt would be good starter issues — fixing dark mode on some screens, adding images, building mostly static screens or components, adding Storybook stories… “simple stuff.” If you are brand new to Javascript or Typescript, brand new to React Native, brand new to Visual Studio Code and in some cases (gasp) brand new to CLI-focused tools, these simple tasks have a number of buried learnings in them. This is a good thing of course, it’s the point of the week; but if you take a day to add a style to a screen, it can seem like you will never be truly productive. The problem there is more about unreasonable expectations than it is about the developer or the infrastructure.

As the responses came in, I felt a bit deflated and fairly sure we were going to kill the project. The answer to the first two questions (build from scratch, rebuild now) was clearly “no” from a vote count perspective. In addition to all the reasons I’ve described above, there was reasonable concern about how an organization of our size could possibly make a transition like this AND get anything else done, whether the various native libraries we use could be integrated, whether the engineer in question really wants to make this move, and whether React Native really would ever work on a Samsung J3 Emerge from 2017. Let’s be clear, this project is going to cost hundreds of thousands of dollars and take months — probably 6. In those months, we will HAVE to slow down progress drastically on our mobile teams, and meaningfully slow down other engineering activity in order to confidently “flip a switch” and replace our native apps with a React Native app when it’s done. It would be so easy to just say “never mind” and go on building features twice until GasBuddy succeeds or fails or until the heat death of the universe, whichever comes first. I wouldn’t get fired for making that choice, but I might get fired for leading us down a dark alley that takes 9 months instead of 6, does not ever ship, or ships and is rife with bugs or poor performance.

Additionally, while React Native Week was an audition for React Native, it was also an audition for our teams. The third question — how would we do this — was really focused on this question of internal vs external resources. I have no doubt that our mobile developers will become proficient React Native developers. It will not be without pain or without meaningful investment from each of them to learn something new and uncomfortable. However, in a vacuum, having an external React Native team rebuild the GasBuddy app from scratch with support from the existing teams (mainly in terms of describing and documenting behavior, providing designs, etc) would be a significantly faster and likely more cost effective approach. While I think we will have to reduce the volume of work per sprint on the existing apps, it won’t be zero. So it would be easy to just load up the tasks on the external team and ignore the whole thing for 2–3 months, and then add internal resources to get us over the finish line. That would mean the existing team misses the formative stages of the app and architecture even more than they already have, and that they aren’t along for the learning-ride that I have gone through by working with experienced React Native developers. So we clearly are not in as healthy a place as we would be if we were building an app from scratch together with no other demands on our time.

We have settled on a hybrid approach — in the first month or so we will have no expectations of the existing team to contribute production-ready code to the RN app. We will use that time to learn and to support the Infinite Red team (and me) in researching/documenting/explaining the existing app features so they can be rebuilt. We will dedicate meaningful sprint capacity (at least 50%) to reserving time for learning and answering questions. If some developers are ready to go into the backlog and implement in the RN app, that’s a bonus, but not an expectation. We will order our tasks such that any areas with known pending changes in the native apps come “later” in React Native development so that we don’t have to implement twice, but we acknowledge up front that when the React Native app ships, it will probably have some regressions to the existing native apps. I am most afraid of Android performance, especially on older phones. There will be a number of visual inconsistencies between the native apps and the RN app just because we are not going to chase them all down before shipping. We will strive to avoid having to “downgrade” and release a hotfix that goes back to the native version — but we acknowledge it might happen. On Android there is a robust beta test framework that can approach the numbers required to be confident about a full release, but no such thing exists on iOS. Luckily iOS seems significantly more predictable (no real surprise) and our support matrix is much smaller.

I was told my previous post ended abruptly, so I might as well keep up the habit. We are off into the wild frontier and this post should memorialize my stupidity or well-placed faith in React Native some months from now. See you in the various Discord chats for React Native, react-navigation, Typescript or yarn (yarn2 will be great)!

--

--

Max Metral
The Startup

Serial Entrepreneur. Father of 3. Currently CTO of GasBuddy.