Earlier this year, we migrated the native TenX app to React Native under the Expo platform (full details in this blog post). This migration has enabled us to focus on our product and fast-track changes:

The other key technology we used is Expo. For those not familiar, Expo is a development toolchain built around React Native. It allows you to develop and publish a React Native project with remarkable ease and speed.

Relying on Expo was one of the key decisions which allowed us to move as quickly as we did. This can be challenging because Expo limits you to only those APIs they provide (you cannot link native code directly), but for the productivity tradeoff, this can be worth it. In our case, we have so far managed to avoid ejecting from the core Expo SDK which has helped us maintain a fast iteration speed as we move forward.

After running on the Expo platform for the past year, we’ve since learned that we needed to have more flexibility and reliability in building our product. One of the biggest downsides of using Expo is that we do not have any control over the native code.

For an early-stage team, this was good because then we could really focus on building and shipping our product. However, as both our product and user base have grown, we now believe that it is time for us to prioritize higher flexibility and reliability in our app.

3 main components to address for Expo ejection

Initially, we would have liked to not eject from Expo completely: this would have meant that we continued to have some dependencies with Expo but would still be able to add and change native code. This was possible using ExpoKit.

However, after some digging in other blogs and looking up GitHub issues, we found out that ExpoKit was being deprecated. With that, we decided to migrate into the bare workflow and completely eject from Expo.

These are the 3 components we needed to address to eject from Expo:

  1. App signing
  2. Over-the-air (OTA) updates
  3. Push notifications

App signing

With Expo, we had the ability to allow any engineer in our company to generate a signed binary file without having to configure each of their computers manually. This allowed us to ship things fast and no single point of failure at any time.

In order to keep this ability after moving away from Expo, we decided to use App Center from Microsoft. Not only does App Center allow us to build the signed binary file at any time, it also supports multiple build configurations across different Github branches.

This empowers us to build the signed binary file with different configurations and environment variables easily, all with just one click.

OTA updates

OTA updates have allowed us to ship updates and fix things nimbly. This was our biggest concern in moving away from Expo — we needed to continue having OTA updates in our app.

It turns out that there is built-in support for OTA updates in the App Center using CodePush! CodePush provides a similar service to Expo’s OTA updates, plus some additional supports such as custom percentage update distribution and rollback retry option. In addition, we are able to configure how and when the updates should be applied so that it will not intercept the user’s interaction. So kudos to App Center! 🎉

Push notifications

Push notifications have enabled us to update the app in real-time whenever a transaction happens. We believe that this feature can be enhanced to improve user interaction and increase retention.

On Expo, all the configurations and integrations for enabling push notifications are done automatically. In order to keep push notifications post Expo ejection, we decided to use Firebase, which was integrated into our backend using an additional React Native library.

Challenges in the migration process

Ejecting from Expo exposed User Interface (UI) issues in our app, for example:

  • Miscalculated margins that previously worked fine in Expo but result in weird layout behaviours with the bare React Native workflow
  • Keyboard layout adjustments that previously needed manual handling but can now be done automatically.

Overall, no major UI bugs were found when we first ran our ejected version.

That aside, stitching up all the tools was the hardest part of this migration process. One of the biggest challenges in integrating with the App Center was setting up the correct schema within the project with different environment variables and correct signing keys.

OTA updates with CodePush also brought new challenges to user experience. We needed to make sure everything was done automatically so as to avoid human error, and we did this by creating an interactive script instead of calling the CLI manually.

Finally, we had some difficulties with outdated third party documentation, but kudos to our team who never gave up trying to figure this out!

Learnings from replatforming the TenX Wallet app

We managed to run our ejected app in development mode earlier than we expected! This was possible because Expo has been moving towards the universal module concept, where modules are broken down into smaller independent packages that we can install (or uninstall) according to our needs.

This allowed us to keep most of our code that has Expo dependencies, which definitely saved a significant amount of time. We were also able to slim down our app to 43% smaller in download size for the Android platform. We are thankful for the Expo team who has been working on this movement.

The development cycle has now become a bit more complex. Migrating from Expo has exposed us to native dependencies and the knowledge of how to manage them using other tools, such as CocoaPods for iOS.

Ejecting from Expo also means we now need to manage our library update by ourselves. Thankfully, because of our awesome React community, tools like React Native Upgrade Helper have been created to help people like us to update our React Native applications smoothly.

We can now do things that we couldn’t before, such as tighter tool integrations involving native code. This exposes us to new learning opportunities for developing our app natively.

The TenX Wallet app version 3.15.0 is now up in the Google Play and App Store (the app will automatically be upgraded to 3.15.4 through an OTA update).

All in all, we’ve gained tremendously from this process and are excited to see what we can build with this new platform.