Start an App with Ionic + Bower + Grunt

This is my first post so any suggestions are welcome. I’m a DEV at a start-up that recently utilized Ionic to build our Android / iOS app. I will not spend time on what the APP actually does (if you’re interested, feel free to go on app/play store and search “Ola Health”, or just click the hyperlink on the left); this post will serve as a quick guide to how to quickly ramp up a Ionic DEV build combining the power of Ionic, Bower and Grunt.

Ionic is a great framework for building hybrid apps. It sits on top of Cordova (native to JS bridge) and most importantly it provides a set of highly customizable ui components that allow developers to build sophisticated enough mobile applications. Ionic also utilizes AngularJS thus by nature frames developers under MVW pattern which at an high level gives us a good enough separation of concern.

For us, we simply followed the instructions here and started an Ionic project with tabs. For the sake of this guide, we named our project “testApp”:

$ ionic start testApp tabs

The command above creates an empty ionic project with tabs. If you look at the bootstrap page of your Ionic app (testApp/www/index.html), you will notice that the Ionic JS library resides at the location:

<script src=”lib/ionic/js/ionic.bundle.js”></script>

Since the Ionic package is dependent on Bower (check package.json and you should see why), by creating an Ionic app via its CLI, Bower comes with it. Here’s the generated content of bower.json:

“name”: “testApp”,
“private”: “true”,
“devDependencies”: {
“ionic”: “driftyco/ionic-bower#1.0.0-rc.3”

You can find the Ionic version that we are using for our app above. Unsurprisingly (as we’ve seen in index.html), the testApp/.bowerrc tells Bower to copy the Ionic JS into www/lib:

“directory”: “www/lib”

The above allows easy upgrade of Ionic JS via Bower. Whenever a new Ionic version’s out and you’re ready to link to it, simply modify bower.json and run:

bower install

So knowing that Ionic depends on Bower and that Ionic CLI (please note, Ionic CLI is not Ionic JS) creates a bower.json for us (you may choose to add other JS libraries, jQuery, moment, etc…).

Ionic CLI provides a descent enough way to build apps, assuming we are building an Android app:

$ cd testApp
$ ionic platform add android
$ ionic build android

The above builds an APK under testApp/platforms/android/ant-build/CordovaApp-debug.apk

So all is good so far, we go on to modify index.html, add logic to our app, and we build again, except this time, we want our build to run unit tests to ensure minimal code quality...

This is where we have decided to use Grunt to wrap our Ionic build (please note we retained the default Gulp usage of Ionic for sass only).

You may follow the instructions on how to install Grunt here. For us, we use Grunt to execute the following build phases (below are snippets from our /testApp/Gruntfile.js):

grunt.registerTask(‘build’, ‘Build the app’, [‘clean’, ‘setup’, ‘test’, ‘sass’, ‘exec:ionic_build:’ + platform]);

During the setup task, we invoke installation of Cordova plugins and adds the platforms (iOS and Android) we want to build via Ionic CLI.

During the test task, we utilize jshint and jasmine for minimal quality control:

grunt.registerTask(‘test’, ‘Run Javascript test with Jasmine.’, [‘jshint’, ‘jasmine’]);

The sass task itself should be self-explanatory. We simply use the sass Grunt plugin so we recompile our CSS on every build. We then delegate the packaging to Ionic CLI in the exec task:


exec : {
ionic_build : {
cmd : function(platform) {
var getCommand = function(platform) {
var command = ‘ionic build ‘ + platform;
return command;
return getCommand(platform);


Please note platform is an input passed in when we run our Grunt via shell.

Finally, to complete the end-to-end build, we run:

$ grunt build --platform=android

You may choose to add more flavors to your Grunt build such as minifying your JS, etc…

Coming up… How to debug your Android Ionic App, both web (using browser debugger) & natively (Android Studio).

Show your support

Clapping shows how much you appreciated Jeffrey Chang’s story.