This week, we launched our updated Tasker app to the community. This is not the app on the app store, but rather the one the Taskers use to get their work done. Functionally, not much has changed since the last release. But underneath, the app has been completely rewritten in React Native.
First and foremost, a huge congratulations needs to go out to the team, especially JR. I’ve never been on an engineering project that went as smoothly or was as fun as this one. So good!
I started looking into React Native in the beginning of August. It’s a really great story. First of all, it’s React. I’ve now decided that’s just about the best thing out there. Secondly, I was 10x more productive than when developing a regular iOS app. Finally, there was a decent chance much of the code could be reused on Android. If every feature did not have to be developed twice, we could choose to develop twice as many features or have half the engineers work on something else.
I created a prototype to see if I thought it could work. The main concerns I had we around navigation, push notifications, other native features, data storage, and just getting the right project structure. More or less, I ended up with the React Native Sample App that we published. All of those things showed great promise or at least that they were possible.
The community was also evolving rapidly. It’s super exciting to be working at the beginning of a technology that shows great promise. Each week, there would be a new thing on github that solved one of our needs. Our strategy was to put off a feature to see if the core team or community would make something available. If they did not, we went ahead and wrote it. I’m sure everyone was doing something similar. Let’s call it bootstrap chicken.
The prototype was enough to convince me and enough to get people excited about it. Towards the end of September, JR started working full-time on it. My time in greenfield projects had to come to a close. Back to real life, but I stayed involved as the Product Manager.
I can’t imagine anyone saying that I’m a very good PM. In particular, my story acceptance followup is horrendous. Fortunately, Paul helped me out. I did do a pretty good job of writing the stories and putting them in the right order.
One decision made this project work, though. It was to acknowledge that this is an engineering project, not a product one. It’s so very tempting to update the functionality of the app “while you’re at it.” But opening that door would have doubled the length of the project. Those discussions with design and others would eat up the development time. It would have made the rollout harder. We could do a soft release because it’s basically the same app. I’ve written about rewrites before, but that was to drastically change the product. If you can get away with it, do it in place and keep it the same. At least we followed one of those.
So I dragged stories around while JR worked his butt off. This is not a small app and we hit critical functional parity (with many UI tweaks needed) at the beginning of October. We put this in the hands of some Taskers and got their feedback. From there it was getting the less critical features done, getting feedback, shipping new builds, making it prettier, and fixing bugs.
By last week, we felt really good about it but needed to buckle down to get the release out. We’d been working so quickly that it was hard to slow down and be more methodical in the final run up. We felt good because Jeremy joined the team, we had great test coverage, and real Taskers in multiple countries were actually using the thing.
We put out another release to a wider audience and incorporated a few final items. Then… ship it. The reception has been neutral. Nothing good or bad. This is amazing! That means success in a technology project with no new features except all of the old ones.
I just wanted to note a few interesting things that we did or encountered.
We have been beta testing React Native integration from Realm. All of our lists (non-singletons) stores are backed by a Realm database. For example, we use this for storing tasks. The various lists and drill-down screens all use the same data. That means its very likely to be always up to date. If you’re interested in trying it out, sign up here.
Be careful about the JS runtime (iOS version). We’ve been testing in iOS 9. Right before release, we realized a library we use was using
new Symbol(). It works in 9.0+ but not in 8.x versions of the OS.
Our navigation scheme really is awesome. It makes everything easier. Check out more information here.
Internationalization was really interesting. I’ll write up more on this topic but, briefly: each component declares its own words and we have code to go through all the components and collect them up. Then we can send that off for translation.
Flux and event dispatching in general really worked out well. Just having minor piece of indirection reduces coupling and leads to great results
I think there’s a missing pattern for how to run things in the “background” in these apps. For example, maybe we’re supposed to sync something with the server every hour or so. We made something up but I haven’t seen anything else about it.
Everything that is iOS specific is in one directory right now and it’s not much. I’m really looking forward to the Android build.
- Objective C: 12 files with 1029 lines of code
- React Components: 112
- Screens (addressable url patterns): 25
- Dispatcher Events: 52
- Platform (iOS specific): 18 files with 605 lines of code
- JS / C percentage: 97%
- Shareable code percentage: 93% (so far - we’ll see with Android)
- Avg. components per screen: 4.5
Now we are going to fix up a few minor things and on to Android. How exciting!
Ok, this video is a bit of a lie because it’s the old app. But the main point was that the React app looks just like this one. So to get an idea of the functionality we’ve implemented in React Native…