React Native and CodePush
Tags: reactnative, tutorial, react
Published: 2023-02-23 10:48:16

>
CodePush is an App Center cloud service that enables React Native developers to deploy mobile app updates directly to their users’ devices. It works by acting as a central repository that developers can publish certain updates to (for example, JS, HTML, CSS and image changes), and apps can query for updates from (using the provided client SDKs). This allows you to have a more deterministic and direct engagement model with your end users while addressing bugs, adding small features that don’t require you to rebuild a binary, or redistributing it through any public app stores
> 

That's how Microsoft described CodePush in their documentation. CodePush is not a new equivalent of TestFlight or Firebase Distribution. It’s a tool for delivering your builds to the end user not just beta delivery tool. In easy words, CodePush is an instrument that gives us the ability to replace JS bundle OTA and avoid the bottleneck of releasing via App Store and Play market. With CodePush you can achieve more web-like release behavior for mobile apps.
Why did I come up with this tool? We needed to make targeted releases and reduce the time of receiving updates. So we gave it a try because we were already users of AppCenter for managing beta releases.

CodePush is located inside AppCenter Dashboard.
![CodePush](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fweq91nfz57ul6ugozwz.png)

There’re you can manage your builds.
![Build](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zy90fd070z2p8o9mrj5x.png)

And configure your deployment keys.
![Deployment keys](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ebu95b1iqjwnyfm6e972.png)

## First steps

I don't want to waste a lot of time on detailed instructions for setting up CodePush SDK, so we have [documentation](https://learn.microsoft.com/en-us/appcenter/distribution/codepush/rn-get-started) with all steps. So let's move on more interesting things.

Firstly, we need to specify the strategy for updating rollout targets and how we will force users to get these updates.

By rollout targets we mean that we can decide who and how can get our updates, and we can get there using deployment keys

### Rollout targets

CodePush gives us a flexible tool for targeting.
By default, we have 2 deployment keys, one for Production, and the other for staging. It's the easiest option.

![Default deployment keys](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/an0zyectx9vc5g3ozbhq.png)

But we can build a fully custom system over these keys. You can create the deployment key for each situation that you need.
Example:
In your app, you have 3 types of users: admins, managers, and customers. With admins and managers, you have a direct channel of communication. So you're creating 3 keys:

![admins, managers, and customers keys](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/om6lfg2snuleaidtkr7w.png)

Save it in locally or put into your DB, CMS etc. Voilà! Now you can start collecting feedback if everything is okay with your app without touching the most fragile group of users.

How it will look in your app? Easy!

You just need to provide the key that you saved for user to codePush library using `sync` method


![Usage example](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9r3vadxpsy9hkfj22ozl.png)



### Getting updates

Ok, we decided how we will send updates to users, but the next question how do they get it ?

Initially you will have similar a config in your entry file

![default config](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kz4rbw4t5acn71iay5ar.png)

Here we also have interesting things to play with.
We have 2 parameters that we can use to achieve the result: **checkFrequency** and **installMode**.

#### Default values

```json
{
  checkFrequency: codePush.CheckFrequency.ON_APP_START,
  installMode: codePush.InstallMode.ON_NEXT_RESTART,
}
```
According to docs: 

> Your app will automatically download available updates, and apply them the next time the app restarts (like the OS or end user killed it, or the device was restarted). This way, the entire update experience is “silent” to the end user, since they don’t see any update prompt and/or “synthetic” app restarts.
>
The main problem with this strategy is that the user may not close the application, and you can't predict when they will get your updates.

#### Background updates

```json
{
  checkFrequency: codePush.CheckFrequency.ON_APP_RESUME,
  installMode: codePush.InstallMode.ON_NEXT_RESUME,
  minimumBackgroundDuration: 30*60 // 30 minutes
}
```
Here with `minimumBackgroundDuration` parameter we specify how long the application will wait until it will be considered as restarted. So we avoid the case when users don't close their apps for years. But we are still not sure that users have the latest versions. Because they need to put their app in the background for the time specified in the `minimumBackgroundDuration` parameter.

##### Immediate updates

```json
{
  checkFrequency: codePush.CheckFrequency.ON_APP_RESUME,
  installMode: codePush.InstallMode.IMMEDIATE,
}
```

The main difference is that each time when the app is resumed it will be updated. The concern is that it could look clunky because the application will restart on the user's eyes.

##### Manual

```json
{
  checkFrequency: codePush.CheckFrequency.MANUAL,
}
```

Last but not least is manual updates, here we can trigger updates programmatically when and how we want. We just need to trigger `codePush.sync` method. 

Example with updateDialog and production/staging keys:


![Mannual example](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/adjn71fjtqy5x6cnyh2a.png)

## Let’s see how it works!

For example, I’ll choose Manual updates

```typescript
const codePushOptions = {
  checkFrequency: codePush.CheckFrequency.MANUAL,
};

const AppWithCodePush = codePush(codePushOptions)(App);

AppRegistry.registerComponent('CodePushPoc', () => AppWithCodePush);
```
And our app will be look like

![App example](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o9qmmg5fjcoxafxnts3j.png)

Using a switcher we will choose our environment.
Then we need to push our first bundle to the CodePush using the AppCenter CLI

```bash
appcenter codepush release-react -a YOUR_ORG_NAME/YOR_APP_NAME -d Prod
```
And you’ll get your build online:

![CodePush with build](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wwdur8x136u9i7rpo3tn.png)

### Let’s change something

We can modify our code somehow and push it to the stage environment.
I’ll create a new branch with the name `feature/new-bg-color` and let’s change `backgroundColor` to `#6b5b95` and push it to the Stage environment

```bash
appcenter codepush release-react -a YOUR_ORG_NAME/YOR_APP_NAME -d Stage
```

We will be able to see this:

![Uploading stage version GIF](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mhtv0ruk6llyhva49o76.gif)


## Last words…

CodePush is a great tool that helps you to improve and speed up your releases but it requires you to be more focused cause the chance of mistakes increases too. You can check the example app in the [repo](https://github.com/Thegrep01/code-push-example/tree/main) (_note it is configured only for Android_).