CodePush is an App Center Colud service provided by Microsoft that enables React Native / Cordova developers to deploy mobile app updates directly to their user's device without going throuch the google play store / Apple app store and review process. App Center provides other services as well such as
- building
- testing,
- distributing and
- monitoring app in cloud.
Generally react native app in production consist of JSBundle file (i.e is the javascript files with images and other assets) which are bundle together by packager and distributed as part of a platform-specific binary (an .ipa or .apk file). When the app is released, updating either the JavaScript code (for example making bug fixes, adding new features) or image assets, requires you to recompile and redistribute the entire binary, which includes any review time associated with the stores to which you are publishing.
The CodePush plugin helps get product improvements in front of your end users instantly, by keeping your JavaScript and images synchronized with updates you release to the CodePush server. This way, your app gets the benefits of an offline mobile experience, as well as the "web-like" agility of side-loading updates as soon as they are available.
In order to ensure that your end users always have a functioning version of your app, the CodePush plugin maintains a copy of the previous update, so that in the event that you accidentally push an update that includes a crash, it can automatically roll back. This way, you can rest assured that your newfound release agility won't result in users becoming blocked before you have a chance to roll back on the server.
Open a terminal and execute following command to create react native project
npx react-native init CodePushDemo
-
Go to https://github.com and create new repository with name CodePushDemo
-
After that, go to root directory of just created CodePushDemo Pfoject and execute following command
git init git add . git commit -m "first commit" git remote add origin https://github.com/{username}/CodePushDemo.git git push origin master
- Create account or social login (github, facebook, google) in https://appcenter.ms/
-
You manage most of CodePush's functionality using the App Center CLI. Open a terminal and execute the following command
npm install -g appcenter-cli
Before you can begin releasing app updates, you must sign-in with your existing CodePush account or create a new App Center account. You can do this by running the following command once you've installed the CLI:
appcenter login
This command will launch a browser, asking you to authenticate with either your GitHub or Microsoft account. Once authenticated, it will create a CodePush account "linked" to your GitHub/MSA identity, and generate an access key you can copy/paste into the CLI in order to sign-in.
To authenticate against the CodePush service without launching a browser and/or without needing to use your GitHub and/or Microsoft credentials (for example, in a CI environment), you can execute the following command to create an "access token"
appcenter tokens create -d "Azure DevOps Integration"
appcenter login --token <accessToken>
Additional commands
appcenter profile list // View User profile
appcenter logout // logout from app center
appcenter tokens list //View running user session from all the machine
appcenter tokens delete <tokenid> // delete the user session
Create App doc
Before deploying updates, you must create an app with App Center for each platform (iOS and Android)
appcenter apps create -d <appDisplayName> -o <operatingSystem> -p <platform>
appcenter apps create -d AppUpdateDemoIOS -o iOS -p React-Native
appcenter apps create -d AppUpdateDemoAndroid -o Android -p React-Native
If you decide that you don't like the name you gave to an app, you can rename it at any time using the following command:
appcenter apps update -n <newName> -a <ownerName>/<appName>
If at some point you no longer need an app, you can remove it from the server using the following command:
appcenter apps delete -a <ownerName>/<appName>
After you create the deployments, you can access the deployment keys for both deployments using
appcenter apps list
Create deployment key docs
We can create deployment keys for production and staging from below command
appcenter codepush deployment add -a <ownerName>/<appName> Staging
appcenter codepush deployment add -a <ownerName>/<appName> Production
We can get the / pair by running following command
appcenter apps list
// returns rajan.twanabashu-zakipoint.com/AudoUpdatePush
To get the list of deployment keys
appcenter codepush deployment list -a <ownerName>/<appName> --displayKeys
or just this to view deployment metrics appcenter codepush deployment list -a /
To rename or delete deployment keys
appcenter codepush deployment remove -a <ownerName>/<appName> <deploymentName>
appcenter codepush deployment rename -a <ownerName>/<appName> <deploymentName> <newDeploymentName>
Dsipatch release via code push
Once your app has been configured to query for updates against the App Center server, you can begin releasing updates to it.
appcenter codepush release-react -a <ownerName>/<appName> -d <deploymentName>
//e.g.
appcenter codepush release-react -a rajan.twanabashu-zakipoint.com/AudoUpdatePush -d Production
Rollback release update
A deployment's release history is immutable, so you cannot delete or remove an update once it has been released. However, if you release an update that is broken or contains unintended features, it is easy to roll it back using the rollback command:
appcenter codepush rollback <ownerName>/<appName> <deploymentName>
//e.g.
appcenter codepush rollback -a rajan.twanabashu-zakipoint.com/AudoUpdatePush Production
Promote stagging update to production
appcenter codepush promote -a <ownerName>/MyApp-iOS -s Staging -d Production -t "*"
3. Integrating Code Push : docs
Once we have configured the App Center, its time to integrate code-push into the react native application. Execute below command in terminal
npm install --save react-native-code-push
Once you have the CodePush plugin, you must integrate it into the Xcode project of your React Native app and configure it correctly. Code push is not compactible with autolink in react native at this moment. So execute following command to link
react-native link react-native-code-push
or update the Podfile to include
pod 'CodePush', :path => '../node_modules/react-native-code-push'
Finally from root directory install pod dependencues
npx pod-install
//or
cd ios
pod install
Integrate in Xcode project
Open up the AppDelegate.m file, and add an import statement for the CodePush headers:
#import <CodePush/CodePush.h>
Find the following line of code, which sets the source URL for bridge for production releases:
return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
and replace with
return [CodePush bundleURL];
your code should now look like this
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
#else
return [CodePush bundleURL];
#endif
}
Using Deployment Kewy
To let the CodePush runtime know which deployment it should query for updates against, open the project's Info.plist file and add a new entry named CodePushDeploymentKey, whose value is the key of the deployment you want to configure this app against
<key>CodePushDeploymentKey</key>
<string>R7Ms5WZiHbQ4fl4XB4_8HsAhPcm9ky53Ck1Am</string>
CodePush plugin makes HTTPS requests to the following domains:
- codepush.appcenter.ms
- codepush.blob.core.windows.net
- codepushupdates.azureedge.net
If you want to change the default HTTP security configuration for any of these domains, you have to define the NSAppTransportSecurity (ATS) configuration inside the project's Info.plist file:
<plist version="1.0">
<dict>
<!-- ...other configs... -->
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>codepush.appcenter.ms</key>
<dict><!-- read the ATS Apple Docs for available options --></dict>
</dict>
</dict>
<!-- ...other configs... -->
</dict>
</plist>
4. Installing the new update docs
CodePush provides Cordova and React Native developers with multiple options to configure the end users update experience. There are three potential "update modes" or deployment strategies for CodePush updates: Silent, Active, and Custom.
First of all in App.js we need to wrap out app inside CodePush higher order functions to configure the update check frequency.
const codePushOption = {
checkFrequency: CodePush.CheckFrequency.ON_APP_RESUME,
};
............
export default CodePush(codePushOption)(App);
App will check for new update from appcenter server on every resume
To sync and install the available update we will need to add following code which will install the update after 10 seconds of app inactivity in background
CodePush.sync({ installMode: CodePush.InstallMode.ON_NEXT_RESUME, minimumBackgroundDuration: 10}, codepushSyncStatus, null); //10 sec
Here CodePush.sync accept following parameter
- installMode: apply update when the app is resume next time
- minimumBackgroundDuration : after this time of app in background new updates are applied
- codepushSyncStatus: call back function that will show the sync statys
- null : downloadProgress indicator. which we are not using at this moment. So ignore.
Full source code will look like this
import CodePush from 'react-native-code-push'
const codePushOption = {
checkFrequency: CodePush.CheckFrequency.ON_APP_RESUME,
};
const App: () => React$Node = () => {
useEffect(() => {
//app resumes after 10 minutes
CodePush.sync({ installMode: CodePush.InstallMode.ON_NEXT_RESUME, minimumBackgroundDuration: 10}, codepushSyncStatus, null); //10 sec
}, [])
const codepushSyncStatus = (status) => {
console.log("code push sync status", status)
}
return (
<>
<StatusBar barStyle="dark-content" />
<View style={{flex: 1,justifyContent: 'center',alignItems: 'center'}}>
<Text> Rajan Twanabashu</Text>
</View>
</>
);
};
export default CodePush(codePushOption)(App);
Code cleanup
- create codepushwrapper.js
import React, {useEffect}from 'react';
import CodePush from 'react-native-code-push'
const codePushOption = {
checkFrequency: CodePush.CheckFrequency.ON_APP_RESUME,
};
const CodePushWrapper = (WrappedComponent) => {
const WrappedApp = ()=>{
useEffect(() => {
//app resumes after 10 minutes
CodePush.sync({ installMode: CodePush.InstallMode.ON_NEXT_RESUME, minimumBackgroundDuration: 10}, codepushSyncStatus, null); //10 sec
}, [])
const codepushSyncStatus = (status) => {
console.log("code push sync status", status)
}
return <WrappedComponent />
}
return CodePush(codePushOption)(WrappedApp);
}
export default CodePushWrapper
then we can cleanup app.js as following
import CodePushWrapper from './codepush';
const App: () => React$Node = () => {
return (
<>
<StatusBar barStyle="dark-content" />
<View style={{flex: 1,justifyContent: 'center',alignItems: 'center'}}>
<Text> Rajan Twanabashu</Text>
</View>
</>
);
};
export default CodePushWrapper(App);
Now after all the above configuration we can dispatch the new release to appcenter via following command. Then depending on the codepush option your update will be silently installed at client end.
appcenter codepush release-react -a <ownerName>/<appName> -d <deploymentName>