DEV Community

Cover image for New to Bitrise CodePush? Here's What I Wish I Knew Before Setting It Up
Kudzai Murimi
Kudzai Murimi Subscriber

Posted on

New to Bitrise CodePush? Here's What I Wish I Knew Before Setting It Up

New to Bitrise CodePush? Here's What I Wish I Knew Before Setting It Up

If you've never used CodePush before, the idea sounds almost too convenient.

You find a bug in a React Native app, fix the JavaScript, and instead of waiting for another App Store or Google Play release, you can push the update directly to users.

That's the part that got my attention.

But once I actually started setting it up, I realized there are quite a few things that aren't obvious from that one-line explanation.

So if you're new to Bitrise CodePush, here's what I learned while going through the setup.

First: What Does CodePush Actually Update?

The easiest way to think about CodePush is:

It updates the JavaScript and assets in your React Native app without requiring a new store release.

So if you've fixed:

  • A JavaScript bug
  • Some text or copy
  • A small UI issue
  • Another change that doesn't require native code

You can potentially deliver that fix without submitting a new binary to the App Store or Google Play.

But there's an important boundary.

If you change native code, CodePush doesn't magically bypass the app stores.

You'll still need a normal app release.

That's probably the first thing I'd make sure the team understands before using it.

What Bitrise Actually Gives You

There are two main parts to the setup.

1. CodePush inside Bitrise Release Management

This is where you manage deployments, upload releases, and control things like rollout percentages.

2. The SDK inside your application

@bitrise/code-push-sdk
Enter fullscreen mode Exit fullscreen mode

The SDK is responsible for checking whether an update is available and applying it.

So the basic idea is:

Bitrise handles the release side → your app handles the update side.

Once I understood that split, the rest of the setup made a lot more sense.

Before You Touch the Code

You'll need a Bitrise account and a Release Management app.

One thing that caught my attention here is that Release Management and your normal Bitrise CI app aren't necessarily the same thing.

If you're already using Bitrise CI to build your React Native app, Release Management is something you add alongside it.

And if you're releasing for both iOS and Android, you'll need to account for both platforms in your setup.

I'd recommend getting the basic Release Management setup working before touching the React Native project.

It makes troubleshooting much easier.

Step 1: Create a Deployment

Inside the Release Management app, go to:

Configuration → Deployments → New deployment

For a real project, I'd probably start with:

  • Staging
  • Production

That separation is useful.

You don't want to be testing an update and accidentally send it to everyone using the production app.

You can either provide an existing deployment key or let Bitrise generate one.

One thing about deployment keys

This initially confused me.

The deployment key looks like something you'd normally hide in a secret.

But it isn't really a password.

The key eventually gets included in the application, which means someone with access to the built app could potentially extract it.

It's better to think of it as an identifier for the deployment rather than a secret credential.

Your API token is the thing you actually need to protect.

Step 2: Install the SDK

The first command is simple:

npm install @bitrise/code-push-sdk

After that, things depend on how your React Native app was created.

And this is one place where I wouldn't recommend blindly copying configuration from a random tutorial.

Expo and bare React Native aren't configured in exactly the same way.

If You're Using Expo

With Expo, you add the CodePush plugin to your app.json.

You'll need your deployment key and the CodePush server URL.

The URL follows this pattern:

https://.codepush.bitrise.io

Then run:

npx expo prebuild

I like doing this step because it lets you check whether the configuration actually made its way into the generated native project.

If You're Using Bare React Native

This takes a little more work.

On iOS, you'll need to make a change in AppDelegate.swift so CodePush can resolve the active release bundle instead of always using the default bundled JavaScript.

You'll also configure the deployment key and server URL in Info.plist.

On Android, the configuration goes into strings.xml, along with some Gradle configuration and a change to how MainApplication.kt resolves the JavaScript bundle.

None of these changes are particularly complicated.

They're just easy places to make a small mistake.

That's why I found it better to follow the Bitrise documentation closely rather than trying to recreate the setup from memory.

Step 3: Think About the User Experience

This was probably the part I didn't think about enough at first.

It's easy to look at CodePush as:

"There's an update, download it."

But you actually have choices about how that update reaches the user.

For example, with:

codePush.sync()

you can use different behaviours.

Silent update

The update downloads in the background and is applied when the app restarts.

For the user, the whole thing can be almost invisible.

Update when the app resumes

Instead of checking only when the app starts, the app can check when it comes back into the foreground.

Interactive update

The user gets feedback that an update is available and can be shown the download process.

For mandatory updates, you can also prevent the user from simply dismissing them.

You can even use progress callbacks if you want to show download progress.

I think this is worth deciding before you ship your first update.

The technically easiest option isn't necessarily the best experience for your users.

Step 4: Build and Release

Once the application is configured, you need to create the JavaScript bundle.

For a bare React Native project:

npx react-native bundle \
--platform ios \
--dev false \
--entry-file index.js \
--bundle-output ./build/main.jsbundle \
--assets-dest ./build

For Expo:

expo export:embed

You then package the generated files and upload them to Release Management.

You can do this manually from the dashboard, which is probably the easiest way to test your first release.

Once you've confirmed everything works, that's when I'd start thinking about automation.

Don't Immediately Send It to Everyone

This is one feature I'd definitely use in production.

When you create the release, you can control the rollout.

You can target specific app versions and use version ranges such as:

1.2.x

or:

=1.2.3 <1.2.7

You can also mark an update as mandatory and control the percentage of users who receive it.

That last part is important.

Imagine you've made a JavaScript change that you think is completely safe.

Instead of immediately sending it to 100% of your users, you can start with a smaller percentage.

If everything looks good, increase the rollout.

That gives you a little more room to catch problems before they become everyone's problem.

What About Automation?

Once you've manually released a couple of updates, you'll probably notice the repetitive part:

Build the bundle.
Zip it.
Upload it.
Do it again for the other platform.

It works.

But I wouldn't want to do that every week.

That's where Bitrise CI comes in.

You can automate the build and upload process so that a workflow handles it for you.

One approach I like is connecting the release to an approved and labelled pull request rather than automatically releasing every merge.

That gives you a deliberate point where someone says:

"This is ready to ship."

The CI system then takes care of the repetitive work.

I wrote separately about that automation process because there are a few more details around credentials, versioning, and workflow configuration.

My Checklist Before the First Release

If I were setting this up on another project, this is the checklist I'd keep nearby:

Bitrise Release Management is configured

iOS and Android are accounted for

Staging and Production deployments are created

@bitrise/code-push-sdk is installed

Expo or native React Native configuration is complete

The app can successfully check for updates

The sync behaviour has been chosen

The first release is tested with a small rollout

Production releases have an automation plan

So, Is CodePush Worth It?

I think it makes the most sense when you regularly have small JavaScript-level fixes that don't justify going through another full app-store release.

It's not a replacement for your normal mobile release pipeline.

Native changes still need a normal build and store submission.

But if your team has ever had to submit a new mobile build because of something that could have been fixed entirely in JavaScript, that's the gap CodePush is trying to close.

For me, the biggest takeaway wasn't just:

"I can push an update without the App Store."

It was realizing that there are several decisions around how that update gets delivered, who receives it, and what the user experiences when it arrives.

That's the part I'd pay attention to before putting CodePush into a production app.

Have You Used CodePush?

Have you used CodePush or another OTA update solution with React Native?

I'd love to hear how you handled it, especially if you ran into problems during setup.

What would you add to this checklist?

Top comments (1)

Collapse
 
respect17 profile image
Kudzai Murimi

You need to get started with Bitrise?
Feel free to visit bitrise.io/