We create mobile apps using React Native, which allows us to write the app in JavaScript, and have it compiled to native iOS and Android apps. More specifically, we use Expo. Expo removes all the headache of managing three separate projects (JS, iOS, Android), while also offering an abstraction over builds and updates.
Use the following commands to start a project:
Create 'my-app': yarn create expo my-app
Move into the folder: cd my-app
Install packages: yarn
Expo won't install TypeScript by default, so we have to add it. To do it, we just need to create an empty tsconfig.json file at the root of the project. Once that's done, Expo will automatically detect that the file exists and install the necessary TypeScript dependencies.
touch tsconfig.json
yarn start
You can use this tsconfig template:
{
"extends": "expo/tsconfig.base",
"compilerOptions": {
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"baseUrl": ".",
"paths": {
"@/*": ["*"]
}
}
}
At this point, your project only exists locally, so we need to link it to our Expo account, so that we can enjoy the other Expo services.
Go to Expo.dev and create a project
Link code to project with eas init --id [ID] (you can find the project ID in the project page)
Expo has EAS, which is the platform through which we create builds and push updates. To use it, we need to configure the services.
In the terminal, log into your Expo account. eas login
Configure EAS Build eas build:configure (this will create an eas.json file with the default configuration)
Add "autoIncrement": true to eas.json build.production to make sure Expo autoincrements the build version for new builds
Add channels to each build profile . It should look like this:
{
"cli": {
"version": ">= 3.15.1"
},
"build": {
"development": {
"developmentClient": true,
"distribution": "internal",
"channel": "development"
},
"staging": {
"channel": "staging",
"autoIncrement": true
},
"production": {
"channel": "production",
"autoIncrement": true
}
},
"submit": {
"production": {}
}
}
Create a staging build using the following command eas build --profile staging. This command will:
Android:
ask what Android application id you want to use
if you'd like to install expo-updates. Say yes.
ask if you want to generate a new Android Keystore. Say yes.
iOS:
ask what iOS bundle identifier you want to use
if you want to log in to your Apple account. Do it.
choose the proper team and provider
it'll ask you to generate a new Apple Provisioning Profile. Say yes.
We want to have two different builds available at all times: one of them to receive staging updates, and one to receive production updates. The staging one will be the one we make available for TestFlight users, and the production one is the one that actually gets promoted to production. The staging build should never be promoted to production.
Ideally, we should have a different icon for the staging app, and also update the name to start with "[BETA]". This will make it very clear which builds are the testing ones. You make those changes on app.json.
After that's done, every time you want to release new code, you just have to run eas update --channel [production | staging]. The staging and production builds will get only the updates pushed to that channel.
There are three types of versions: App version, build, and code version.
App version: the version of the app that is gonna be released in the stores. iOS and Android versions should always match. Updated on new builds (doesn't have to be on every build).
Build: This are independent numbers for iOS and Android. Each time there's a new build for one of the platforms, this number needs to be updated
Code version: the actual version of the JS bundle code. This is updated every time new features or bug fixes are released.
These are changes that involve adding or removing native packages. Basically any changes to native code.
Do changes on a feature branch
Merge changes to development
When ready for staging:
Update app.json with a new version. Also make sure the name says "BETA" and the icons being used are the staging ones.
Create the new build with eas build --profile staging. (Once the builds are done, upload them to the stores)
Undo the changes to app.json but keep the new version
Commit with message Create build [version]
Merge changes to staging
When ready for production:
Merge from staging to main
Create the new build with eas build --profile production. (Once the builds are done, upload them to the stores)
Do changes on a feature branch
Merge changes to development
When ready for staging:
Create new code version with yarn version (This will update the version on package.json and create matching tagged commit)
Merge changes to staging
Push a new update to staging with eas update --channel staging
Tell testers to test staging version
When ready for production:
Merge from staging to main
Push a new update to production with eas update --channel production