Skip to content
Logo Theodo

It’s alive! Get your Ionic app to update automatically (Part 2)

Woody Rousseau4 min read

In part 1 of this tutorial, we learned how you can get your Ionic app to self-update, to deploy new code whenever needed, instead of having to wait up to two weeks for Apple to review your new versions.

Deploy channels

As with web applications, you may want to first deploy features on a test application (often called staging), to also have a preproduction application, or even to have specific versions to test latest large features (A/B testing for instance).

Ionic Deploy handles this need with channels. You can manage your channels on the Ionic Platform Dashboard’s Deploy section. By defaut, the “Production” channel is used and a few others were also already created, but you can create a lot more.

Pushing environment specific updates

To push only to a certain environment, just add the --deploy flag. For instance, if you a have a staging channel, you can simply use

ionic upload --deploy staging

I recommend against using the “Production” channel as it is the one used by default when uploading a new version without specifying a deploy value.

Fetching environment specific updates

Let’s say you have an angular constant channelTag being the tag of the channel. Fetching updates only from this specific channel can be done by adding a single line to the code from the first part of the tutorial. Check this out.

.run(function($ionicPopup, channelTag) {
  var deploy = new Ionic.Deploy();
  deploy.setChannel(channelTag);
  deploy.watch().then(function() {}, function() {}, function(updateAvailable) {
    if (updateAvailable) {
      deploy.download().then(function() {
        deploy.extract().then(function() {
          deploy.unwatch();
          $ionicPopup.show({
            title: 'Update available',
            subTitle: 'An update was just downloaded. Would you like to restart your app to use the latest features?',
            buttons: [
              { text: 'Not now' },
              {
                text: 'Restart',
                onTap: function(e) {
                  deploy.load();
                }
              }
            ],
          });
        });
      });
    }
  });
};

One codebase, several applications

Using a single codebase and being able to hold all the versions of your app simultaneously on your phone can be achieved in a few extra steps:

Let’s start by building a config.tpl.xml file, which is to be the template of the cordova config file. Place it on the root of your project.

config.tpl.xml

<widget xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0" id="<%=appId%>" version="<%=version%>">
  <name><%=appName%></name>
  <description>Updaty is a great app which self updates</description>
  <author email="dev@theodo.fr" href="http://theodo.fr">Theodo</author>
  <content src="index.html"/>
</widget>

A few values are to be injected in the file:

Let’s now create a config.json file (also placed at the root of your project) which will define those values for each environment:

config.json

{
  "staging": {
    "appId": "fr.theodo.updaty-staging",
    "appName": "Updaty Staging"
  },
  "prod": {
    "appId": "fr.theodo.updaty",
    "appName": "Updaty"
  }
}

Generating the environment specific files

A simple gulpfile is enough to generate all the files you need. Pick up the following libraries to start off:

npm install --save-dev gulp-ng-constant gulp-ionic-channels yargs

gulpfile.js

var gulp = require('gulp');
var ionicChannels = require('gulp-ionic-channels');
var ngConstant = require('gulp-ng-constant');

var args = require('yargs').default('channelTag', 'staging').argv;

gulp.task('config', function() {
  gulp.src('./config.json')
  .pipe(ionicChannels({
    channelTag: args.channelTag
  }))
  .pipe(ngConstant())
  .pipe(gulp.dest('./www/js'));
});

Simply running gulp config will generate ./config.xml and ./www/js/config.js for the staging channel tag, and gulp config --channelTag prod will do the same for the prod channel tag.

config.xml (output)

<widget xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0" id="fr.theodo.updaty-staging" version="0.0.1">
  <name>Updaty Staging</name>
  <description>Updaty is a great app which self updates</description>
  <author email="dev@theodo.fr" href="http://theodo.fr">Theodo</author>
  <content src="index.html"/>
</widget>

www/js/config.js (output)

angular.module("config", [])

.constant("appId", "fr.theodo.updaty-staging")

.constant("appName", "Updaty Staging")

.constant("version", "0.0.1")

.constant("channelTag", "staging")

;

gulp-ionic-channels

I made it all easy for you with this gulp plugin I developed, which takes the config.json file as source, adds to it the version from your package.json file as well as the channelTag passed as an argument, and uses it to:

gulp-ng-constant

This useful plugin will generate a javascript file which contains all the angular constants you need from the enriched configuration returned by gulp-ionic-channels, such as the channelTag constant.

Final modifications

You finally need to edit

<!-- your app's js -->
<script src="js/config.js"></script>
<script src="js/app.js"></script>
<script src="js/controllers.js"></script>
<script src="js/services.js"></script>

angular.module('updaty', ['config', 'ionic', 'ionic.service.core', 'updaty.controllers', 'updaty.services'])

You should be good to go!

Liked this article?