Expo has done a lot in terms of usage of the two simulators and it is much easier now to run on both platforms however when it comes to deployment the pain has prevailed. There are many small issues that cause subtle problems along the way.
There are many third party platforms that aim to provide some haven from the ever-changing apis of the two platforms. Maintaining a true CI/CD pipeline for your apps can prove extremely challenging as the dependency management especially on upgrades is a big hassle.
Third party publishing platforms:
Expo is a pretty good publishing platform that has a freemium model
.apk, .ipa)Code Magic is quite good if you want to make the publishing even smoother, but the price point is higher. However I would recommend it for one offs and when you are in a rush to get an app out. It can give you the breathing room to allow for building a proper pipeline.
Publishing the app to their respective stores requires accounts on both Google Play and App Store. In order to publish to the App store the membership cost is $99/year so it isn’t worth keeping one if you aren’t don’t have a healthy pipeline of published apps. The pricing for the play store is a one time flat fee of $25.
I prefer the playstore for a few reasons, it’s a bit cheaper so it has a lower barrier for experimentation and also the code is a bit more familiar since it is JVM based and also I prefer the google model to the apple model.
The publication to the Play Store and to the App Store is a matter of logging into the account of your organisation and
uploading the built .apk or .ipa. Unfortunately at this time there still isn’t a fully automatic way to do this
other than using a specialized third party service. If tasked with publishing the app our suggestion is to build the
app and upload it to the production environment account.
On both Apple and Google Play you need to create specific types of accounts with special permissions and link with other parts of your accounts' identity.
For our purposes we will have two production level apps. One that can be downloaded internally for testing and one that is generally available. For the GA side of things it would mean that you require developer accounts for both platforms so we will focus on the staging deployment instead. It will allow for online installation but it will not be accessible from the appstores.
Building and distributing apps via Expo
Distributing apps via Expo has the only downside that it doesn’t make use of the resective appstore discoverability,
other than that the built .ipa and .apk is essentially the same.
We need to have an expo account so let’s create one here. Once we signed up we can publish our app changes to expo and have anyone that has Expo installed be able to check our app out.
In order to publish to expo:
npx expo publish
This way of publishing is not enough for the stores but it is enough for testing the app features, however if you eject from the managed expo flow this will no longer be an option.
In order to build a binary complete version of our app that can be distributed to the app stores we should run this command and we should see output similar to this. Essentially what it’s telling us is that we reserved a spot in the queue and as soon as an execution timeshare is available our package build will be attempted.
npx expo build:android
✔ Choose the build type you would like: › apk
Checking if there is a build in progress...
Accessing credentials for arturdas in project coffeebrew
✔ Would you like to upload a Keystore or have us generate one for you?
If you don't know what this means, let us generate it! :) › Generate new keystore
Keystore updated successfully
- Expo SDK: 39.0.0
- Release channel: default
- Workflow: Managed
Building optimized bundles and generating sourcemaps...
Starting Metro Bundler.
Building iOS bundle
Building Android bundle
Finished building JavaScript bundle in 18573ms.
Building source maps
Finished building JavaScript bundle in 12906ms.
Finished building JavaScript bundle in 336ms.
Finished building JavaScript bundle in 148ms.
Building asset maps
Finished building JavaScript bundle in 1424ms.
Finished building JavaScript bundle in 1460ms.
Bundle Size
┌ index.ios.js 1.82 MB
├ index.android.js 1.83 MB
├ index.ios.js.map 6.41 MB
└ index.android.js.map 6.43 MB
Learn more about JavaScript bundle sizes
Analyzing assets
Saving assets
No assets changed, skipped.
Processing asset bundle patterns:
- /Users/zero/projects/ws-react-native/coffeebrew/**/*
Uploading JavaScript bundles
Publish complete
📝 Manifest: https://exp.host/@arturdas/coffeebrew Learn more.
⚙️ Project page: https://expo.io/@arturdas/coffeebrew Learn more.
Checking if this build already exists...
Build started, it may take a few minutes to complete.
You can check the queue length at https://expo.io/turtle-status
You can make this faster. 🐢
Get priority builds at: https://expo.io/settings/billing
You can monitor the build at
https://expo.io/accounts/arturdas/builds/1aa07974-5784-47ab-a325-e60b927653aa
Waiting for build to complete.
You can press Ctrl+C to exit. It won't cancel the build, you'll be able to monitor it at the printed URL.
⠧ Build queued...
If you try to build the binary before you use turtle-cli it won’t work as you need to define an expo project page
before running the build.
We can see that the build would take very long in this case since we are on the free tier. Let’s try to speed things up.
We can build the .apk and .ipa locally using the same utils that expo runs under the hood. The tool is called
turtle-cli. We can use it to create the binary builds locally and so it will circumvent the build queue on expo.
npm i -D turtle-cli
Now we have the tools required for building the assets we need to publish each app to their respective appstores. We will be working mostly with the android version as the iOS version requires an Apple Developer Account and you need to pass in the password and username for it.
EXPO_USERNAME=<expo-username> EXPO_PASSWORD=<expo-password> npx turtle build:android -m debug -t apk
Once this completes you will be able to see the path to the built .apk
${HOME}/expo-apps/@<username>__<app-name>-<signature>-signed.apk
Apple has a different flow for issuing certificates. If you are familiar with iOS then you must be aware of the code signing requirements that have been enforced by iOS and OSX.
On google play the way to sign it is a bit easier and it involves a few steps but there is much less red tape around the process.
Expo should be able to take care of managing the certificates, however if you want to manage your own the have a good guide on how to do that.
Expo automatically creates the keystore file, but if you need to create one manually what you want to do is use the
keytool cli utility installed along with Android Studio
keytool -genkey -v -keystore file.keystore -alias YOUR_ALIAS_NAME -storepass YOUR_ALIAS_PWD -keypass YOUR_ALIAS_PWD -keyalg RSA -validity 36500
In order to build locally for Android using turtle-cli
export EXPO_ANDROID_KEYSTORE_PASSWORD=<android-keystore-passwd>
export EXPO_ANDROID_KEY_PASSWORD=<android-key-passwd>
turtle build:android --keystore-path /path/to/your/keystore.jks --keystore-alias PUT_KEYSTORE_ALIAS_HERE
When building for iOS things get a bit more convoluted, I am not a big fan of the way OSX works in the sense that everything requires yet another type of certificate. This adds a lot of noise on top of the real developer work.
In order to build a binary .ipa
export EXPO_IOS_DIST_P12_PASSWORD=<dist_p12_password>
turtle build:ios --team-id YOUR_TEAM_ID --dist-p12-path /path/to/your/dist/cert.p12 --provisioning-profile-path /path/to/your/provisioning/profile.mobileprovision
Uploading to Play Store and AppStore:
The most DevOpsy thing we could and should do is try and add a build pipeline to the mix. In order to be able to build
iOS you will have to use OSX capable machines to build the .ipa.
A good template has been published by the good folks at expo and you should be able to build on top of this to get your own pipeline up and running. A word of caution though you should figure out which alternative is the most cost effective depending on your release cycles. Building your own may seem quite glamorous and technically challenging but may not be the most cost effective every time.
You can publish your binary via Expo and also manually to the respective stores.
npx expo upload:android
npx expo upload:ios --apple-id <apple-id>
Android and Apple have different release cycles in that in order to publish new apps you need to have your app reviewed. This can be a lengthy process and can cause unwanted dealys in your release cycle. This becomes even nastier when you have updates in your API. This becomes difficult to manage and somewhat unsustainable.
If you use expo publishing and you upload the builds to the store then there will be a really cool thing that I haven’t mentioned so far. The JS bundles can be published and you will see the updated version when you open the app again.
This is by far one of the biggest benefits you get when using react-native, you are not always subject to the
timeline on which customers choose to update their apps.
