How to publish an Expo App to the Stores with Release Channels
Let’s demystify the release channels!
In 2017 when I started developing apps for myself using Expo, all I wanted was to have an app live on the App Store & the Play Store.
What I thought was the quickest way to do it back then was Git push master 😮, no branch, no pull request, no staging ENV. When the app was ready, I had to build it for Apple & Android using the Expo CLI. Finally, with my .apk and .ipa in my hands, I could publish it by going through the very long and stressful review process of the App Store and the Play Store (this is a whole other topic). And it worked.
A few days later, let’s say I have a bug to fix or a feature I want to add. How was I doing it? I had to repeat the same process all over again. So I was doing the changes, pushing on master, building the standalone app and submitting it to the Stores so that the users could see the new version a few days later (provided that the App Store review is accepted). Oh, and they could only see the changes if they had updated my app on their phone!
But wait a moment. That is not what was happening. The users had access to the new version instantly. How was that possible?
I did some googling and I came across OTA updates (OTA stands for Over The Air). What is that?
OTA updates allow you to publish a new version of your app JavaScript and assets without building a new version of your standalone app and re-submitting to app stores
Wow, ok, that was something new for me back then! So Expo is telling me that to make changes on my app I can just write a command and people will see it instantly? That seems like a dream when you usually have to wait a few days to (maybe) get an approval!
How does OTA works? To put it short, you can do any change you want in your javascript app and just write the expo publish command. Then your app will be minified and 2 versions of your code (iOS & Android) will be uploaded to the Expo CDN.
Ok, but what does it have to do with my users’ app on their phone? Good question! What Expo wrote in the documentation is:
By default, Expo will check for updates automatically when your app is launched and will try to fetch the latest published version. If a new bundle is available, Expo will attempt to download it before launching the experience.
That’s it! Each time your user opens the app, Expo will check and fetch the latest version of your code that you uploaded with the command expo publish (more details here)! So there is no need to upload a new standalone build of your app and to go again through the process of review for each Store! (however, there are a few exceptions that you can find here)
This discovery for me was mind blowing! I started using it right away! What a pleasure to fix something and see it available directly on my users’ phones!
Ok Julien, but what about release channels?!
Let’s get back to them! How did I come across release channels and why OTA updates were not enough by themselves for me? A year ago, I had a freelance project for a client. It was an app which was already live on the Stores and needed to be improved by adding some features/design & bugs fixes. They also needed a way to see the version I was working on, like a staging ENV (they didn’t have one at the moment).
I couldn’t write expo publish to show them the WIP because it would have impacted the users. And that is when I came across release channels! You can think of them like different servers where you can upload your app, each with a specific name. So for example, when you write expo publish , you can also add the flag —release-channel (eg: expo publish —release-channel staging ) and this way, your app is published to this specific channel. You can add as many channels as you want.
Imagine this simple workflow:
- A production version of your app which is available on —release-channel production
- A staging version which is available on —release-channel staging
But how will the users get the right version on their phone?
Let’s say you want to build an app and upload it to the Stores, you do expo build:android or expo build:ios , right? By default, Expo will automatically add a channel for you which is the default one.
Remember OTA updates? So the freshly new produced binary will only pull updates published over the default channel. This way, each time you publish your app with expo publish (without specifying a channel), expo will publish it on the default channel and your user will have access to the new version.
We can also improve this workflow by adding different channels! From now on, instead of publishing without specifying a channel, you can publish a production version of your app with the command expo publish —release-channel production . This new build will subscribe to the production channel and listen for new updates.
You just need to upload it to the Stores the first time.
Now, imagine you want to work on a new version of your app and show it to some test users without messing with the live production version.
You simply need to create another channel, let’s say expo publish —release-channel staging and build a new binary that will subscribe to this specific staging channel (you can upload this build on Testflight for example and each time you will publish new changes on this channel, your Testflight users will be able to see the Work In Progress! For Android, you can upload this binary on a test release).
When you are happy with your staging app, there is no need to create a new built. You can deploy your changes on the production app by promoting the release to a new channel.
What!? Each time you publish your app, 2 things are created:
a release, identified by a publicationId for Android and iOS platforms. A release refers to your bundled source code and assets at the time of publication.
a link to the release in the staging channel, identified by a channelId . This is like a commit on a git branch.
In order to see everything that you’ve published, just do expo publish:history . You will see something like this:
Let’s get back to the promotion! If you want to promote your staging app to the production one, you just have to identified the publicationId you want to promote and do expo publish:set —publish-id
That’s it, your changes are now live in production ! You can do expo publish:history again to see that the channel has changed!
What if you added a big regression to your users doing that?
No need to worry, just rollback the promotion channel doing expo publish:rollback —channel-id (Be careful, you rollback the channelId , not the publicationId 😉)!
This is as simple as that, your release will be back to the staging channel 🙂
You can imagine any workflow that suits your needs, for example the one with multiple production channels corresponding to different versions of your app where you can maintain each version separately!
One more thing!
Now that you know pretty much everything there is to know about release channels, how about accessing channels directly in the code?
For example, this could serve to set ENV variables based on the channel. You can access this info in the releaseChannel field in the manifest object.
Here is the Expo example:
You can create a function that looks for the specific release and sets the correct variable.
If you are curious to know more about release channels, I invite you to look at the Expo documentation: Release channels & Advanced release channels.
By the way, if you have any question or if I missed something, please don’t hesitate to let me know in the comments below!
If you are interested about my next articles, don’t forget to follow me here 😉
Источник
Build Standalone Expo .apk and .ipa with Turtle CLI
February 05, 2021 — 16 min
This article was updated on February 05, 2021.
A great way to start writing React Native applications is to use Expo. You don’t even need to setup a development environment to get started thanks to Snack, an online React Native application editor. Your application is public by default. Sharing has never been that easy.
Brown turtle swimming underwater, Photo by Wexor Tmg on Unsplash
However, you would like to share an application exclusively with some people, not through an app store or any public channel. One possibility is to share the built application file, e.g. an .apk file for Android and an .ipa file for iOS.
Expo is so great a service (oh, and did I mention free?) that they offer you to publish your app on their servers and if you wanted to build these .apk and .ipa files, you could do so on their servers.
The flow looks like:
and you obtain a nice URL to the artifact created for you when the build finishes.
But, again, this is public. On a server you don’t control. (Although, if you made the same mistake as I did, a ticket to their support can delete any files you had wished to keep private. 🥇)
Luckily for you, Expo provide the tools they are using on their servers for free (did I mention they’re great!?). The build process relies on a CLI tool called turtle-cli . It is open-source and available on GitHub.
Let us go through an example of how to create your application file without resorting to Expo servers. That means you can keep an application private and also build your application while being offline.
The following instructions assume you have bash and Node.js available. In my experience, using the current LTS version of Node.js (version 14.15.4) works best.
Caveat: I could not complete the iOS instructions to the end since I do not have an Apple Developer paid account.
We will go through the following steps:
A condensed version of these steps without much explanation or context is available on the accompanying GitHub repository.
To install Turtle CLI, run
This will make command turtle globally available on your system. To verify it was correctly installed, let’s print the version:
2. Create a dummy application
Let’s create a dummy application using Expo CLI. In your terminal, run
It will ask you a few questions:
The blank template is enough for us.
If you have yarn installed, Expo will use it by default to install dependencies. You can use the —npm flag in the init command if you’d prefer to use npm instead.
Once it’s done setting up your project, you should see the following output in the terminal:
Let’s verify the generated boilerplate works:
To finish setting up the dummy application, you need to configure the app.json file because some configuration keys must be specified to build a standalone app.
If you would like to know more about these standalone app specific configurations, check Expo’s documentation for iOS and for Android.
For this tutorial, it is only necessary to specify the keys «bundleIdentifier» under «ios» , and «package» under «android» in your app.json file:
3. Publish Expo app on local server
Expo has this notion of app publishing: it allows you to share a link or QR code to Expo’s website and anyone can run your app through the Expo app on their devices.
Having your app published is also necessary for over-the-air (OTA) updates, allowing seamless updates to your application, and to publish your application (i.e. building your application files on Expo servers).
You would typically run
and your app would then be available at https://expo.io/ /NAME>.
To have your Expo app “published” on your local server (and avoid public publishing on Expo servers), you will use a different command:
The —dev flag is necessary because you will use a non-https server to publish your Expo app. Note that this prevents you from using OTA updates.
Your server does not need to be running for this step, but you do need to know which local URL you are going to use in advance. This tuorial assumes you will run a local server at http://127.0.0.1:8000.
You can now export the app:
This command will create a dist directory containing the iOS and Android JavaScript bundles and the different assets you are using.
You can now serve the dist directory on your web server, e.g.
Note: if for some reason you need to re-export your application (because you modified your app.json file since the last export, for instance), you must first remove the dist directory:
4. Create APK file — Android
First, verify that your local server is running. For example, you should see a similar output:
For Turtle CLI to work correctly to create an .apk file for Android, you need to make sure the following dependency is installed: Java Development Kit (version 8).
If you know which Expo SDK version you are going to use, you can run
This will take some time:
In the meantime, you can move on to the next section.
4.2. Create Keystore
Just like any other Android app, this app must be signed with some security certificates. In Android-land, as far as I understand, it’s called a keystore. The instructions to create such a keystore file are available on the Android Developers documentation.
Basically, just create a dummy Android project with Android Studio, and then go to Build > Generate Signed Bundle / APK. . Choose APK and press Next . The UI will ask you which app you want to sign, and your dummy app should be pre-selected. On the same screen, press on the button Create new. ; just fill the form and you’re good to go.
Alternatively, if you have keytool CLI utility available on your system (you can check that by trying keytool —help in your terminal), you can generate a keystore file with the following command
As a TL;DR, you can just download a dummy certificate on the accompanying repository under should-be-private/keystore.jks , for testing purposes only. The keystore file is hugely important if you ever plan to submit your app to Google Play store: it’s the only way to assert you’re the rightful owner to provide new updates to your app.
File: keystore.jks
Keystore Password: keystorepassword
Keystore Key Alias: keyalias
Keystore Key Password: keypassword
Make sure that you are serving the dist directory on http://127.0.0.1:8000 as explained above in Run a local server. Assuming you are using bash as your shell, from the root of your project, run:
Note that you need the flag —public-url to point to http://127.0.0.1:8000/android-index.json . In addition, it is also necessary to use the —type apk flag to produce an APK file since version 0.8.0 of turtle-cli .
The build may take some time:
Once it finishes, you should see this output in your terminal:
This message gives you the location of your built .apk file. You can now move on to the Distribute and install section below if you are not interested in creating an .ipa file for iOS.
5. Create IPA file — iOS
First, verify that your local server is running, e.g.
For Turtle CLI to work correctly to create an .ipa file for iOS, you need to make sure your system is macOS and that the following dependencies are installed:
- Xcode (version 11.4 or newer)
- fastlane
Note: make sure that you have run Xcode at least once and that you have agreed to the license agreements.
For more details, see Expo’s documentation.
If you know which Expo SDK version you are going to use, you can run
If it errors out, saying that you don’t have the right version of fastlane , try re-installing fastlane (guide). The version used in this article is fastlane 2.140.0 .
This will take some time:
In the meantime, you can move on to the next section.
5.2. Create Signing keys
This assumes you have an Apple Developer Account, which is a paid account.
To create your distribution certificate file, or .p12 file, you can follow this guide.
You will also need your Apple Team ID and a Provisioning Profile that you can generate through Xcode as well. This other guide covers in greater lengths what all these cerficates are for and how to obtain them.
Note that the provisioning profile expires in 6 days in my case, since I do not have an Apple Developer paid account.
Sadly, it is not possible to share example files.
Make sure that you are serving the dist directory on http://127.0.0.1:8000 as explained Run a local server. Assuming you are using bash as your shell, from the root of your project, run:
Note that you need the flag —public-url to point to http://127.0.0.1:8000/ios-index.json .
Once the build finishes successfully, you should get the path to your .ipa file.
6. Distribute and install
Take your .apk and share it through some Google Drive link or other medium of your choice.
If you download this .apk file through an Android device, it should offer you to install the application on the device.
Trick: if the URL is really not friendly to type, and for whatever reason you have to type it manually, use a QR Code generator (e.g. http://www.barcode-generator.org/) and your device’s camera to simplify your life!
Alternatively, if you connect an Android device to your computer, you should be able to run:
to list all your connected Android devices and emulators. (In my case, only the emulator is “connected”.)
It is then possible to install the .apk file by running:
Caveat: I could not fully test this section, so my apologies if this does not work as intended.
Since you should have Xcode, the most promising solution is in this guide. It also mentions other ways to install the .ipa file.
That’s it for now, thank you for reading this far. You will find below the resources mentioned in this article.
If you have any questions or comments, please drop me a line on Twitter. I shall reply as soon as possible.
Stay tuned for more.
- Expo: https://expo.io
- Turtle CLI: https://github.com/expo/turtle#readme
- Expo’s guide to Building Standalone apps: https://docs.expo.io/distribution/building-standalone-apps/
- Configuring app.json : https://docs.expo.io/workflow/configuration
- Expo docs to configure CI with Turtle CLI: https://docs.expo.io/distribution/turtle-cli
- Expo docs to host application on your own servers: https://docs.expo.io/distribution/hosting-your-app/
- How to create a keystore for Android: https://developer.android.com/studio/publish/app-signing#generate-key
- Supporting GitHub repository: https://github.com/RobinCsl/build-standalone-expo-app/
Personal blog written by Robin Cussol
I like math and I like code. Oh, and writing too.
Источник