Skip to content

Instantly share code, notes, and snippets.

@bvaughn
Last active April 7, 2018 14:51
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bvaughn/91583b158a207c72d63954452101b5d6 to your computer and use it in GitHub Desktop.
Save bvaughn/91583b158a207c72d63954452101b5d6 to your computer and use it in GitHub Desktop.
Overview of the current React / ReactNative sync and release process

I've gotten a couple of questions about how the RN sync process works, so I thought I'd write up a high level overview of the current process and some of its challenges.

Sources of truth

As far as JavaScript goes, there are a couple of things that live outside of the React Native GitHub repository that get auto-synced in:

  • React (core)
  • ReactNative renderer
  • Other things (e.g. component types like View, Text, the Animated library, StyleSheet, etc.)

The source of truth for React core is GitHub (https://github.com/facebook/react). It gets published to NPM and React Native depends on it via an NPM dependency. e.g. the most recently release of RN (55) depends on React core 16.3.1

The source of truth for the React Native renderer is also GitHub (https://github.com/facebook/react). It's developed (and lightly tested) in the React repo and then manually synced to Facebook's internal repo (often referred to as "fbsource") where it is tested much more extensively via a suite of unit and integration tests. Then an automated process syncs it from Facebook to React Native's GitHub repo.

The source of truth for all other things is Facebook (aka fbsource). Development and testing is done internally, and then once changes are merged to master, they get picked up by the automated process that copies them out to React Native's GitHub repo.

Release challenges

The two most recent RN releases (54 and 55) have accidentally included some deprecation warnings that are intended for React 16.4 but were already turned on within the React Native renderer. This is, understandably, surprising and confusing to people. These warnings are enabled via feature flags- so why are those flags being turned on prematurely in the React Native GitHub repo?

The answer for this boils down a mix of the React Native release cycle and how Facebook tests React releases.

Feature flags

First, let's look at how Facebook tests releases. The React team syncs from our GitHub repo to Facebook's internal repo on a regular basis (at least once a week). We have a lot of tests in our git repo, but there are way more inside of Facebook- so regularly syncs give us a much higher confidence that React is working as intended.

Typically, we put new features behind feature flags so that we can develop them (and write tests for them) without them leaking into open source releases. We enable these feature flags interally before we are ready to release to open source because it gives us a chance to test them, gather feedback from a smaller audience (of Facebook engineers), and make changes to the API without a breaking release or causing churn in the open source ecosystem. To manage this, we store feature flags in a single module and fork that module for different builds- so we can turn a feature on within Facebook and leave it off for the NPM releases.

At least, that's how it works for packages like react and react-dom. The React Native renderer sync process (React GitHub -> Facebook fbsource -> React Native GitHub) presents a challenge, because there's only a single feature flag file. This means that when we turn a flag on for internal testing within Facebook- it will eventually be picked up by the automatic sync script and make its way into the React Native repo (and the next release branch that's cut).

Release cycle

Releases are managed differently between React Native and other packages (like react and react-dom). React releases are a manual process. We publish a release (to NPM) when we think we have an appropriate set of features (or bug fixes) to justify one- and only after we've synced code locally and ensured that it didn't break any Facebook products or tests.

React Native releases, on the other hand, are done on a predetermined schedule. They're still covered by (internal and external) automated tests, but the key deciding factor of when to cut a release is a date rather than a feature set. This, combined with the current feature flag limitation I mentioned above, is why the recent releases accidentally enabled a deprecation warning before we intended it to be enabled publicly.

This has also lead to React Native releases that depend on pre-release versions of React. e.g. React Native 48 depended on React 16 alpha 12. This could cause problems- if React Native renderer has a dependency on a React (core) feature that hasn't yet been released to NPM- but in practice it's usually pretty safe because the React core package doesn't change often.

@ujwal-setlur
Copy link

OK, where is this feature flag file for react-native so that we can do some postinstall tweaking to turn off flags that were turned on accidentally?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment