Building an Editor by Sharing Code Between Android, iOS, and Web with React Native

When WordPress began rolling out the powerful new Gutenberg editor for building web pages (and, soon, entire websites), we were excited to bring that power to our users on mobile. 

Why React Native

We know firsthand how hard it is to make a great editor. We have built native editors for Android and iOS before (and before). In addition, it was going to be extremely difficult to keep up with the work on the web version of the editor: the web editor had a substantial head start, and there is a larger community of developers contributing to Gutenberg on the web. 

Gutenberg on the web is built with React, so we saw React Native as a way for mobile to leverage all of the work being done to create a great editor on the web.

Not only would reusing code from the web allow us to move faster, but it would also help us keep pace with the web because we would get any web updates “for free” (or at least that was our hope). In addition, we wouldn’t have to write two mobile editors from scratch: one for iOS and one for Android. Instead, we would write one editor in React Native!

Reusing Code From the Web

Mobile has very different design constraints and conventions compared to the web, so one of the first challenges we discovered was that we could not easily reuse a lot of the UI components from the web: we had to either do complex refactorings or reimplement the components for mobile. 

So far, we have most often reimplemented the UI components for mobile instead of refactoring the web components. This allows us to avoid complicated refactorings while also giving us the freedom to make the best mobile-specific experience possible. Although having a pre-existing web component to use as a starting point made writing these mobile-specific components much easier, it did fall short of true code reuse.

We were much more successful in sharing business logic. At times, it’s been almost magical. An early example of this was adding undo/redo, which was already implemented on the web. We only needed to hook into that web capability on the mobile side and undo/redo “just worked”.

We love how we get bug fixes and feature improvements “for free” when we pull in the latest code from the web. This saves time and, more importantly, ensures that the user experience is consistent across all platforms. Of course, it’s not always good news–sometimes we get new bugs from web too.

Collaboration Between the Mobile and Web Teams

Another benefit of reusing the web code is that it has brought the web and mobile teams closer. Before this, the mobile and web teams only really interacted when discussing APIs. Now we’re discussing everything from design to architecture.

Working Across Multiple Platforms is Hard

No One Is An Expert On Every Platform

Using React Native means working on three very different platforms: iOS, Android, and the Web. That’s even ignoring React Native itself, which could arguably be considered the fourth platform. Very few of our developers are an expert on all three platforms—most tend to be an expert in one platform, proficient in another, and closer to a junior developer on the third platform.

This means that working on a mobile feature that spans all three platforms usually requires at least two developers with complementary skill sets. As mobile developers, we signed up for this when we decided to adopt React Native. The web team, though, is in a more difficult position because they started working on a web project, then we showed up, and all of a sudden they discovered they were working on a project that spans three platforms.

Web developers on Gutenberg have been enthusiastic about supporting mobile, but it’s a significant challenge for them to make sure that their changes don’t break any of the platforms. Likewise, mobile devs need to run and test Gutenberg on the web to make sure that their changes do not break that. Of course, that is what CI is for…

Continuous Integration

Maintaining a CI setup that builds and tests a single codebase on three very different platforms is difficult—particularly when one of those platforms is iOS, which can only be tested on Apple hardware. Even once you get all three platforms working, CI across three platforms has three times as many ways to break and is much slower. 

In addition, any flakiness on CI becomes a much larger problem. As an initial matter, there are just more opportunities for flakiness to appear on a multiplatform project. If a CI check fails and the error is on a platform the PR author is not confident with, they need to find another developer to help them resolve the issue.

To ensure that the tests CI is running on PRs are both speedy and reliable, we’ve been running a relatively small set of tests. Of course, this means that CI misses more breaking changes.

Are We Happy We Chose React Native?

The short answer is yes, we are very happy. We’ve experienced several pain points, but it is hard to overstate the benefit we have gotten from being able to reuse code from the web on both iOS and Android.

Would you like to contribute?

Gutenberg Mobile is a part of Gutenberg, an open-source project. You can check it out here: https://github.com/WordPress/gutenberg, and you can find most of the team involved in developing it on the #mobile channel on Making WordPress Slack.

Join the Conversation

8 Comments

Leave a comment

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: