Audius React Native Migration
When we first built the Audius Music mobile app, we chose to simply create a thin React Native WebView wrapper around our already existing web app. It allowed us to go to market quickly and provide a full-featured mobile experience with minimal development effort.
But over time, it became clear that the WebView-based mobile experience was not ideal for users in a few different ways.
Another benefit was that new features only needed to be implemented for one platform and would then be available across web, iOS, and Android. Also, the crypto libraries that we depended on were immature and difficult, if not impossible, to use outside of a web environment.
At the time, using a WebView was definitely the right choice.
But over time, it became clear that the WebView-based mobile experience was not ideal for users in a few different ways:
- Performance was lacking, especially for animations and transitions, which were capped at 30 frames per second
- Many native gestures were not supported
- Mobile navigation was directly tied to the web routing structure, so changing between screens often meant losing a previous navigation context
The React Native WebView approach also presented some difficulties for developers:
- For certain features, communicating with the native layer was necessary and required an asynchronous and potentially slow message passing bridge
- Running the app locally required bundling and serving the web app before running the React Native layer
🚚 Migrating to React Native
To provide users and developers with a better experience, we decided to remove the WebView and build a fully React Native mobile application.
However, we wanted to avoid the maintenance burden of two completely separate apps, so we set a goal of sharing as much code between web and mobile as possible. This presented a challenge and required careful consideration at every step.
It was not possible to reuse our web React components in React Native so rewriting at least the UI layer was required, but much of the state management and business logic could be shared.
Incremental migration
We decided to perform the migration in two phases so that we could reap some benefits early.
Phase 1 was the process of implementing the user interface in React Native while still using the web app as the state management layer (using redux and redux-sagas). This postponed having to migrate much of the complex business logic and would already achieve 60fps animations, better gesture support, and improved UI performance.
Phase 2 was the process of repurposing all the state management & business logic existing in the web app to be platform-agnostic and to run in React Native. Having platform-agnostic business logic would allow the WebView to be removed entirely and both the mobile and web apps to run on top of the same business logic.